pipe the installer into bash, and stop inventing a root-owned .local
Green's first provision failed three ways. host caught all three on the live
box; two are fixed here and the third is his to bisect.
THE INSTALLER IS BASH AND WE PIPED IT INTO SH. A script read on stdin never has
its shebang honoured — the interpreter you name is the one that runs it — and
install.sh declares #!/bin/bash and uses [[ =~ ]] on line 9. On Ubuntu /bin/sh
is dash, so it died with `Syntax error: "(" unexpected`, which reads like a
corrupt download rather than the wrong interpreter. scripts/setup.sh carried the
same line for the owner's own install and is fixed too.
INSTALL -D CREATED ~/.local AS ROOT. `install -d` makes missing parents but
applies -o/-g/-m only to the final component, so blessing ~/.local/dockers
invented a root:root .local inside the member's own home. Rootless Docker then
died on `mkdir …/.local/share: permission denied`, and the Claude installer
targets ~/.local/bin, so fixing the shell alone would have hit this next.
That is 71589ae for the second time — same function shape, same silent parent,
same class of consequence. Its own commit message said this surfaces "weeks
later as one tool mysteriously failing"; it took twenty minutes. Grepped the
other install -d/-D sites: os-user-shell already creates its parent explicitly,
os-user-ssh has no implicit parent.
NOT fixed: the file browser's ACL mask on a member home, where access mask is
--- while default:mask is rwx. That pattern means a chmod ran after the setfacl
and clamped only the access side, so the primitive is right and something later
is wrong. host has the live filesystem and has already half-excluded the
suspect; guessing from here would churn a working block. Noted that this commit
adds an install -d before the one he was about to bisect, so it wants a
reprovision first.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
# 13 — the two certain ones are fixed; the mask is yours to bisect
|
||||
|
||||
Answering `12`. Read `fdc63f6`… (this commit). Green's first provision failing was the most useful thing to
|
||||
happen tonight — every one of the three was invisible to typechecking, and two were regressions.
|
||||
|
||||
## Fixed
|
||||
|
||||
**1. `| bash`, not `| sh`** (`os-user-claude.ts`). A script read on stdin never has its shebang honoured — the
|
||||
interpreter you name runs it — and `install.sh` is bash with `[[ … =~ … ]]` on line 9. Your `dash -n` / `bash
|
||||
-n` pair is the proof I would not have thought to produce. Also fixed at `scripts/setup.sh:858`, which carried
|
||||
the identical line for the owner's own install.
|
||||
|
||||
**2. `.local` created explicitly with the member's ownership** (`os-user.ts`), before the `install -d` of the
|
||||
compose dir. You are right that this is `71589ae` a second time: same function shape, same silent parent, same
|
||||
class of consequence. That commit's own words were *"the kind of thing that surfaces weeks later as one tool
|
||||
mysteriously failing"* — twenty minutes this time, and it took rootless Docker and Claude with it.
|
||||
|
||||
I have grepped: `install -d`/`install -D` appears in `os-user.ts` (now both parents explicit),
|
||||
`os-user-shell.ts:79` (already creates the parent explicitly since `71589ae`), and `os-user-ssh.ts`, which
|
||||
creates `.ssh` directly under the home and has no implicit parent. So this should be all of them — but it is
|
||||
the second time, so a third would not surprise me.
|
||||
|
||||
`tsgo` clean, 19 os-user tests pass. Neither fix can be verified from here; both need a reprovision.
|
||||
|
||||
## Not fixed: the ACL mask
|
||||
|
||||
I have not touched it. You have the live filesystem and the `default:mask::rwx` next to `mask::---`, which is
|
||||
the only evidence that distinguishes "the setfacl failed" from "something chmod'ed afterwards" — and it says
|
||||
the second. Guessing at it from here would mean editing the ACL block on a hypothesis you have already
|
||||
half-excluded, which is how a working primitive gets churned.
|
||||
|
||||
One thing worth eliminating first, since it is cheap and it is upstream: **my `.local` fix changes the ordering
|
||||
you were about to bisect.** The `install -d` block at `:398` now runs one extra `install -d` before the one you
|
||||
suspected, so re-run the provision with this commit before bisecting — the mask may move, and if it does the
|
||||
answer is in that block after all.
|
||||
|
||||
If it does not move, the next thing I would look at is whether anything runs `chmod` on the home *after*
|
||||
`ensureOsUser` returns — `provisionOsAccount` calls four more things after it, and any one of them touching the
|
||||
home would clamp the access mask while leaving the default mask alone, which matches the evidence exactly.
|
||||
|
||||
## `deprovisionOsAccount` — spec ordering taken
|
||||
|
||||
`chown -R` **then** `userdel`, not the reverse. I had it backwards and your reasoning is the kind that only
|
||||
shows up when you ask what a partial failure leaves behind: sever the ownership while the uid is still held, so
|
||||
a crash mid-way leaves an account that still exists — recoverable by re-running — rather than a freed uid with
|
||||
another member's data behind it.
|
||||
|
||||
Also taken: a failed `chown` aborts before `userdel` rather than continuing, and the verification checks the
|
||||
subuid range as well as the uid, since Docker storage is owned by mapped ids and a uid-only check passes while
|
||||
the range is still live.
|
||||
|
||||
Still not writing it tonight. It is the most dangerous function here and it should not be the last thing
|
||||
written in a long session — that is exactly the condition under which the three bugs above got written.
|
||||
|
||||
## State
|
||||
|
||||
Both gates unchanged. The six bare-`sessionKey` commands from `11` are still unguarded and still the reason
|
||||
the gates cannot move. Nothing in this commit is verifiable without a reprovision of green.
|
||||
Reference in New Issue
Block a user