Skip to content

1.1.70: the bug hunt's HIGH findings and three more regressions - #263

Merged
click0 merged 1 commit into
mainfrom
claude/analyze-test-coverage-nCOJW
Nov 6, 2026
Merged

click0 merged 1 commit into
mainfrom
claude/analyze-test-coverage-nCOJW

Conversation

@click0

@click0 click0 commented Nov 6, 2026

Copy link
Copy Markdown
Owner

1.1.70 (continued) — HIGH findings + regressions of 1.1.65–1.1.67

Still version 1.1.70 (not tagged yet): this extends the [1.1.70] CHANGELOG section that #262 opened, no version bump.

Host descriptors leaked into jails (lib/ifconfig_ops.cpp, lib/util.cpp, lib/jail_query.cpp, daemon/ws_console.cpp, lib/status_fd.cpp)

The cached IfconfigOps ioctl socket (UDP, host stack, alive for the life of crated / crate run) had no close-on-exec, and the exec helpers passed every descriptor on. Jexec'ed /etc/rc, ifconfig, ws-console shells and jail_attached commands inherited it. Fixes:

  • SOCK_CLOEXEC on the socket.
  • closefrom(3) in the children of Util::execCommand* / execPipeline, JailExec::execInJail* / spawnInJail and the ws-console shell.
  • The supervisor crated spawns keeps only stdio and fd 3.
  • No allocation between fork and exec in those two daemon children.

devfs rulesets (lib/privops_authz_pure, daemon/privops_handlers.cpp, lib/run.cpp, lib/devices_pure)

apply_devfs_rules deletes and refills the ruleset it names, and the gate looked only at mount_path. A tenant could therefore rewrite ruleset 4 or another tenant's private set. Now:

  • The ruleset must be in 10000..59999 and not in use by a live jail of another caller (DenyForeignDevfsRuleset).
  • crated records every apply_devfs_rules over libnv, root included. A record lasts while that devfs is mounted.
  • An unrecorded set counts as taken while it holds rules.
  • add_devfs_unhide_rule (which writes into whatever set the mount uses) is refused to tenants (DenyDevfsSharedRuleset).
  • crate run steps to the next number on a refusal.

backup-prune (lib/backup_prune_pure)

  • Retention buckets were directory-wide. Without --jail, daily=1 kept one jail's newest stream and deleted the other jails' fulls. They now apply per jail, and an incremental's base must come from the same jail.
  • 65..128-character jail names now parse.

HTTP export (daemon/routes.cpp)

tar --one-file-system, as the CLI export has had since 1.1.48. Shares, the X11 dir, a read-only base, devfs and tmpfs stay out of the archive. Paths come from pathnames.h.

Container name vs kernel name (lib/jail_query, lib/run_pure, lib/lifecycle.cpp, daemon/control_socket.cpp, daemon/routes.cpp, CLI targets)

The kernel name is web_pid4242 (privops) or the jid (root path). The registry and /var/run/crate/<name>.crate use web. Before this change:

  • crate restart stopped the container and then found nothing to start.
  • The control socket's start spawned a second instance next to the running one, and its restart 404'd.
  • The HTTP restart killed the container, then 404'd.

Now:

  • JailQuery::findContainer resolves a kernel name, a jid or a container name. RunPure::containerNameOfJail reads the name off the jail directory for root-path jails. An ambiguous name gets 409.
  • The HTTP routes also pool-check the resolved kernel name.
  • Restart decides what to start before stopping, in all three places. The HTTP restart uses stopCrate.
  • Every CLI target takes the three forms.

tmpfs: [/tmp] hid the X11 socket (lib/run.cpp, lib/mounts_pure, lib/validate_pure.cpp)

A tmpfs at or above /tmp/.X11-unix / /tmp/wayland is now mounted before the X11 setup, which fixes the firefox and chromium profiles. crate validate no longer warns that it hides shares under it.

Third-review regressions

  • crate -p stack up placed --log-progress after run, so no member started. Fixed with StatusPure::crateRunArgv.
  • Status stream: a post-exec failure produced exited + failed. The stream now carries exactly one terminal event.
  • jail_created reported a name no jail had on the root path. It now reports the kernel's name.

Docs / tests

  • Docs updated: crate.5, docs/trust-model en/uk, README en/uk, runbook §4m, CHANGELOG.
  • TODO lists what this left open: in-memory claims across restarts, root-path ruleset collisions, libifconfig sockets in host-side children, snapshot routes / ws-console by kernel name, a dotted --name under jail(8).
  • make test-unit with -Werror: 1602/1602 passed (+10 cases).
  • make check-version and make check-kyuafile pass. mandoc lint shows only pre-existing warnings.
  • The FreeBSD-only files were syntax-checked on Linux. The FreeBSD lite CI job compiles and links them.
  • On-hardware checks are in runbook §4m.

Generated by Claude Code

Folded into 1.1.70 (not tagged yet), on top of #262:

- Host descriptors no longer reach jails: SOCK_CLOEXEC on the cached
  IfconfigOps socket; closefrom(3) in the children of the Util exec
  helpers, JailExec and the ws-console shell; the crated-spawned
  supervisor keeps only stdio and its status pipe.
- devfs: a per-user caller may fill only a private ruleset
  (10000..59999) that no live jail of another caller uses; crated
  records every apply_devfs_rules; add_devfs_unhide_rule is refused to
  tenants; crate run steps to the next number on a refusal.
- backup-prune applies retention per jail; 128-char jail names parse.
- HTTP export: tar --one-file-system, paths from pathnames.h.
- JailQuery::findContainer: targets by kernel name, jid or container
  name (RunPure::containerNameOf / containerNameOfJail); restart in the
  CLI, the control socket and HTTP decides what to start before it
  stops; start no longer spawns a second instance.
- A tmpfs over /tmp is mounted before the X11 setup (firefox/chromium).
- crate -p stack up: --log-progress before `run` (StatusPure::crateRunArgv).
- One terminal event per --status-fd stream; jail_created carries the
  kernel's jail name.

Docs: crate.5, trust-model en/uk, README en/uk, runbook §4m, CHANGELOG,
TODO (what this left open). make test-unit -Werror: 1602/1602.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X6t6tzVypHye5bDGLxzmZK
@click0
click0 merged commit f34fe27 into main Nov 6, 2026
5 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