Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions vminitd/Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion vminitd/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.3.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
.package(url: "https://github.com/apple/swift-system.git", from: "1.4.0"),
.package(url: "https://github.com/apple/swift-system.git", from: "1.6.3"),
.package(name: "containerization", path: "../"),
],
targets: [
Expand Down Expand Up @@ -63,6 +63,7 @@ let package = Package(
dependencies: [
.product(name: "Logging", package: "swift-log"),
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "SystemPackage", package: "swift-system"),
.product(name: "Containerization", package: "containerization"),
.product(name: "ContainerizationOS", package: "containerization"),
"LCShim",
Expand Down
2 changes: 1 addition & 1 deletion vminitd/Sources/vmexec/Console.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// limitations under the License.
//===----------------------------------------------------------------------===//

import Foundation
import FoundationEssentials
import Musl

class Console {
Expand Down
39 changes: 22 additions & 17 deletions vminitd/Sources/vmexec/ExecCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
import ArgumentParser
import ContainerizationOCI
import ContainerizationOS
import Foundation
import FoundationEssentials
import LCShim
import Logging
import Musl
import SystemPackage

struct ExecCommand: ParsableCommand {
static let configuration = CommandConfiguration(
Expand Down Expand Up @@ -56,8 +57,8 @@ struct ExecCommand: ParsableCommand {
}

private func execInNamespaces(process: ContainerizationOCI.Process) throws {
let syncPipe = FileHandle(fileDescriptor: 3)
let ackPipe = FileHandle(fileDescriptor: 4)
let syncPipe = FileDescriptor(rawValue: 3)
let ackPipe = FileDescriptor(rawValue: 4)

let pidFd = CZ_pidfd_open(Int32(parentPid), 0)
guard pidFd > 0 else {
Expand All @@ -79,12 +80,14 @@ struct ExecCommand: ParsableCommand {

if processID == 0 { // child
// Wait for the grandparent to tell us that they acked our pid.
guard let data = try ackPipe.read(upToCount: App.ackPid.count) else {
throw App.Failure(message: "read ack pipe")
var pidAckBuffer = [UInt8](repeating: 0, count: App.ackPid.count)
let pidAckBytesRead = try pidAckBuffer.withUnsafeMutableBytes { buffer in
try ackPipe.read(into: buffer)
}
guard let pidAckStr = String(data: data, encoding: .utf8) else {
throw App.Failure(message: "convert ack pipe data to string")
guard pidAckBytesRead > 0 else {
throw App.Failure(message: "read ack pipe")
}
let pidAckStr = String(decoding: pidAckBuffer[..<pidAckBytesRead], as: UTF8.self)

guard pidAckStr == App.ackPid else {
throw App.Failure(message: "received invalid acknowledgement string: \(pidAckStr)")
Expand All @@ -99,17 +102,19 @@ struct ExecCommand: ParsableCommand {
try pty.configureStdIO()
var masterFD = pty.master

let data = Data(bytes: &masterFD, count: MemoryLayout.size(ofValue: masterFD))
try syncPipe.write(contentsOf: data)
try withUnsafeBytes(of: &masterFD) { bytes in
_ = try syncPipe.write(bytes)
}

// Wait for the grandparent to tell us that they acked our console.
guard let data = try ackPipe.read(upToCount: App.ackConsole.count) else {
throw App.Failure(message: "read ack pipe")
var consoleAckBuffer = [UInt8](repeating: 0, count: App.ackConsole.count)
let consoleAckBytesRead = try consoleAckBuffer.withUnsafeMutableBytes { buffer in
try ackPipe.read(into: buffer)
}

guard let consoleAckStr = String(data: data, encoding: .utf8) else {
throw App.Failure(message: "convert ack pipe data to string")
guard consoleAckBytesRead > 0 else {
throw App.Failure(message: "read ack pipe")
}
let consoleAckStr = String(decoding: consoleAckBuffer[..<consoleAckBytesRead], as: UTF8.self)

guard consoleAckStr == App.ackConsole else {
throw App.Failure(message: "received invalid acknowledgement string: \(consoleAckStr)")
Expand Down Expand Up @@ -144,9 +149,9 @@ struct ExecCommand: ParsableCommand {
} else { // parent process
// Send our child's pid to our parent before we exit.
var childPid = processID
let data = Data(bytes: &childPid, count: MemoryLayout.size(ofValue: childPid))

try syncPipe.write(contentsOf: data)
try withUnsafeBytes(of: &childPid) { bytes in
_ = try syncPipe.write(bytes)
}
}
}
}
12 changes: 2 additions & 10 deletions vminitd/Sources/vmexec/Mount.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import ContainerizationOCI
import ContainerizationOS
import Foundation
import FoundationEssentials
import Musl

struct ContainerMount {
Expand All @@ -36,22 +36,14 @@ struct ContainerMount {
}

func configureConsole() throws {
let ptmx = self.rootfs.standardizingPath.appendingPathComponent("dev/ptmx")
let ptmx = rootfs + "/dev/ptmx"
guard remove(ptmx) == 0 else {
throw App.Errno(stage: "remove(ptmx)")
}
guard symlink("pts/ptmx", ptmx) == 0 else {
throw App.Errno(stage: "symlink(pts/ptmx)")
}
}

private func mkdirAll(_ name: String, _ perm: Int16) throws {
try FileManager.default.createDirectory(
atPath: name,
withIntermediateDirectories: true,
attributes: [.posixPermissions: perm]
)
}
}

extension ContainerizationOCI.Mount {
Expand Down
43 changes: 24 additions & 19 deletions vminitd/Sources/vmexec/RunCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import ArgumentParser
import Cgroup
import ContainerizationOCI
import ContainerizationOS
import Foundation
import FoundationEssentials
import LCShim
import Logging
import Musl
import SystemPackage

struct RunCommand: ParsableCommand {
static let configuration = CommandConfiguration(
Expand Down Expand Up @@ -85,8 +85,8 @@ struct RunCommand: ParsableCommand {

private func childSetup(
spec: ContainerizationOCI.Spec,
ackPipe: FileHandle,
syncPipe: FileHandle,
ackPipe: FileDescriptor,
syncPipe: FileDescriptor
) throws {
guard let process = spec.process else {
throw App.Failure(message: "no process configuration found in runtime spec")
Expand All @@ -96,12 +96,14 @@ struct RunCommand: ParsableCommand {
}

// Wait for the grandparent to tell us that they acked our pid.
guard let data = try ackPipe.read(upToCount: App.ackPid.count) else {
throw App.Failure(message: "read ack pipe")
var pidAckBuffer = [UInt8](repeating: 0, count: App.ackPid.count)
let pidAckBytesRead = try pidAckBuffer.withUnsafeMutableBytes { buffer in
try ackPipe.read(into: buffer)
}
guard let pidAckStr = String(data: data, encoding: .utf8) else {
throw App.Failure(message: "convert ack pipe data to string")
guard pidAckBytesRead > 0 else {
throw App.Failure(message: "read ack pipe")
}
let pidAckStr = String(decoding: pidAckBuffer[..<pidAckBytesRead], as: UTF8.self)

guard pidAckStr == App.ackPid else {
throw App.Failure(message: "received invalid acknowledgement string: \(pidAckStr)")
Expand All @@ -122,17 +124,19 @@ struct RunCommand: ParsableCommand {
try pty.configureStdIO()
var masterFD = pty.master

let data = Data(bytes: &masterFD, count: MemoryLayout.size(ofValue: masterFD))
try syncPipe.write(contentsOf: data)
try withUnsafeBytes(of: &masterFD) { bytes in
_ = try syncPipe.write(bytes)
}

// Wait for the grandparent to tell us that they acked our console.
guard let data = try ackPipe.read(upToCount: App.ackConsole.count) else {
throw App.Failure(message: "read ack pipe")
var consoleAckBuffer = [UInt8](repeating: 0, count: App.ackConsole.count)
let consoleAckBytesRead = try consoleAckBuffer.withUnsafeMutableBytes { buffer in
try ackPipe.read(into: buffer)
}

guard let consoleAckStr = String(data: data, encoding: .utf8) else {
throw App.Failure(message: "convert ack pipe data to string")
guard consoleAckBytesRead > 0 else {
throw App.Failure(message: "read ack pipe")
}
let consoleAckStr = String(decoding: consoleAckBuffer[..<consoleAckBytesRead], as: UTF8.self)

guard consoleAckStr == App.ackConsole else {
throw App.Failure(message: "received invalid acknowledgement string: \(consoleAckStr)")
Expand Down Expand Up @@ -220,8 +224,8 @@ struct RunCommand: ParsableCommand {
}

private func execInNamespace(spec: ContainerizationOCI.Spec) throws {
let syncPipe = FileHandle(fileDescriptor: 3)
let ackPipe = FileHandle(fileDescriptor: 4)
let syncPipe = FileDescriptor(rawValue: 3)
let ackPipe = FileDescriptor(rawValue: 4)

let unshareFlags = try setupNamespaces(namespaces: spec.linux?.namespaces)

Expand Down Expand Up @@ -255,8 +259,9 @@ struct RunCommand: ParsableCommand {

// Send our child's pid before we exit.
var childPid = processID
let data = Data(bytes: &childPid, count: MemoryLayout.size(ofValue: childPid))
try syncPipe.write(contentsOf: data)
try withUnsafeBytes(of: &childPid) { bytes in
_ = try syncPipe.write(bytes)
}
}
}

Expand Down
10 changes: 6 additions & 4 deletions vminitd/Sources/vmexec/vmexec.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@ import ArgumentParser
import ContainerizationError
import ContainerizationOCI
import ContainerizationOS
import Foundation
import FoundationEssentials
import LCShim
import Logging
import Musl
import SystemPackage

@main
struct App: ParsableCommand {
Expand Down Expand Up @@ -233,7 +234,7 @@ extension App {
}

static func writeError(_ error: Error) {
let errorPipe = FileHandle(fileDescriptor: 5)
let errorPipe = FileDescriptor(rawValue: 5)

let errorMessage: String
if let czError = error as? ContainerizationError {
Expand All @@ -242,8 +243,9 @@ extension App {
errorMessage = String(describing: error)
}

if let data = errorMessage.data(using: .utf8) {
try? errorPipe.write(contentsOf: data)
let bytes = Array(errorMessage.utf8)
_ = try? bytes.withUnsafeBytes { buffer in
try errorPipe.write(buffer)
}
try? errorPipe.close()
}
Expand Down