Skip to content

0.9.29 — rootless: RCTL umbrella auto-apply at create_jail#187

Merged
click0 merged 1 commit into
mainfrom
claude/release-0.9.29
May 10, 2026
Merged

0.9.29 — rootless: RCTL umbrella auto-apply at create_jail#187
click0 merged 1 commit into
mainfrom
claude/release-0.9.29

Conversation

@click0
Copy link
Copy Markdown
Owner

@click0 click0 commented May 10, 2026

Summary

Thirtieth 0.9.x release. The set_loginclass_rctl primitive from 0.9.28 now fires automatically after a successful create_jail privops invocation, sourced from a new rctl_umbrella: block in crated.conf. Operators no longer need a startup-script step to seed loginclass quotas.

What lands

Config schema

rctl_umbrella:
  memoryuse: 4G
  pcpu:      200
  maxproc:   256

Crated::Config::rctlUmbrella (vector of pairs). YAML parser validates each key/value via RetunePure::validateRctlKey / validateRctlValue at load time — bad entries throw at daemon startup, not at first jail-create.

Auto-apply

maybeApplyUmbrella(verb, uid, status) post-hook runs after every libnv-transport dispatch. Fires only when:

  1. verb == CreateJail
  2. uid > 0 (peer creds known — libnv socket only; HTTP path always has uid=0 → no-op)
  3. 200 <= status < 300
  4. g_umbrellaRules non-empty

For each rule: rctl -a loginclass:crate-<uid>:KEY:deny=VALUE via Util::execCommand. Best-effort — rctl failures log to stderr but don't fail the create_jail response (jail is up; losing an umbrella rule is a quota gap, not a correctness break).

Behaviour

# crated.conf has:
#   rctl_umbrella:
#     memoryuse: 4G

# alice (uid 1000) sends create_jail "web1" via libnv socket
# crated:
#   1. handleCreateJail succeeds
#   2. maybeApplyUmbrella fires:
#      rctl -a loginclass:crate-1000:memoryuse:deny=4G
#   3. response 200 returned to client

# alice spawns web2: rule re-applied (idempotent at kernel)
# alice's TOTAL across all jails capped at 4G

# bob (uid 1001): independent crate-1001 loginclass with own 4G cap

HTTP path: no auto-apply

The HTTP transport never has a peer uid (cpp-httplib limitation; 0.9.14 architecture decision). Auto-apply skips on HTTP requests. Operators wanting umbrella on HTTP clients call set_loginclass_rctl manually.

Test plan

  • Suite: 1303/1303 passing
  • daemon/privops_handlers.o, daemon/config.o compile clean
  • FreeBSD CI must pass

No new tests — auto-apply path is daemon-side runtime behaviour requiring real rctl(8). Indirect coverage:

  • rctl_umbrella config parsing tested implicitly via daemon startup on FreeBSD CI (bad config = startup throw)
  • maybeApplyUmbrella mirrors maybeWritePerUserAudit shape (proven from 0.9.13)
  • set_loginclass_rctl validators (0.9.28) cover the key/value path

Series state

CLI call-sites wired (12+). Per-user namespacing fully wired:

  • runtime paths (0.9.8) + per-user lease file (0.9.27)
  • ZFS dataset prefix (0.9.9)
  • network sub-CIDR (0.9.10)
  • RCTL loginclass (0.9.11) + umbrella primitives (0.9.28) + auto-apply (this PR)

Remaining:

  • 0.9.30 — default flip (rootless_per_user: true becomes default in crated.conf.sample)
  • 1.0.0 — setuid bit removed from Makefile install

Generated by Claude Code

Thirtieth 0.9.x release. The set_loginclass_rctl primitive
from 0.9.28 now fires automatically after a successful
create_jail privops invocation, sourced from a new
rctl_umbrella: block in crated.conf. Operators no longer
need a startup-script step to seed loginclass quotas.

Config schema:
  Crated::Config gains rctlUmbrella (vector<pair<key,val>>).
  YAML form:
    rctl_umbrella:
      memoryuse: 4G
      pcpu:      200
      maxproc:   256
  Validated via RetunePure at load time.

Process-global rules:
  Crated::setUmbrellaConfig(rules) registered once at
  daemon startup. main.cpp calls before opening privops
  listener.

Auto-apply in dispatcher:
  maybeApplyUmbrella(verb, uid, status) runs after every
  libnv-transport dispatch. Fires when:
    - verb == CreateJail
    - uid > 0 (libnv path; HTTP always uid=0 → no-op)
    - 200 <= status < 300
    - g_umbrellaRules non-empty
  Runs rctl -a loginclass:crate-<uid>:KEY:deny=VALUE per rule
  via Util::execCommand. Best-effort: failures log to stderr,
  don't fail the create_jail response.

HTTP path skips auto-apply (no peer uid available — 0.9.14
cpp-httplib limitation). Operators wanting umbrella on HTTP
clients call set_loginclass_rctl manually.

Suite stays at 1303 (auto-apply needs real rctl(8)).

Remaining: default flip (0.9.30), setuid removed (1.0.0).
@click0 click0 merged commit 61f367b into main May 10, 2026
2 checks passed
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