Commit Graph
311 Commits
Author SHA1 Message Date
Danny Canter ceee3a67ba vminitd: Lower nio event loop group threads to 1 (#677) 2026-04-10 10:47:22 -07:00
Dmitry Kovba 250546f185 Fix the hardlink count decrement threshold and unlink cleanup (#610)
- Fixes a hardlink count decrement threshold
- Fixes unlinking not freeing the first inode

Resolves the failing added tests:

```
✘ Test hardlinkLinksCount() recorded an issue at TestEXT4Format+Link.swift:43:9: Expectation failed: try EXT4.EXT4Reader(blockDevice: afterUnlink).stat("/original").inode.linksCount == 1
✘ Test hardlinkLinksCount() failed after 0.016 seconds with 1 issue.
```

```
✘ Test unlinkFirstInodeFreesInode() recorded an issue at TestEXT4Format+Link.swift:58:9: Expectation failed: try EXT4.EXT4Reader(blockDevice: path).superBlock.freeInodesCount == EXT4.EXT4Reader(blockDevice: emptyPath).superBlock.freeInodesCount
✘ Test unlinkFirstInodeFreesInode() failed after 0.014 seconds with 1 issue.
```
2026-04-09 15:28:35 -04:00
Dmitry Kovba 2c4012e4e8 Derive the block size from the log block size (#662)
Derives the block size from the log block size.
2026-04-09 15:26:23 -04:00
Dmitry Kovba 3a84f98821 Fix the xattr read loop bounds (#658)
Fixes the `xattr` read loop bounds. Resolves the failing added tests:

> ✘ Test lastXattrNotDroppedAtBufferBoundary() recorded an issue at
TestEXT4ExtendedAttributes.swift:72:13: Expectation failed: (attrs.count
→ 0) == 1
> ✘ Test lastXattrNotDroppedAtBufferBoundary() failed after 0.001
seconds with 1 issue.

> Swift/Array.swift:430: Fatal error: Array index is out of range
2026-04-09 14:09:55 -04:00
Dmitry Kovba b2be8dec67 Remove the incorrect check for visited inodes (#659)
Removes the incorrect check for visited inodes. Fixes the added failing
tests:

> ✘ Test sameAbsoluteSymlinkFollowedTwice() recorded an issue at
TestEXT4Reader+IO.swift:502:6: Caught error: symlink loop while
resolving: target/../symlink/file.txt
> ✘ Test sameAbsoluteSymlinkFollowedTwice() failed after 0.009 seconds
with 1 issue.

> ✘ Test sameRelativeSymlinkFollowedTwice() recorded an issue at
TestEXT4Reader+IO.swift:516:6: Caught error: symlink loop while
resolving: ../target/../symlink/file.txt
> ✘ Test sameRelativeSymlinkFollowedTwice() failed after 0.010 seconds
with 1 issue.
2026-04-09 14:09:07 -04:00
Dmitry Kovba d8ec470b39 Throw an error for non-ASCII xattr names (#657)
Throws an error for non-ASCII xattr names on read instead of crashing at
force-unwrapping.
2026-04-09 13:59:24 -04:00
Dmitry Kovba 757885052b Crash instead of silently truncate on a type overflow (#663)
Crash instead of silently truncate on a type overflow. This change has
no real effect and only improves the code quality.
2026-04-09 13:56:19 -04:00
Dmitry Kovba 74ac944790 Match the byte order in the EXT4 reader to how the EXT4 formatter writes data (#664)
Matches the byte order in the EXT4 reader to how the EXT4 formatter
writes data.
2026-04-09 13:55:27 -04:00
Danny Canter 8451a8427d Single file mounts: Add/fix up some comments (#675) 2026-04-09 10:21:07 -07:00
Dmitry Kovba adce496396 Trim null bytes from the symlink target string (#618)
Trims null bytes from the symlink target string.
2026-04-09 13:19:51 -04:00
Dmitry Kovba 340c31d1d9 EXT4: Fix the construction of the path (#666)
Fixes the construction of the path and removed unnecessary code. Fixes
the added failing test:

> ✘ Test fileTreeNodePathWithAbsoluteRoot() recorded an issue at
TestEXT4Reader+IO.swift:600:9: Expectation failed: (dirPtr.pointee.path
→ /) == (FilePath("/dir") → /dir)
> ✘ Test fileTreeNodePathWithAbsoluteRoot() recorded an issue at
TestEXT4Reader+IO.swift:601:9: Expectation failed: (filePtr.pointee.path
→ /) == (FilePath("/dir/file") → /dir/file)
> ✘ Test fileTreeNodePathWithAbsoluteRoot() failed after 0.001 seconds
with 2 issues.
2026-04-08 22:32:38 -07:00
Danny Canter ab89983c56 Mounts: Change single file mounts to a different approach (#665)
Related to https://github.com/apple/container/issues/1251

Change to sharing in the parent directory, and then bind mounting in the
file into the container. This has the unfortunate reality of being less
secure, but the current approach is burdended by a couple things,
namely:

1. You can't share in files that are on a different volume
2. There is a Virtualization bug that causes spurious errors when trying
to open the file.

I've added a doc to go over the approach we've taken, and some
workarounds if the approach is not satisfactory.
2026-04-08 22:01:13 -07:00
Danny Canter c2552ca399 Epoll: Rework epoll type (#619) 2026-04-08 21:59:41 -07:00
Dmitry Kovba f6e7099cf1 Fix the minimum disk size check comparing bytes to blocks (#670)
Fixes the minimum disk size check comparing bytes to blocks and reduces
the code duplication.
2026-04-08 20:43:59 -07:00
Dmitry Kovba bc287a0f1c Fix the SuperBlock reserved block count field names (#668)
Fixes the `SuperBlock` reserved block count field names.
2026-04-08 20:11:50 -07:00
Dmitry Kovba 4c5c731a99 Fix typos in the code and comments (#673)
Fixes typos in the code and comments.
2026-04-08 20:11:41 -07:00
Dmitry Kovba 50560a33cb Remove unused, duplicated, and outdated private methods (#667)
Removes unused, duplicated, and outdated private methods.
2026-04-08 14:45:18 -07:00
Dmitry Kovba 744a7174c6 Remove not used code in the EXT4 formatter (#656)
Removes not used code in the EXT4 formatter.
2026-04-08 14:45:02 -07:00
Raj 636715513c Add multi-reference push to ImageStore (#661) 2026-04-07 16:41:58 -07:00
Danny Canter 997d5a4b08 Actions: Add Linux build step (#654)
Related to https://github.com/apple/containerization/issues/606

To make sure the project (and many linux specific libraries) builds on
linux lets add a linux step to build for both musl and glibc. Eventually
this will run unit tests as well. This change needs a bit more libc
agnostic-ifying work to make sure things work for both libcs.
2026-04-07 15:13:12 -07:00
Danny Canter a1038a9841 make default goal compile on Linux (#648)
To be able to test vminitd/vmexec/linux specific packages on ci it'd be
a heck of a lot easier if `make` just worked. This should be the last
bit needed. The default goal currently compiles just fine after the
linux specific `make deps` is ran. Next in line would be adding decent
unit tests/actually getting ci setup for the linux bits.
2026-04-06 11:13:16 -07:00
Danny Canter 367c136705 VirtualMachineInstance: Make default impls public (#651) 2026-04-06 10:34:32 -07:00
Dmitry Kovba 56916452e9 Fix the uid/gid truncation to 16 bits (#636)
Fixes the uid/gid truncation to 16 bits.
2026-04-03 19:07:30 -07:00
Dmitry Kovba 33afe9974f Remove the unreachable partial last block group handling in the EXT4 formatter (#640)
Fixes the last block group handling in the EXT4 formatter.
2026-04-03 19:07:17 -07:00
Dmitry Kovba 0273d0dcff Fix a force-unwrap crash on the last leaf of an extent tree (#639)
Fixes a force-unwrap crash on the last leaf of an extent tree:

> ContainerizationEXT4/EXT4+Formatter.swift:1148: Fatal error:
Unexpectedly found nil while unwrapping an Optional value
2026-04-03 19:06:50 -07:00
Dmitry Kovba 587339ae63 Add a guard against an empty range in the EXT4 formatter (#641)
Adds a guard against an empty range in the EXT4 formatter to prevent a
possible crash:

> Swift/arm64e-apple-macos.swiftinterface:6314: Fatal error: Range
requires lowerBound <= upperBound
2026-04-03 19:06:22 -07:00
Dmitry Kovba 586385fb15 Remove not used code which had a buffer overread (#629)
Removes not used `FilePath.init?(Data)` which had a buffer overread. It
used `String(cString:)` which reads until `\0`, but `Data` is not
null-terminated.
2026-04-03 17:07:43 -04:00
Dmitry Kovba b36c63c0b1 Skip deleted directory entries instead of breaking (#637)
Skips deleted directory entries instead of breaking.
2026-04-03 17:06:47 -04:00
Dmitry Kovba 79427211dc Fix a retain cycle in the FileTreeNode class (#638)
Fixes a retain cycle in the `FileTreeNode` class.
2026-04-03 17:01:24 -04:00
Danny Canter 1d60473274 LinuxPod: Remove macOS ifdef (#643)
It compiles fine on non-macOS
2026-04-03 12:31:42 -07:00
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
Dmitry Kovba 11bbbbb852 Support a default route without a gateway (#628)
Adds the support for a default route without a gateway.

```
/ # ip route show default
default dev eth0 scope link 
```
2026-04-02 14:27:56 -07:00
Danny Canter 8615e3b021 Remove more incorrect os gates (#632)
A lot of logic we have works perfectly fine on other OS'.
2026-04-02 10:12:55 -07:00
Danny Canter 4c28821fef LinuxContainer: Move memory clamping to VZ code (#630)
The memory limit (clamp to system ram) is a VZ limitation so it's weird
that we had that logic directly in LinuxContainer. Someone could make a
VZVirtualMachineInstance that doesn't have this limitation but we
inherit this logic because it's done before passing off the memory
amount to the VMM.
2026-04-01 20:17:14 -07:00
Danny Canter baccf3f44b Hash: Make package visibility/remove ifdef (#631)
These build fine on Linux, and I don't honestly know why we had
hashMountSource as public API..
2026-04-01 19:45:53 -07:00
Danny Canter a864456240 ArchiveWriter: Fix uaf in finishEncoding() (#622)
finishEncoding() called archive_free() and then passed the freed pointer
to wrap(), which would call archive_error_string() on it if the return
code was not ARCHIVE_OK. Fix by nil-ing the pointer before freeing and
throwing directly without attempting to read the (already freed) error
string.
2026-04-01 18:29:46 -07:00
Danny Canter 1f495bc5be ArchiveReader: Cleanup tempdirs/files (#623)
There was a couple spots we were leaving around tempdirs
2026-04-01 14:20:44 -07:00
Danny Canter 220042089b Remove LinuxContainer.setupIO (#627)
Dead code
2026-04-01 13:57:43 -07:00
Danny Canter aa6f2c5d6c ContainerizationExt4: Remove unneeded os guards (#626)
There was some platform (darwin) specific guards in this package that
didn't make sense.
2026-04-01 15:07:26 -04:00
Dmitry Kovba d46f6ec92f Fix a range subscript when reading an xattr header (#612)
Fixes a range subscript when reading an `xattr` header.
2026-04-01 09:06:39 -07:00
Dmitry Kovba c28d3f1ba9 Fix a hardlink cycle detection (#611)
Fixes a hardlink cycle detection.
2026-03-30 19:02:54 -07:00
Danny Canter c5c1500eac Remove some unneeded Foundation imports (#613) 2026-03-30 17:00:58 -07:00
Dmitry Kovba 15bbddcaeb Fix the xattr sort comparator (#605)
- Closes #603.
- Fixes the `xattr` sort comparator. For example, when `$0.index >
$1.index` and `$0.name.count < $1.name.count`.
2026-03-30 13:03:37 -07:00
Danny Canter 6444b23f13 Netlink: Support glibc (#600)
- Closes #491.
2026-03-30 10:58:32 -07:00
Dmitry KovbaandRonit Sabhaya bed3705dbb Remove a double-counted offset in large files (#597)
* Removes a double-counted offset in large files. 
* This is the same fix as was suggested previously in 
https://github.com/apple/containerization/pull/462.

Co-authored-by: Ronit Sabhaya <ronitsabhaya75@gmail.com>
2026-03-30 09:50:43 -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
Yibo Zhuang a59ed89421 vmexec: create working directory if it doesn't exist (#591)
This seems like standard OCI runtime behavior, which is to create the
working directory if it doesn't exist.
2026-03-19 22:24:25 -07:00