Skip to content

1.0.0 — remove setuid bit from Makefile install#189

Merged
click0 merged 1 commit into
mainfrom
claude/release-1.0.0
May 12, 2026
Merged

1.0.0 — remove setuid bit from Makefile install#189
click0 merged 1 commit into
mainfrom
claude/release-1.0.0

Conversation

@click0
Copy link
Copy Markdown
Owner

@click0 click0 commented May 12, 2026

Summary

  • Makefile install target: install -s -m 04755 crateinstall -s -m 0755 crate (setuid bit removed)
  • cli/args.cpp version string bumped to crate 1.0.0
  • docs/rootless-migration.md status updated to "1.0.0, setuid removed"; 1.0.0 entry in release-log filled in
  • CHANGELOG.md 1.0.0 entry covering upgrade matrix, rollback procedure, and the 1.x backlog (per-user path leaks not yet wired — see audit findings)

This is a one-line build change. Every other piece of the rootless track shipped in 0.9.0–0.9.30:

Stage Releases
Privops verb taxonomy (JSON wire format) 0.9.0–0.9.7
Per-user namespacing pure modules + audit 0.9.8–0.9.13
libnv listener (FreeBSD-native, getpeereid) 0.9.14
CLI call-site wiring (14 sites, 21 verbs) 0.9.15–0.9.29
Default flip (rootless_per_user: true) 0.9.30
Setuid bit removed 1.0.0 (this PR)

Behaviour change

# 0.9.30
$ ls -l /usr/local/bin/crate
-rwsr-xr-x  ... /usr/local/bin/crate   ← setuid

# 1.0.0
$ ls -l /usr/local/bin/crate
-rwxr-xr-x  ... /usr/local/bin/crate   ← no setuid

crate(1) runs as the operator's uid and talks to crated(8) over the libnv privops socket (/var/run/crate/privops.sock by default). crated MUST be running for crate(1) to function in 1.0.0; the daemon was already required for the 0.9.x track, so this is not a new dependency.

Wire compatibility

No wire changes since 0.9.29. 1.0.0 clients interop with 0.9.30 daemons; bearer tokens, JSON privops, libnv schemas, control sockets, HTTPS API, Prometheus metrics all unchanged.

Rollback

Patch Makefile back to -m 04755 and rebuild, OR pin to 0.9.30. The setuid bit is the only thing that changed between the two; 0.9.30 → 1.0.0 → 0.9.30 is reversible without daemon side-effects.

1.x backlog (not blocking 1.0.0)

From the pre-1.0 audit:

  • lib/network_lease6.cpp IPv6 lease path still hardcoded (IPv4 sibling done 0.9.27)
  • lib/lifecycle.cpp .crate file path hardcoded
  • lib/pfctl_ops.cpp pf lock not per-user
  • lib/stack.cpp DNS dirs hardcoded
  • lib/vm_run.cpp VM + cloud-init paths hardcoded
  • lib/run_net.cpp:446 direct ifconfig -vnet (should use existing SetIfaceUp privops verb)
  • Query-side privops verbs (inspect/doctor/migrate shell out today)
  • Test coverage on impure modules (run.cpp 1810 lines vs run_pure.cpp 24 lines)

These are latent multi-tenant bugs but don't block setuid removal — single-tenant workflows are unaffected.

Test plan

  • FreeBSD CI (lite) green on PR
  • Linux CI green on PR
  • After merge: make install DESTDIR=/tmp/stage && ls -l /tmp/stage/usr/local/bin/crate shows mode 0755 (no s bit)
  • crate --version prints crate 1.0.0
  • Smoke: crate list (as non-root operator with crated running) succeeds
  • Smoke: crate list (with crated stopped) fails with a clear "daemon not running" error

Generated by Claude Code

End of the rootless track. The Makefile install target now
installs crate(1) at mode 0755 instead of 04755; the binary
can no longer self-elevate. Every privileged operation is
delegated to crated(8) via the libnv privops socket (local
clients, getpeereid-authenticated) or the HTTPS API with
bearer tokens (remote clients).

This is a one-line build change. The preceding 31 mini-PRs
(0.9.0 → 0.9.30) staged the verb taxonomy, libnv listener,
per-user namespacing, CLI call-site wiring, and default flip,
so the setuid removal here is a security gate, not a code
rewrite.

Wire-format unchanged. 1.0.0 clients interop with 0.9.30
daemons and vice versa. Suite stays at 1303.
@click0 click0 merged commit 7844561 into main May 12, 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