Commit Graph
84 Commits
Author SHA1 Message Date
jwhur b770cd2a02 Add stat RPC (#614)
Add `Stat` RPC to vminitd.

`Stat` RPC is used to stat file system objects in the VM. It accepts the
path to the object (resolved against VM root) and returns the stat
result.
2026-04-27 14:44:33 -07:00
J Logan f1ee6f8b73 Adds journal modes to EXT4.Formatter. (#689)
- Closes #671.
- Adds optional journal parameter to `EXT4.Formatter.init()`, with nil
default specifying the current no-journal filesystem configuration.
Otherwise the parameter value contains the journal size and mode.
- `minDiskSize` parameter for formatter init specifies the minimum
usable capacity of the resulting filesystem. The resulting disk image
grows past this value to accommodate the filesystem on-disk structures,
including the journal if specified.
2026-04-21 12:25:09 -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 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 3c4215702b LinuxContainer/LinuxPod: Sort mounts by depth (#601) 2026-04-03 10:28:47 -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
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 a35b168888 LinuxContainer/LinuxPod: Add support for NoNewPrivileges (#581)
Basically just a direct mapping to the prctl/OCI spec field.
2026-03-14 11:23:22 -07:00
Danny Canter 55c2a0a961 Integration: Sysctl tests (#582) 2026-03-13 13:32:17 -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
Danny Canter 6f9ae02933 LinuxContainer/LinuxPod: Fix UDS proxy if target is symlink (#568)
Closes #256

If the target of the uds proxy goes through a symlink (/var/run) we had
the same bug we had with mounts previously where we'd follow this and if
the resolved path existed in the root of the VM we'd end up mounting
there. Fix this by plopping the sockets in a holding spot and then bind
mounting them in (which has the correct resolution logic).
2026-03-03 10:41:28 -08:00
Yibo Zhuang bacd99619f linux pod: exec process should inherit container's process config (#562)
This change fixes an issue in linux pod where the exec process
does not inherit the container process config which means any
environment variables, working directory, user, rlimits,
capabilities would be different for the exec process.

This change ensures that exec process would inherit
environment variables, working directory, user, rlimits,
and capabilities from the container process config but
resets arguments, terminal, and stdio as those should not
be inherited.

This change also adds an integration test to exercise this.
2026-02-26 21:22:52 -08:00
Danny Canter 205ccc7774 LinuxPod: Add hostname field on pod config (#561)
Just like we have for hosts and dns configurations, we can add a
hostname field to make it easier to setup if every container is going to
be using the same hostname.
2026-02-26 13:41:40 -08:00
Danny Canter 485bb6ec2c Integration: Fix network disable test (#557) 2026-02-25 05:42:23 -08:00
William Tan 0f7e3a5a33 vmexec: Pass through process env for ExecCommand (#550)
This mirrors the logic already in place for RunCommand and will allow
the PATH environment variable to get picked up properly.
2026-02-22 17:09:05 -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
jwhur 185bc1ecd7 vminitd: read errorPipe instead of syncPipe (#547)
ManagedProcess should read errorPipe until EOF to get any error message
from vmexec.
2026-02-21 05:38:46 -08:00
Danny Canter 32cf8c4d32 vminitd: Implement minimal init process to reap zombies (#537)
There are some workloads that benefit from having a "true" init process
that reaps zombies. This change implements a minimal init as part of
vminitd and exposes an API to be able to use this init process in our
containers. signals will be forwarded, any child procs will be reaped
and the exit code of the actual workload will be propagated. The
LinuxContainer/LinuxPod API is a very simple bool to ask to use this as
our init process, and the init simply spawns whatever command you want
as a child underneath this.

```
➜  ./bin/cctl run --kernel bin/kernel.arm64 --init
/ # ps aux
PID   USER     TIME  COMMAND
    1 root      0:00 /.cz-init -- /bin/sh
    2 root      0:00 /bin/sh
    3 root      0:00 ps aux
```
2026-02-20 16:22:36 -08:00
Danny Canter 061bc0a071 LinuxContainer: Add support for optional writable layer (#533)
This adds support to LinuxContainer to be able to provide an optional
writable layer. This is useful as today the rootfs size is determined by
the size of the image block itself which is set in stone at unpack time
of the image. This leaves a lot to be desired because a user might want
a larger or smaller rootfs size, but it's not configurable on a per
container basis because of this. To support this, we can pass an
additional writable block device that we can overlayfs with the image
contents in the guest. All writes will go to this writable layer, and
the rootfs size in the container is now whatever size this writable
layer is.

The block devices (via our ext4 package, but you could use whatever) are
cheap enough to generate on the fly that you can choose whatever size
you want easily.
2026-02-19 15:27:43 -08:00
Danny Canter 39aeac3f19 LinuxContainer/LinuxPod: Support duplicate virtiofs mounts (#522)
If we have the same source we should dedupe these. Previously
virt.framework would yell at us for a duplicate tag because we derive
the tag from hashing the mount source.
2026-02-09 11:06:53 -08:00
J Logan 258ad89d51 Disable pod single file mount test. (#511) 2026-02-02 16:23:57 -08:00
J Logan 3f36cba3bf Align kernel build version with Kata used in container. (#510)
- Also temporarily disable single file integration tests until they're
reliable.
2026-02-02 15:34:58 -08:00
Danny Canter dd60ac3ab7 Add LinuxRLimit type (#499)
I was not a huge fan of how rlimits were specified using the OCI type as
it just takes in strings for the type which isn't super ergonomic. This
adds a new type for rlimits that we can convert to oci type like we
already do for capabilities.
2026-01-29 14:10:39 -08:00
Danny Canter a8758a6ab3 LinuxPod: Add back top-level dns/hosts (#501)
Upon further thought, we should probably support this at the pod level
and allow per container overrides. I've changed my mind on how tedious
it is to specify it on a per-container basis.
2026-01-28 14:23:19 -08:00
Danny Canter db113ffec9 LinuxPod: Support per container dns/hosts (#496)
This shouldn't have been pod level, and we had no way to set hosts today
either. This just exposes hosts and the dns configs per container now.
2026-01-27 10:11:32 -05:00
1a017417bc LinuxContainer/LinuxPod: Single file support (#487)
Fixes #79

This adds support for single file (virtiofs based) mounts to the two
main container types. This is transparent, and doesn't need to be setup
by a user, so there is no visible API change. Virtiofs does not support
single file mounts today, and it would be less than ideal from a
security standpoint to just expose the parent directory of the file to
the vm and then bind mount in the file, so we chose the following:

1. Create a temp directory the container types will manage.
2. Hardlink in the file we want.
3. Share that tempdir into the vm.
4. Finally bind mount in the file into the container.

The main goal I wanted for this is to leave the logic out of the
`VirtualMachineInstance`. I really want this to just be a little dance
the container types do, and leave the vm out of it. Because of that,
most of the logic is shoved in a new `FileMountContext` type that does
the dirty tricks of rewriting what the user asked for to be a bind mount
from a temporary holding spot we'll use in the guest for these temp
directories.

One of the downsides to this is today the tempdirs are solely on the
main volume, so cross volume will need to copy the file to the tempdir,
so writes won't get written back.

Co-authored-by: Dean Coulstock <d_coulstock@apple.com>
Co-authored-by: Jaewon Hur <hurjaewon@snu.ac.kr>
2026-01-22 20:57:58 -08:00
Danny Canter 863380c5e1 Interface: Support custom mtu (#484)
We started the legwork awhile ago, but never exposed it to be
configurable by the container types.
2026-01-20 17:32:28 -08:00
Danny Canter 552d4ce759 Integration: Add simple test filtering (#479)
Just does simple string contains logic
2026-01-17 20:15:54 -08:00
Danny Canter 26f3dcc796 LinuxProcess: Start stdin relay after process start (#478)
Fixes #477

Because we start piping stdin before process launch we can fill up the
guest pipe buffer before the process even starts. We'd need some
backpressure mechanism to handle this and slow consumers (register the
other end with epoll and buffer some data etc.), but we should probably
just start piping after the process is up and running. This change does
exactly that, as well as stops holding the process mutex while draining
stdin in the guest for `CloseStdin()`.

This fixes issues where we try and write > pipe_buf bytes through stdin.
Today this hangs.
2026-01-16 14:14:08 -08:00
Danny Canter 8446f895ee Allow filtering container statistics (#471)
It's possible a user doesn't want the full stats list, and only wants
cpu/mem etc. This plumbs through the ability to filter to only what is
requested. This, while we're already here, adds in memory.event output
to the stats list. For that specifically, I think eventually we may want
a streaming variant of this so you can get alerted of changes in the
file immediately instead of polling/one off reads, but this is useful
for now.
2026-01-13 13:35:00 -08:00
Danny Canter 2f55d75fec Support read only rootfs (#461) 2026-01-02 13:28:44 -08:00
Danny Canter 44ecb87f8d Agent: Add single file copying (#463)
Add a streaming rpc to copy single files in and out. This can easily be
extended to support copying directories, but we need the guest agent to
be able to tar/untar, and we'll need to figure out what that model is.
2026-01-02 08:57:40 -08:00
Danny Canter 7962dae643 Add capabilities support (#444)
Closes https://github.com/apple/containerization/issues/442

This adds capabilities support to LinuxContainer via a new surface in
ContainerizationOS + some C wrappers.
2025-12-11 15:07:17 -05:00
Danny Canter 2d27ef6deb LinuxPod: Wire up pid namespace sharing (#434)
In a prior change I'd added a way for vminitd to double as a simple
pause container. This change wires this up by adding a new bool to the
pod config to ask for pid ns sharing.
2025-12-05 10:42:50 -05:00
Danny Canter 5c190dc4a8 Integration: multipleConcurrentProcesses adjustments (#424)
Remove the prints (To me they're just noise) and stop SIGKILL'ing
the init process and just stop the container.
2025-12-02 10:59:13 -05:00
RahulThennarasu f31d2005b5 ManagedProcess: Capture vmexec stderr and convert to Containerization Error (#411)
Fixes #277

When vmexec fails, it logs to stderr and exits with code 1. Previously,
the error details were lost. This change captures stderr and converts it
into a proper ContainerizationError.

Signed-off-by: Rahul Thennarasu <rahulthennarasu07@gmail.com>
2025-11-19 23:56:09 -08:00
Danny Canter 4c761d50c6 Add new FileHandle option for serial console output (#410)
Taking in a filehandle gives the user quite a bit more freedom on how to
handle boot log output. They can set up a kqueue watch on it and
redirect output somewhere else etc etc. The implementation for this has
us take in a new BootLog type that has two options:

1. .file, which is analogous to what we had prior. Just provide a URL
and a true by default append field.
2. .fileHandle which is the new addition. Can pass any fd that is
writable, and the VMM should write serial console output to it.
2025-11-14 10:40:32 -08:00
Danny Canter b501931267 Integration: Actually run testContainerStopIdempotency (#409)
We (I) forgot to add it :)
2025-11-13 14:37:42 -08:00
Danny Canter c8549315ed LinuxContainer: Keep reference to vended execs (#408)
This change is aimed at making forgetting to call .delete() on a
LinuxProcess less destructive than it can be. Because Virt.framework
invalidates any vsock fds it vended if the vm is stopped, trying to
perform some operations on the grpc client through any of the process
methods could trigger an ebadf, which NIO asserts on. This keeps a
reference to the execs and deletes all of them for you once the
container dies. I still think leaving .delete a public method is useful
as otherwise the stdio fds are left open, but cleanup should occur all
in one place now if you don't care about this.

This additionally:

1. Fixes two of our tests that forgot to delete() an exec.
2. Adds two new tests to verify that process.delete() is now idempotent,
and we don't need to call delete().
2025-11-13 02:13:09 -08:00
Danny Canter 3de29338e1 Integration: Add stdio ingest test (#385)
Add a test to ingest 200MiB of data across stdout/stderr. Useful to test
how fast we can ingest stdio. The timing will always be a tad off as it
times between start and wait returning, and there's quite a lot in the
way.. but it's a good enough metric.
2025-11-07 11:08:01 -08:00
Raj 52ed5b542c Revert "Add filesystem notification (FSNotify) support" (#384)
Reverts apple/containerization#294. This is causing the CI to break
because of concurrency issues with tests. Let's revert while we
investigate.
2025-11-05 15:06:24 -08:00
Raj 80e84a9ce1 Add filesystem notification (FSNotify) support (#294)
Addresses apple/container#141, where containers don't receive filesystem
events on mounted volumes, preventing incremental rebuilds and other
file-watching features. This PR implements the guest-side components for
FSNotify. Host-side implementation in the container repo will complete
the pipeline.

Summary:
- Add gRPC protocol definitions for filesystem event notifications
- Implement guest-side event handler that generates Linux inotify events
- Add CLI testing tool (`cctl fsnotify`) and integration test
infrastructure
2025-11-05 12:20:15 -08:00
Danny Canter f3d998975c LinuxContainer: Add new constructor (#377)
Add a constructor that allows just passing in a configuration without
doing the closure dance.
2025-10-31 14:27:39 -07:00
Danny Canter 07325561f3 Integration: Add UDS test (#374) 2025-10-30 01:00:54 -07:00
Danny Canter cc66529b59 VirtualMachineManager: Take in EventLoopGroup directly (#367) 2025-10-28 02:24:53 -07:00
Danny Canter eb1b8741b5 LinuxContainer/Pod: Remove pause/resume (#366) 2025-10-27 17:33:49 -07:00
Danny Canter ca657f5009 Always provide a serial console (#346) 2025-10-23 14:32:56 -07:00
Danny Canter dc4284a149 Introduce new experimental LinuxPod type (#343)
Closes #319

Introduces a new type capable of running > 1 container in the guest. The
API mostly follows LinuxContainer, and each individual container can be
addressed via any of the methods that require you to pass the
containerID as the first param. Today there's no support for namespace
sharing, but that shouldn't be terrible to support.
2025-10-23 13:59:58 -07:00
Danny Canter 22f7b6ac13 LinuxContainer: Add bootlog as configuration field (#344)
Closes #227

Previously, the bootlog was supplied once in the constructor to
VZVirtualMachineManager which meant that if you used this same manager
for multiple ctrs that all logs would end up going to the same file,
which becomes quite cumbersome to follow..

This change moves bootlog to be a container configuration param and also
moves it to be a VMConfiguration param, so it can be threaded through
from LinuxContainer -> vmm.create() and be truly container unique now.
The largest driver for this was the integration tests which today every
single test spits out logs to a singular file, making guest
investigations tricky to actually look into.

Result after:
```
➜  containerization git:(bootlog-per-ctr) ✗ ls -alh bin/bootlogs
total 1520
drwxr-xr-x@ 24 dcantah  staff   768B Oct 22 17:34 .
drwxr-xr-x@  8 dcantah  staff   256B Oct 22 17:34 ..
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-cat-mount.log
-rw-------@  1 dcantah  staff    22K Oct 22 17:34 test-cgroup-limits.log
-rw-------@  1 dcantah  staff   249K Oct 22 17:34 test-concurrent-processes-output-stress.log
-rw-------@  1 dcantah  staff   167K Oct 22 17:34 test-concurrent-processes.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-container-devconsole.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-container-hostname.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-container-hosts-file.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-container-manager.log
-rw-------@  1 dcantah  staff    22K Oct 22 17:34 test-container-reuse.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-container-statistics.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-container-stdin.log
-rw-------@  1 dcantah  staff     0B Oct 22 17:34 test-nested-virt.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-pause-resume-io.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-pause-resume-wait.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-pause-resume.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-process-custom-home-envvar.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-process-echo-hi.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-process-false.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-process-home-envvar.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-process-true.log
-rw-------@  1 dcantah  staff    11K Oct 22 17:34 test-process-tty-envvar.log
-rw-------@  1 dcantah  staff    38K Oct 22 17:34 test-process-user.log
```
2025-10-23 03:27:24 -07:00
Kathryn Baldauf fa3c348bfe Add close method to IO writer protocol (#336)
Add close method to IO writer protocol and update testing BufferWriter
to conform to the protocol

Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
2025-10-16 14:23:39 -07:00