diff --git a/vminitd/Sources/vmexec/ExecCommand.swift b/vminitd/Sources/vmexec/ExecCommand.swift index fe43a758..545935c2 100644 --- a/vminitd/Sources/vmexec/ExecCommand.swift +++ b/vminitd/Sources/vmexec/ExecCommand.swift @@ -100,7 +100,10 @@ struct ExecCommand: ParsableCommand { try App.applyCloseExecOnFDs() try App.setRLimits(rlimits: process.rlimits) - // set uid, gid, and supplementary groups + // Change stdio to be owned by the requested user. + try App.fixStdioPerms(user: process.user) + + // Set uid, gid, and supplementary groups try App.setPermissions(user: process.user) if process.terminal { diff --git a/vminitd/Sources/vmexec/RunCommand.swift b/vminitd/Sources/vmexec/RunCommand.swift index f08beff2..02246515 100644 --- a/vminitd/Sources/vmexec/RunCommand.swift +++ b/vminitd/Sources/vmexec/RunCommand.swift @@ -109,7 +109,10 @@ struct RunCommand: ParsableCommand { try App.setRLimits(rlimits: process.rlimits) - // set uid, gid, and supplementary groups + // Change stdio to be owned by the requested user. + try App.fixStdioPerms(user: process.user) + + // Set uid, gid, and supplementary groups. try App.setPermissions(user: process.user) if process.terminal { diff --git a/vminitd/Sources/vmexec/vmexec.swift b/vminitd/Sources/vmexec/vmexec.swift index 9a3078b1..ab383ace 100644 --- a/vminitd/Sources/vmexec/vmexec.swift +++ b/vminitd/Sources/vmexec/vmexec.swift @@ -104,6 +104,24 @@ extension App { } } + static func fixStdioPerms(user: ContainerizationOCI.User) throws { + for i in 0...2 { + var fdStat = stat() + try withUnsafeMutablePointer(to: &fdStat) { pointer in + guard fstat(Int32(i), pointer) == 0 else { + throw App.Errno(stage: "fstat(fd)") + } + } + + let desired = uid_t(user.uid) + if fdStat.st_uid != desired { + guard fchown(Int32(i), desired, fdStat.st_gid) != -1 else { + throw App.Errno(stage: "fchown(\(i))") + } + } + } + } + static func setRLimits(rlimits: [ContainerizationOCI.POSIXRlimit]) throws { for rl in rlimits { var limit = rlimit(rlim_cur: rl.soft, rlim_max: rl.hard)