Commit Graph
62 Commits
Author SHA1 Message Date
Aditya Ramani f8c943b44d Write file data in chunks in ContentWriter (#634)
Update the `ContentWriter.create(from url: URL)` method to not load the
whole file in memory when computing its hash and writing its contents
2026-04-03 12:20:12 -07:00
Danny Canter 3c4215702b LinuxContainer/LinuxPod: Sort mounts by depth (#601) 2026-04-03 10:28:47 -07:00
Anthony 35f97f225d Add progress handler for rootfs unpacking (#515)
I've added an optional progress handler for rootfs unpacking so that
consumers can show progress. The Ubuntu image takes about 8 seconds to
unpack on my machine, and I'm developing an app where it would be useful
to show progress in the UI.

Total size is determined in an optional first pass that scans archive
headers. Bytes written are then reported during unpacking. The optional
first pass adds 15 (Alpine) to 115 (Ubuntu) ms to unpacking duration on
my machine, depending on image size.
2026-04-02 17:33:55 -07:00
Maxime Grenu 1951816427 fix(dns): validate nameserver addresses are valid IP addresses (#534)
## What

Add a `DNS.validate()` method that verifies all nameserver entries are
valid IPv4 or IPv6 addresses. The method is called from
`Vminitd.configureDNS()` before applying the configuration.

## Why

Closes #467. Currently, any arbitrary string can be passed as a
nameserver in `DNSConfiguration`, which silently results in an invalid
`/etc/resolv.conf` inside the container. Hostname strings like
`dns.example.com` would be written to resolv.conf but would not work as
nameservers.

## How

- Added `DNS.validate() throws` method in `DNSConfiguration.swift` that
iterates over all nameservers and attempts to parse each as either an
`IPv4Address` or `IPv6Address` (using the existing parsers in
`ContainerizationExtras`)
- Added `import ContainerizationExtras` to `DNSConfiguration.swift` (the
`Containerization` target already depends on `ContainerizationExtras`)
- Called `config.validate()` at the start of `Vminitd.configureDNS()` so
validation happens before any GRPC call

## Testing

Added 6 new unit tests in `DNSTests.swift`:
- ✅ Valid IPv4 nameservers accepted
- ✅ Valid IPv6 nameservers accepted  
- ✅ Mixed IPv4/IPv6 nameservers accepted
- ✅ Empty nameserver list accepted
- ❌ Hostname rejected
- ❌ Invalid address rejected

## Checklist

- [x] Tests added
- [x] No breaking changes to existing API (validate() is a new method,
existing init is unchanged)
- [x] Follows existing patterns (uses ContainerizationExtras IP address
types, ContainerizationError for errors)

Signed-off-by: Maxime Grenu <maxime.grenu@gmail.com>
2026-03-25 02:40:07 -07:00
Dmitry Kovba 59f0a046f2 Fix date and time bugs in EXT4 (#592)
- Fixes EXT4 timestamp encoding for pre-1970 dates
- Fixes EXT4 timestamp decoding for pre-1970 dates
- Fixes the creation date
- Fixes a `UInt32` overflow

Resolves the following failures in the added tests:
```
Swift/arm64e-apple-macos.swiftinterface:38198: Fatal error: Double value cannot be converted to UInt64 because the result would be less than UInt64.min
error: Process '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/libexec/swift/pm/swiftpm-testing-helper --test-bundle-path /Users/Dmitry/Apple/containerization/.build/arm64-apple-macosx/debug/containerizationPackageTests.xctest/Contents/MacOS/containerizationPackageTests --filter encodeNegativeTimestamp /Users/Dmitry/Apple/containerization/.build/arm64-apple-macosx/debug/containerizationPackageTests.xctest/Contents/MacOS/containerizationPackageTests --testing-library swift-testing' exited with unexpected signal code 5
```

```
✘ Test decodeNegativeTimestamp() recorded an issue at TestEXT4Format+Create.swift:100:6: Caught error: not a valid EXT4 superblock
✘ Test decodeNegativeTimestamp() failed after 0.003 seconds with 1 issue.
✘ Suite NegativeTimestampRoundtripTests failed after 0.004 seconds with 1 issue.
✘ Test run with 1 test in 1 suite failed after 0.004 seconds with 1 issue.
```
2026-03-25 02:25:19 -07:00
Danny Canter d8fcd1e9ca Network: Move to standalone type (#584)
The network protocol and VMNetNetwork implementation currently are
housed on ContainerManager even though they are generally useful types
even outside of this easy to use helper type. This change moves them to
not be nested types anymore, as well as exposes a new param on
VMNetNetworks constructor so we can pass the type of network.
2026-03-19 11:33:46 -07:00
Danny Canter 1be13d1d76 LinuxContainer: Support copying directories (#571)
Now that the static linux SDK we use has libarchive linked against it,
we can finally live our dream (/s) of supporting copying directories
in/out a little easier. This was.. kind of annoying. I think the very
simple route of writing archive to guest/host -> streaming over grpc is
simplest, but on the guest end we have a couple problems:

1. The VMs rootfs is read only today always, which is a good thing to me
and I don't want to change if we don't have to.
2. Writing the archive to the containers rootfs temporarily could work,
but it's a bit weird, and the user can make the containers rootfs
readonly which would screw that plan.
3. We could write it to /run or /tmp, but they're tmpfs and dealing with
the headache of the user possibly tarring an enormous dir is one I don't
want to care about.

So, that leaves us with the (truthfully better to me) approach of trying
to write the tar data directly to the host and skipping grpc which kinda
forces us to have a temp spot. Because of that, I made it such that we
pass a port number from host<->guest, and transfer the actual data
(either the single file or tarred dir contents) over the vsock port
instead. The stream is kinda clunky, but it just serves as a means to
exchange metadata and a "we're done" signifier.
2026-03-06 15:30:00 -08:00
Raj e6a5acdff2 Add OCI 1.1 subject, artifactType, and referrers API (#546)
This PR adds OCI Image Spec v1.1 artifact support. It extends Manifest,
Index, and Descriptor with the `subject` and `artifactType` fields, adds
a `referrers()` method to RegistryClient implementing the OCI
Distribution Spec v1.1 referrers API. Also, I've added some unit unit
tests for backward compatibility and roundtrip encpding of all new
fields
2026-02-23 12:09:16 -08:00
Anthony b6b95ac897 Add per-container networking flag to ContainerManager.create() (#549)
This PR adds a `networking: Bool = true` parameter to
`ContainerManager.create()` so callers can opt out of network interface
creation on a per-container basis.

## Motivation

Currently, `ContainerManager.create()` unconditionally allocates a vmnet
network interface for every container (when the manager has a network
configured). Some use cases don't need network access and benefit from
having it disabled to reduce attack surface.

There's no way to achieve this today without either:
- Initializing the `ContainerManager` without a network (which disables
networking for *all* containers)
- Clearing `config.interfaces` in the configuration closure (which
wastes an IP allocation from the vmnet pool since `network.create(id)`
has already been called)

## Changes

- Add `networking: Bool = true` to all three `create()` overloads on
`ContainerManager`
- When `false`, `self.network?.create(id)` is skipped entirely. No
interface is allocated, and no DNS is configured.
- `releaseNetwork`/`delete` remain safe to call regardless, since
`Allocator.release` silently ignores unknown IDs.
- Add unit test `testNetworkingFalseSkipsInterfaceCreation` using the
existing `NilGatewayNetwork` fixture
- Add integration tests `testNetworkingDisabled` and
`testNetworkingEnabled` that create containers through a network-enabled
`ContainerManager` and verify the presence/absence of `eth0` via
`/sys/class/net/`
2026-02-22 17:08:49 -08:00
Maxime Grenu 86171acece ContainerizationOCI: raise Reference name limit to 255 to match OCI spec (#541)
## What

Raise the constant from 127 to 255 in `Reference.swift` and update the
derived `referenceTotalLengthMax` accordingly.

## Why

Closes #453.

The [OCI distribution
spec](https://github.com/opencontainers/distribution-spec/blob/main/spec.md)
states that the **name** component of an image reference (registry host
+ repository path) may be at most 255 bytes. The previous hard-coded
limit of 127 characters incorrectly rejected valid references that used
long registry hostnames or deep path hierarchies.

The old `referenceTotalLengthMax = 255` was also inconsistent: with a
127-char name cap, a 255-char total reference would only allow a very
short tag. The new value is derived explicitly as `nameTotalLengthMax
(255) + separator (1) + tagLengthMax (128) = 384`.

## How

- `nameTotalLengthMax`: 127 → 255
- `tagLengthMax`: new constant (128) documenting the maximum tag length
already enforced by the tag regex (`{0,127}` + leading char = 128
chars).
- `referenceTotalLengthMax`: computed from the two constants above (384)
rather than hard-coded to 255.

## Testing

Added three new cases in `ReferenceTests.swift`:
- ✅ Name of 128 characters (registry + path) — previously rejected, now
accepted
- ✅ Name of exactly 255 characters — at the OCI spec maximum, accepted
- ❌ Name of 256 characters — one over the limit, rejected
2026-02-20 11:37:42 -08:00
Manoj Mahapatra 98391937da Guard against if ipv4Gateway is nil, removed fore unwrap (#524)
- Guarded against ipv4Gateway if nil and throw
`ContainerizationError(.invalidState, ...)` instead of force unwraping
- Added a unit test
`ContainerManagerTests.testCreateThrowsWhenGatewayMissing`
2026-02-10 22:20:03 -08:00
Saehej Kang 3f4eee7d2a [keychain]: add list function + update variable/parameter names (#502)
- Add a `list` function that is needed for the `container registry list`
command
- Updates to `KeychainHelper` and `KeychainQuery` variable/parameter
names
- Updates to test cases
2026-02-04 18:15:30 -08:00
J LoganandAditya Ramani 1b50c817b6 Adds zstd decompression for layer content blobs. (#508)
- Closes apple/container#988.
- macOS libarchive is not built with zstd support, so the workaround in
ArchiveReader is to attempt to decompress every archive as zstd. If
decompression fails, we pass the original archive to libarchive. If it
succeeds, we pass the uncompressed archive.
- Adds blob media type recognition for zstd to EXT4Unpacker. Tested zstd
blob unpack using `image pull tonistiigi/hello-world:zstd-docker`.

Co-authored-by: Aditya Ramani <a_ramani@apple.com>
2026-02-02 13:10:22 -08:00
Aditya Ramani 3a0b79d7fb Check for wildcard when determining if proxy should be bypassed (#497)
The `shouldBypassProxy` method from `ProxyUtils.swift` did not account
for `NO_PROXY` entries of the form `*.host.com`
This PR adds an additional check to determine if the proxy should be
bypassed for a given host.
2026-01-28 09:55:45 -08:00
Dmitry Kovba 1d9140cc8a Add a route when a gateway is outside a subnet (#488)
When we set a gateway outside a subnet in Linux, this fails with:
```
ip-route-add-default: netlink response indicates error, rc = -101 
```

To resolve the error, we should first add a route to the gateway outside
the subnet, which this PR does.
2026-01-22 18:57:46 -08:00
J Logan 8da5f2306d Move Bindable to ContainerizationExtras, fix binding bugs. (#481)
- Bindable is generally useful, so it makes sense to move it out of the
netlink library. Removed Equatable conformance from Bindable as this
isn't generally necessary (it's only used for unit tests in netlink).
- Fix some offset checks in a couple data binding functions and improve
the unit tests.
2026-01-21 15:34:10 -08:00
J Logan f570b8734e Fix formatting. (#476) 2026-01-15 11:29:34 -08:00
J Logan 3e93416b9a Merge commit from fork
* Admit only valid OCI layout files when loading image.

- Adds `AdmissionMapper` protocol for validating archive
  member paths and normalizing them to relative paths
  under the extraction root directory.
- Renames `Reader.swift` to `ArchiveReader.swift` to
  match type name.
- Rework `TempDir` to address `NSString.utf8String`
  deprecation warning in Swift 6.2.3.
- Rework `ArchiveReader.extractContent()` to use an
  `AdmissionMapper` to validate and remap archive
   members before extracting.
- Adds `IdentityAdmissionWrapper` for naive extraction.
- Adds `NoSymlinkAdmissionWrapper` that only extracts
  regular files and directories under the extraction root.
- Adds `OCIImageAdmissionWrapper` that only extracts
  valid OCI image layout paths.
- Use `OCIImageAdmissionWrapper` for `cctl image load`
  and print rejected paths.

* PR feedback.

* Adds public init() for TrustedAdmissionMapper.

* Replace AdmissionMapper with more secure extraction.

- Adds FileDescriptor.mkdirSecure() to prevent
  root escapes on member pathnames, and to prevent
  symlink traversal.
- Adds FileDescriptor.unlinkRecursive() to
  facilitate overwrites when there are multiple
  archive entries with the same member path.
- Adds FileDescriptor.validateSymlinkTargetInRoot()
  to validate that extracted symlink targets do
  not escape the root.
- Rewrite ArchiveReader.extractContents() to use
  secure path functions.

* Remove unneeded symlink check, rename files.

* Simplify the lexical normalizer workaround.

* Reject member paths containing parent traversal components.

* Remove unused lexical normalization workaround.

* Fix leaking fds, extract absolute members as relative.
2026-01-15 12:52:02 -06:00
Kathryn Baldauf ec2ee3e94d Update license header on all files to include the current year (#470)
Related to https://github.com/apple/container/pull/1024

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2026-01-05 13:08:48 -08:00
J Logan 452f354bac Adds MACAddress type. (#468)
- Simplifies processing and validation of MAC addresses for
apple/container#1005, where we need to create MAC addresses and
corresponding link local IPv6 addresses.
- Adds Codable for IPAddress and CIDR for apple/container#1006, so we
can parse and relay IP addresses regardless of address family for port
forwards.
2026-01-05 11:31:23 -08:00
Danny Canter cbb48bc0fd vminitd: Strip binaries (#464) 2026-01-01 17:07:14 -08:00
J Logan 9f2742abf4 Handle multiple messages in netlink responses. (#460)
- Closes #459.
- Loop in `parseResponse()` until all data is consumed.
- Add properties to LinkResponse for `isEthernet`, `isLoopback`,
`address`.
2025-12-29 08:06:34 -08:00
Yibo Zhuang dcbc7bf71d Use string representation for CIDR and IPAddress types (#458)
This change adds extension to the CIDR and IPAddress types to implement
custom encode/decode functions for `Codable` conformance to use their
string representation as the output from encode and input to decode.
This would make the output from encoding this type (e.g. JSON) more
human-readable rather than using the internal integer representation.
2025-12-20 17:11:36 -08:00
Yibo Zhuang 5ac406601e Add custom decoder to Linux struct for optional fields (#455)
Allows decoding of minimal OCI specs with empty linux objects by
providing default values for missing fields. Also added unit test to
ensure that empty Linux struct {} works correctly with the fix.
2025-12-19 01:28:02 -08:00
J LoganandAgam Dua 9ba8267afb Use typesafe IP/CIDR parameters everywhere. (#448)
- Closes #445.
- Adopts refined IPv4 and IPv6 types developed
  by Agam Dua <agamdua@users.noreply.github.com>.
- For type safety and clarity, use IP and CIDR types
  where we were previously using String.

Co-authored-by: Agam Dua <agamdua@users.noreply.github.com>
2025-12-16 09:58:44 -03:00
Dmitry Kovba bb0cd39177 Lowercase error messages (#440)
For consistency, all error messages are lowercased.
2025-12-09 05:38:48 -08:00
Danny Canter 836b699a91 Wire up experimental OCI runtime support (#416) 2025-11-21 12:16:58 -08:00
RahulThennarasu 4d47c58a3d Fix: Allow OCI archives without manifest annotations (#397)
Fixes #369

Per the OCI Image Spec, manifest descriptor annotations are optional.
Previously, archives without annotations would fail to import with
"Failed to import image".

**Changes:**
- Modified `getImageReferencefromDescriptor` to return digest-based
references (`untagged@sha256:...`) when annotations are missing
- Removed guard that skipped manifests without annotations
- Added test case with `scratch_no_annotations.tar`

**Testing:**
All 167 tests pass, including new test for images without annotations.
2025-11-15 00:32:15 -03:00
Danny Canter cfe4fd77cb Socket: Return Int32 and not FileHandle for uds receives (#398)
Gives more flexibility. The caller doesn't need to carry around this
FileHandle object if they don't really need it.
2025-11-10 15:48:06 -08:00
Kathryn Baldauf a27fefbb59 Add custom decoder inits for various oci types that use omitempty (#347)
Many fields on the various OCI types use "omitempty" for encoding and
decoding the json representation in golang. This PR adds custom json
decoder functions to allow for behavior similar to "omitempty".

---------

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2025-10-24 15:05:40 -07:00
Danny Canter 4f996d3509 LinuxContainer: Move Process type out of Configuration (#340)
As a first step to making a pod type, move the nested process
configuration out of LinuxContainer.Configuration.Process and into a
standalone LinuxProcessConfiguration type.
2025-10-20 10:52:48 -07:00
Danny Canter 8a34763e40 Socket: Add fd receiving (#330)
Via scm_rights. Useful for supporting spawning runc as an OCI runtime as
that's how the pty is passed to the client.
2025-10-14 15:59:56 -07:00
Danny Canter d18d1186a2 ContainerizationExtras: Add AsyncMutex (#324)
We already have `AsyncLock`, but in some cases it'd be nice to have the
type protect a piece of data that you access through the lock, much like
the Synchronization frameworks new `Mutex` type.

This change adds such a type.
2025-10-09 10:47:35 -04:00
J Logan 2443a245cb Fixes proxy logic in RegistryClient. (#314)
- Closes #255.
- Fixes ProxyUtils so that the environment variable to be used for proxy
selection is determined by the request scheme.
- RegistryClient uses ProxyUtils to get the proxy URL used by the
HTTPClient.
- Tweak hostname resolution error message to avoid misleading output if
the proxy hostname cannot be resolved.
2025-10-09 10:30:49 -04:00
J Logan 995a231348 Removes "all rights reserved" from license header. (#309) 2025-10-03 13:27:59 -07:00
Michael Crosby cb6b78f580 dns config should have options not opts (#303)
Signed-off-by: crosbymichael <michael_crosby@apple.com>
2025-09-29 16:35:58 -04:00
Sidhartha Mani fe227c805e Add IO utilities for traversing dirs and reading files from EXT4 devices (#285) 2025-09-18 09:03:26 -07:00
Harry LiandDmitry Kovba 5fbae0e590 feat: add proxy utility (#288)
Signed-off-by: Harry Li <harrymingh@gmail.com>
Co-authored-by: Dmitry Kovba <dkovba@apple.com>
2025-09-12 11:23:41 -07:00
Danny Canter b422e036da ContainerizationOS: Rework User type (#279) 2025-09-04 18:16:17 -07:00
Eric Ernst f92c0cd8c6 containerization: Add additional tests (#273)
Add additional tests, with varying levels of utility.

Before: Overall Code Coverage: 41.73%
After: Overall Code Coverage: 42.95%

Signed-off-by: Eric Ernst <eric_ernst@apple.com>
2025-08-26 13:13:05 -07:00
Danny Canter 259c841591 ContainerizationExtras: Timeout adjustments (#254)
Three things:

1. Timeout.run today didn't allow a throwing closure.
2. Add a new constructor for Timeout that takes in a Duration directly
so we can be more granular than seconds.
3. Add unit tests because we all love those :)
2025-08-07 14:34:45 -04:00
Dmitry Kovba d512fcb7cc Transition to actors (#225)
Due to the reduced use of the macro, we can now fully transition to
`Mutex`.
2025-07-29 08:10:48 -04:00
Dmitry Kovba 41d41e4ffe Check for supported types in the @SendableProperty macro (#212)
- The `@SendableProperty` macro now checks for supported types to
prevent a misuse with unsupported types like structs, dictionaries, and
arrays
- The new `@SendablePropertyUnchecked` can be used with classes and
enums
2025-07-14 15:08:08 -07:00
Raj ad219fecf1 Make MTU configurable for Netlink (#204)
Here we add the implementation to make MTU value configurable instead of
hardcoding in `linkSet`.
2025-07-08 15:54:57 -07:00
Aditya Ramani b24b72a7e4 Reference image via sha for test (#190)
CI was failing since the test image we use had a tag re-pushed. Pinning
the test to reference the image version by its sha

---------

Signed-off-by: Aditya Ramani <a_ramani@apple.com>
2025-07-01 17:58:40 -07:00
Dmitry Kovba b626d32a48 Fix compilation warnings (#163)
This PR fixes compilation warnings observed in:
```
swift -v --version
Apple Swift version 6.2-dev (LLVM 5fbc818cf26c90b, Swift 2e1897356956e43)
Target: arm64-apple-macosx26.0
/Users/Dmitry/Library/Developer/Toolchains/swift-6.2-DEVELOPMENT-SNAPSHOT-2025-06-17-a.xctoolchain/usr/bin/swift-frontend --version
Apple Swift version 6.2-dev (LLVM 5fbc818cf26c90b, Swift 2e1897356956e43)
Target: arm64-apple-macosx26.0
Build config: +assertions
```
2025-06-24 13:15:44 -07:00
Aditya Ramani 016c80fac0 Better parsing for www-authenticate headers (#155)
There was a bug where the `www-authenticate` header in the HTTP response
from a registry would not be parsed accurately.

Specifically, if the header value had more than one `<space>` character,
the entire header would be ignored. This PR fixes this bug and adds unit
test to detect this in the future.


Fixes https://github.com/apple/container/issues/240
And most likely fixes https://github.com/apple/container/issues/237

Signed-off-by: Aditya Ramani <a_ramani@apple.com>
2025-06-20 15:51:47 -07:00
Alexey Makhov 4a196b6dc2 Adds some context to fetchToken errors (#129)
Fixes https://github.com/apple/container/issues/182 and
https://github.com/apple/container/issues/183

Signed-off-by: Alexey <makhov.alex@gmail.com>
2025-06-17 08:26:46 -07:00
Josh Soref c00ede68c1 fix comment misspellings (#131)
This PR corrects misspellings identified by the [check-spelling
action](https://github.com/marketplace/actions/check-spelling)

The misspellings have been reported at
https://github.com/jsoref/containerization/actions/runs/15662940240/attempts/1#summary-44123291170
The action reports that the changes in this PR would make it happy:
https://github.com/jsoref/containerization/actions/runs/15662940315/attempts/1#summary-44123291367

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2025-06-16 16:06:37 -04:00
Kathryn Baldauf 7c063dfbe4 Remove most uses of env variables for image registries (#100)
When we were testing the repo, we added authentication to most of the
registry tests so that we could access private images. Now that the
images are public, this PR removes the use of REGISTRY_TOKEN and
REGISTRY_USERNAME in tests that no longer require authenticating.

Note: REGISTRY_TOKEN, REGISTRY_USERNAME, and REGISTRY_HOST are still
required in the CI to push images and for a few registry tests. So the
env variables are not completely removed. The variables are only used in
the test tool cctl and in our swift tests.

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2025-06-12 10:16:43 -04:00