Use container's environment when starting the init process (#329)

Fixes an issue first described in
https://github.com/apple/container/issues/740.

Previously the initial process of the container was using vminitd's
environment variables to find the target executable. This PR updates the
code to use the container's configured environment for the initial
process instead. The behavior of an exec in a container should be the
same as before.

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
This commit is contained in:
Kathryn Baldauf
2025-10-13 21:33:18 -07:00
committed by GitHub
parent 6e96cdb3a0
commit e283e023ab
3 changed files with 22 additions and 8 deletions
+12 -5
View File
@@ -21,14 +21,18 @@ import Foundation
public struct Path {
/// lookPath looks up an executable's path from $PATH
public static func lookPath(_ name: String) -> URL? {
lookup(name, path: getPath())
lookup(name, path: getCurrentPath())
}
public static func lookPath(_ name: String, path: String) -> URL? {
lookup(name, path: path)
}
// getEnv returns the default environment of the process
// with the default $PATH added for the context of a macOS application bundle
public static func getEnv() -> [String: String] {
var env = ProcessInfo.processInfo.environment
env["PATH"] = getPath()
env["PATH"] = getCurrentPath()
return env
}
@@ -58,14 +62,17 @@ public struct Path {
}
/// getPath returns $PATH for the current process
private static func getPath() -> String {
public static func getCurrentPath() -> String {
let env = ProcessInfo.processInfo.environment
return env["PATH"] ?? "/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
}
// findPath returns a string containing the 'PATH' environment variable
private static func findPath(_ env: [String]) -> String? {
env.first(where: { path in
public static func findPath(_ env: [String]?) -> String? {
guard let env = env else {
return nil
}
return env.first(where: { path in
let split = path.split(separator: "=")
return split.count == 2 && split[0] == "PATH"
})
+1 -1
View File
@@ -138,7 +138,7 @@ struct RunCommand: ParsableCommand {
try App.setPermissions(user: process.user)
// Finally execve the container process.
try App.exec(process: process)
try App.exec(process: process, currentEnv: process.env)
}
private func execInNamespace(spec: ContainerizationOCI.Spec, log: Logger) throws {
+9 -2
View File
@@ -22,6 +22,7 @@
import ArgumentParser
import ContainerizationError
import ContainerizationOCI
import ContainerizationOS
import Foundation
import LCShim
import Logging
@@ -71,8 +72,14 @@ extension App {
}
}
static func exec(process: ContainerizationOCI.Process) throws {
let executable = strdup(process.args[0])
static func exec(process: ContainerizationOCI.Process, currentEnv: [String]? = nil) throws {
// lookup executable
let path = Path.findPath(currentEnv) ?? Path.getCurrentPath()
guard let resolvedExecutable = Path.lookPath(process.args[0], path: path) else {
throw App.Failure(message: "Failed to find target executable \(process.args[0])")
}
let executable = strdup(resolvedExecutable.path())
var argv = process.args.map { strdup($0) }
argv += [nil]