Skip to content
Open
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
8 changes: 4 additions & 4 deletions Sources/Containerization/LinuxContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,8 @@ public final class LinuxContainer: Container, Sendable {
"/run/container/\(id)/rootfs"
}

private static func guestSocketStagingPath(_ containerID: String, socketID: String) -> String {
"/run/container/\(containerID)/sockets/\(socketID).sock"
private static func guestSocketStagingPath(_ socketID: String) -> String {
"/run/container/sockets/\(socketID).sock"
}
}

Expand Down Expand Up @@ -693,7 +693,7 @@ extension LinuxContainer {
mounts.append(
ContainerizationOCI.Mount(
type: "bind",
source: Self.guestSocketStagingPath(self.id, socketID: socket.id),
source: Self.guestSocketStagingPath(socket.id),
destination: socket.destination.path,
options: ["bind"]
))
Expand Down Expand Up @@ -1030,7 +1030,7 @@ extension LinuxContainer {
let port: UInt32
if socket.direction == .into {
port = self.hostVsockPorts.wrappingAdd(1, ordering: .relaxed).oldValue
socket.destination = URL(filePath: Self.guestSocketStagingPath(self.id, socketID: socket.id))
socket.destination = URL(filePath: Self.guestSocketStagingPath(socket.id))
} else {
port = self.guestVsockPorts.wrappingAdd(1, ordering: .relaxed).oldValue
socket.source = rootInGuest.appending(path: socket.source.path)
Expand Down
8 changes: 4 additions & 4 deletions Sources/Containerization/LinuxPod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -296,8 +296,8 @@ public final class LinuxPod: Sendable {
"/run/container/\(containerID)/rootfs"
}

private static func guestSocketStagingPath(_ containerID: String, socketID: String) -> String {
"/run/container/\(containerID)/sockets/\(socketID).sock"
private static func guestSocketStagingPath(_ socketID: String) -> String {
"/run/container/sockets/\(socketID).sock"
}

private static func guestVolumePath(_ volumeName: String) -> String {
Expand Down Expand Up @@ -659,7 +659,7 @@ extension LinuxPod {
mounts.append(
ContainerizationOCI.Mount(
type: "bind",
source: Self.guestSocketStagingPath(containerID, socketID: socket.id),
source: Self.guestSocketStagingPath(socket.id),
destination: socket.destination.path,
options: ["bind"]
))
Expand Down Expand Up @@ -1057,7 +1057,7 @@ extension LinuxPod {
let port: UInt32
if socket.direction == .into {
port = self.hostVsockPorts.wrappingAdd(1, ordering: .relaxed).oldValue
socket.destination = URL(filePath: Self.guestSocketStagingPath(containerID, socketID: socket.id))
socket.destination = URL(filePath: Self.guestSocketStagingPath(socket.id))
} else {
port = self.guestVsockPorts.wrappingAdd(1, ordering: .relaxed).oldValue
socket.source = rootInGuest.appending(path: socket.source.path)
Expand Down
58 changes: 58 additions & 0 deletions Sources/Integration/ContainerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,64 @@ extension IntegrationSuite {
}
}

// NOTE: Once upon a time our guest agent created any proxied unix sockets at
// a path that contained the container ID in it. The problem here is if the container
// ID is comically long we exceed the max length of a unix domain socket path.
func testUnixSocketIntoGuestLongContainerID() async throws {
let id = "test-unixsocket-long-id-" + String(repeating: "a", count: 40)

let bs = try await bootstrap(id)

let hostSocketPath = try createHostUnixSocket()

let buffer = BufferWriter()
let container = try LinuxContainer(id, rootfs: bs.rootfs, vmm: bs.vmm) { config in
config.process.arguments = ["sleep", "100"]
config.sockets = [
UnixSocketConfiguration(
source: URL(filePath: hostSocketPath),
destination: URL(filePath: "/tmp/test.sock"),
direction: .into
)
]
config.bootLog = bs.bootLog
}

do {
try await container.create()
try await container.start()

let lsExec = try await container.exec("ls-socket") { config in
config.arguments = ["ls", "-l", "/tmp/test.sock"]
config.stdout = buffer
}

try await lsExec.start()
let status = try await lsExec.wait()
try await lsExec.delete()

guard status.exitCode == 0 else {
throw IntegrationError.assert(msg: "ls command failed with status \(status)")
}

guard let output = String(data: buffer.data, encoding: .utf8) else {
throw IntegrationError.assert(msg: "failed to convert ls output to UTF8")
}

guard output.hasPrefix("s") else {
throw IntegrationError.assert(
msg: "expected socket file (starting with 's'), got: \(output)")
}

try await container.kill(.kill)
try await container.wait()
try await container.stop()
} catch {
try? await container.stop()
throw error
}
}

func testNonClosureConstructor() async throws {
let id = "test-container-non-closure-constructor"

Expand Down
1 change: 1 addition & 0 deletions Sources/Integration/Suite.swift
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ struct IntegrationSuite: AsyncParsableCommand {
Test("container memory events OOM kill", testMemoryEventsOOMKill),
Test("container no serial console", testNoSerialConsole),
Test("unix socket into guest", testUnixSocketIntoGuest),
Test("unix socket into guest long container id", testUnixSocketIntoGuestLongContainerID),
Test("unix socket into guest symlink", testUnixSocketIntoGuestSymlink),
Test("container non-closure constructor", testNonClosureConstructor),
Test("container test large stdio ingest", testLargeStdioOutput),
Expand Down
Loading