Vendor apple/containerization with a VM-extensions forwarding patch
Switch the containerization dependency from the github URL to a vendored copy (third_party/containerization, upstream commit 6b7b42ca) referenced by path, so we can carry a small local patch that upstream lacks: LinuxContainer.Configuration gains a `vmExtensions` field forwarded into VMConfiguration.extensions. Upstream already supports VMConfiguration.extensions + the VZInstanceExtension hook, but LinuxContainer — our only entry point — never forwarded them, so there was no way to attach a device (e.g. a memory balloon) to a container's VM. Tests/, docs/, examples/, images/ and the corresponding test targets are trimmed for footprint (we never build the dependency's tests). See PATCHES.md for the full diff vs. upstream and the re-vendoring procedure. Also adds the ContainerizationExtras product to NucleicCore (AddressAllocator, named in the configureVZ signature). Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Copyright © 2025-2026 Apple Inc. and the Containerization project authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if canImport(FoundationEssentials)
|
||||
import FoundationEssentials
|
||||
#else
|
||||
import Foundation
|
||||
#endif
|
||||
|
||||
#if canImport(Musl)
|
||||
import Musl
|
||||
private let _mount = Musl.mount
|
||||
#elseif canImport(Glibc)
|
||||
import Glibc
|
||||
private let _mount = Glibc.mount
|
||||
#endif
|
||||
|
||||
/// `Binfmt` is a utility type that contains static helpers and types for
|
||||
/// mounting the Linux binfmt_misc filesystem, and creating new binfmt entries.
|
||||
public struct Binfmt: Sendable {
|
||||
/// Default mount path for binfmt_misc.
|
||||
public static let path = "/proc/sys/fs/binfmt_misc"
|
||||
|
||||
/// Entry models a binfmt_misc entry.
|
||||
/// https://docs.kernel.org/admin-guide/binfmt-misc.html
|
||||
public struct Entry {
|
||||
public var name: String
|
||||
public var type: String
|
||||
public var offset: String
|
||||
public var magic: String
|
||||
public var mask: String
|
||||
public var flags: String
|
||||
|
||||
public init(
|
||||
name: String,
|
||||
type: String = "M",
|
||||
offset: String = "",
|
||||
magic: String,
|
||||
mask: String,
|
||||
flags: String = "CF"
|
||||
) {
|
||||
self.name = name
|
||||
self.type = type
|
||||
self.offset = offset
|
||||
self.magic = magic
|
||||
self.mask = mask
|
||||
self.flags = flags
|
||||
}
|
||||
|
||||
/// Returns a binfmt `Entry` for amd64 ELF binaries.
|
||||
public static func amd64() -> Self {
|
||||
Binfmt.Entry(
|
||||
name: "x86_64",
|
||||
magic: #"\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00"#,
|
||||
mask: #"\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff"#
|
||||
)
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
/// Register the passed in `binaryPath` as the interpreter for a new binfmt_misc entry.
|
||||
public func register(binaryPath: String) throws {
|
||||
let registration = ":\(self.name):\(self.type):\(self.offset):\(self.magic):\(self.mask):\(binaryPath):\(self.flags)"
|
||||
|
||||
try registration.write(
|
||||
to: URL(fileURLWithPath: Binfmt.path).appendingPathComponent("register"),
|
||||
atomically: false,
|
||||
encoding: .ascii
|
||||
)
|
||||
}
|
||||
|
||||
/// Deregister the binfmt_misc entry described by the current object.
|
||||
public func deregister() throws {
|
||||
let data = "-1"
|
||||
try data.write(
|
||||
to: URL(fileURLWithPath: Binfmt.path).appendingPathComponent(self.name),
|
||||
atomically: false,
|
||||
encoding: .ascii
|
||||
)
|
||||
}
|
||||
#endif // os(Linux)
|
||||
}
|
||||
|
||||
#if os(Linux)
|
||||
/// Crude check to see if /proc/sys/fs/binfmt_misc/register exists.
|
||||
public static func mounted() -> Bool {
|
||||
FileManager.default.fileExists(atPath: "\(Self.path)/register")
|
||||
}
|
||||
|
||||
/// Mount the binfmt_misc filesystem.
|
||||
public static func mount() throws {
|
||||
guard _mount("binfmt_misc", Self.path, "binfmt_misc", 0, "") == 0 else {
|
||||
throw POSIXError.fromErrno()
|
||||
}
|
||||
}
|
||||
#endif // os(Linux)
|
||||
}
|
||||
Reference in New Issue
Block a user