Skip to content

atelet: make durable-dir volumes writable by non-root containers - #1906

Open
Davanum Srinivas (dims) wants to merge 1 commit into
agent-substrate:mainfrom
dims:pr/durable-dir-mode
Open

Davanum Srinivas (dims) wants to merge 1 commit into
agent-substrate:mainfrom
dims:pr/durable-dir-mode

Conversation

@dims

@dims Davanum Srinivas (dims) commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Durable-dir volumes were created 0700, so a container running as a non-root user could not write its own volume. Now 0777, as Kubernetes creates an emptyDir: one actor's containers can run as different users, and the 0700 actor directory above keeps other actors out.

A restore keeps the mode the snapshot recorded, as emptyDir keeps a pod's own chmod. Volumes created earlier stay 0700, fine while every container runs as root. No effect until an image's USER is honored (#1918). Cleanup of files a non-root container leaves behind landed in #1910.

Tests: TestPrepareDurableDirVolume. Exercised on kind with the micro-VM class: uid 65532 writes a durable dir, then suspend and resume.

  • Tests pass
  • Appropriate changes to documentation are included in the PR

@dims

Copy link
Copy Markdown
Collaborator Author

pull Bot pushed a commit to RolfLobo/substrate that referenced this pull request Sep 30, 2026
…agent-substrate#1910)

Follow-up to agent-substrate#1906. Removing a directory entry needs write permission on
the directory that holds it, and with all capabilities dropped uid 0
gets no exemption. A non-root container can create a subdirectory in its
`0777` durable dir; that subdirectory belongs to the container's uid,
typically `0755`, so root cannot empty it. `resetActorDirs` fails after
every checkpoint of such an actor and the suspend never completes. Chmod
first, as the bundle dir does, is no way out: chmod needs ownership or
`CAP_FOWNER`.

Why atelet and not ateom, which already holds the capability: an ateom
that dies before cleanup leaves the files behind and moves the hang to
the next resume on that node. atelet owns the actor directories and
needs it on the crash path either way.

Manifest only, so no unit test. Exercised on kind with the micro-VM
class: uid 65532 writes a durable dir, then suspend and resume. Without
the capability the same run hangs in `SUSPENDING`.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR (none
needed)
@bowei Bowei Du (bowei) added area/node area/security Security related issue/pr area/storage kind/bug Something isn't working / bugfixes labels Sep 30, 2026

@mayawang Maya Wang (mayawang) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this reads well. One question about actors that already have a snapshot.

Comment thread cmd/atelet/main.go
Created 0700, a non-root container could not write its own volume. Now
0777, as Kubernetes creates an emptyDir: one actor's containers can run
as different users, and the 0700 actor directory above keeps other
actors out. A restore keeps the mode the snapshot recorded; volumes
created earlier stay 0700, which is fine while every container runs as
root.
Quentin Bisson (QuentinBisson) pushed a commit to giantswarm/substrate that referenced this pull request Oct 1, 2026
…agent-substrate#1910)

Follow-up to agent-substrate#1906. Removing a directory entry needs write permission on
the directory that holds it, and with all capabilities dropped uid 0
gets no exemption. A non-root container can create a subdirectory in its
`0777` durable dir; that subdirectory belongs to the container's uid,
typically `0755`, so root cannot empty it. `resetActorDirs` fails after
every checkpoint of such an actor and the suspend never completes. Chmod
first, as the bundle dir does, is no way out: chmod needs ownership or
`CAP_FOWNER`.

Why atelet and not ateom, which already holds the capability: an ateom
that dies before cleanup leaves the files behind and moves the hang to
the next resume on that node. atelet owns the actor directories and
needs it on the crash path either way.

Manifest only, so no unit test. Exercised on kind with the micro-VM
class: uid 65532 writes a durable dir, then suspend and resume. Without
the capability the same run hangs in `SUSPENDING`.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR (none
needed)

(cherry picked from commit afb62e1)
Quentin Bisson (QuentinBisson) pushed a commit to giantswarm/substrate that referenced this pull request Oct 5, 2026
…agent-substrate#1910)

Follow-up to agent-substrate#1906. Removing a directory entry needs write permission on
the directory that holds it, and with all capabilities dropped uid 0
gets no exemption. A non-root container can create a subdirectory in its
`0777` durable dir; that subdirectory belongs to the container's uid,
typically `0755`, so root cannot empty it. `resetActorDirs` fails after
every checkpoint of such an actor and the suspend never completes. Chmod
first, as the bundle dir does, is no way out: chmod needs ownership or
`CAP_FOWNER`.

Why atelet and not ateom, which already holds the capability: an ateom
that dies before cleanup leaves the files behind and moves the hang to
the next resume on that node. atelet owns the actor directories and
needs it on the crash path either way.

Manifest only, so no unit test. Exercised on kind with the micro-VM
class: uid 65532 writes a durable dir, then suspend and resume. Without
the capability the same run hangs in `SUSPENDING`.

- [x] Tests pass
- [x] Appropriate changes to documentation are included in the PR (none
needed)

(cherry picked from commit afb62e1)
Comment thread cmd/atelet/main.go
Comment on lines +1545 to +1546
// different users. Chmod, because MkdirAll applies the umask and skips an
// existing directory. A restore then re-applies the mode the snapshot

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 nit 🟢 – The directory can't already exist here. resetActorDirs removes and recreates the durable-dir parent before both Run and Restore call prepareOCIBundles. So the umask is the only reason for the chmod. Consider dropping "and skips an existing directory" here, and the existing-dir half of TestPrepareDurableDirVolume along with its comment.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(we just did some hardening of durdir setup)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/node area/security Security related issue/pr area/storage kind/bug Something isn't working / bugfixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants