Skip to content

Add UID/GID enforcement, pids.max, and OOM isolation (#99 PR 1/6)#100

Merged
powderluv merged 1 commit intomainfrom
users/powderluv/isolation-pr1-setuid
Apr 18, 2026
Merged

Add UID/GID enforcement, pids.max, and OOM isolation (#99 PR 1/6)#100
powderluv merged 1 commit intomainfrom
users/powderluv/isolation-pr1-setuid

Conversation

@powderluv
Copy link
Copy Markdown
Collaborator

Summary

First PR in the bare-metal job isolation series (#99). Adds three foundational cgroup + process controls.

Changes

  1. setuid/setgid — Jobs run as submitting user's UID/GID (not root). Command::uid()/gid() when spurd is root; graceful skip otherwise.
  2. pids.max — Fork bomb protection. Limits processes per job to max(cpus*256, 1024).
  3. memory.oom.group — OOM kills entire job cgroup, not random process.

Works with both bare-metal and container (Enroot-like) paths — cgroup setup happens before process spawn in both cases.

Isolation series roadmap

  1. This PR: setuid + pids.max + OOM
  2. Device cgroup (GPU enforcement at kernel level)
  3. PID + mount namespace
  4. seccomp-BPF syscall filter (from AXIS)
  5. Landlock filesystem restrictions (from AXIS)
  6. Config + CLI integration

Test plan

  • Full test suite passes (0 failures)
  • CI cluster test: submit job as non-root user, verify GPU access works
  • Fork bomb test: :(){ :|:& };: → pids.max kills cgroup

🤖 Generated with Claude Code

First step toward bare-metal job isolation. Three changes to the
executor's cgroup and process setup:

1. **setuid/setgid**: Jobs run as the submitting user's UID/GID
   instead of root. Uses Command::uid()/gid() when spurd runs as
   root. Non-root spurd gracefully skips (current behavior preserved).

2. **pids.max**: Limits total processes per job cgroup to prevent
   fork bombs. Set to max(cpus * 256, 1024).

3. **memory.oom.group**: Kills entire job cgroup on OOM instead of
   a random process. Prevents partial job survival with corrupted state.

These work with both bare-metal and container (Enroot-like) execution
paths since cgroup setup happens before process spawn in both cases.

Closes: part of #99

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Comment on lines +286 to +291
if uid > 0 && nix::unistd::geteuid().is_root() {
use std::os::unix::process::CommandExt;
cmd.uid(uid);
cmd.gid(gid);
debug!(job_id, uid, gid, "job will run as non-root user");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we also log a warning for spurd running as non-root user case that setuid and setgid cannot be performed?

@shiv-tyagi
Copy link
Copy Markdown
Member

Posted a doubt around gpu node permissions in #102.

#102 (review)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants