ww build: honor Go output permission modes
This commit is contained in:
@@ -6308,6 +6308,103 @@ residue. Existing package tests continue to own all action/test variants,
|
||||
graph identity, output ordering, cwd/environment/stdin, timeout, and broader
|
||||
transaction behavior.
|
||||
|
||||
### 11.28 Implemented Go-like build-output permissions
|
||||
|
||||
Newly published build outputs now use Go 1.26.5's output-kind permission and
|
||||
caller-umask contract. An ordinary linked command starts from `0777`; a
|
||||
non-link archive starts from `0666`. The kernel filters either base permission
|
||||
through the invoking process's umask when the request-private publication inode
|
||||
is created. WW's required adjacent interface sidecar is data like its archive
|
||||
and uses the same `0666` base. Assembly-only builds create neither kind of
|
||||
public output.
|
||||
|
||||
#### Pinned Go evidence and direct pre-fix measurements
|
||||
|
||||
The authority is official Go 1.26.5 at commit
|
||||
`c19862e5f8415b4f24b189d065ed739517c548ba`:
|
||||
|
||||
- `runBuild` routes explicit single and directory `-o` products through
|
||||
`ModeInstall`, after deciding the caller-visible output path
|
||||
([`cmd/go/internal/work/build.go`, lines 459–558](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/build.go#L459-L558)).
|
||||
- `BuildInstallFunc` begins with permission `0666`, changes it to `0777` for an
|
||||
ordinary link action, creates the output parent, and gives that permission to
|
||||
`moveOrCopyFile`
|
||||
([`cmd/go/internal/work/exec.go`, lines 1904–2000](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/exec.go#L1904-L2000)).
|
||||
- On its rename path, `moveOrCopyFile` creates a destination-adjacent dummy with
|
||||
the requested permission, observes the caller-filtered mode, removes the
|
||||
dummy, applies that mode to the linked source, and renames it. Its copy
|
||||
fallback creates the destination with the requested permission and therefore
|
||||
receives the same kernel filtering
|
||||
([`cmd/go/internal/work/shell.go`, lines 119–220](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/internal/work/shell.go#L119-L220)).
|
||||
- Official `build_output.txt` asserts executable default, explicit-file,
|
||||
nested-file, trailing-directory, and existing-directory command outputs
|
||||
([lines 7–44](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_output.txt#L7-L44)).
|
||||
`build_multi_main.txt` exercises directory fan-out for two main packages and
|
||||
a local command-line package
|
||||
([lines 1–16](https://github.com/golang/go/blob/c19862e5f8415b4f24b189d065ed739517c548ba/src/cmd/go/testdata/script/build_multi_main.txt#L1-L16)).
|
||||
|
||||
The testdata anchors directly specify that the public command routes produce
|
||||
executables. The exact `0777`/`0666` bases and caller filtering are implemented
|
||||
by the pinned source. Therefore the resulting mode formula is source-derived;
|
||||
it is not an observation of the installed host Go toolchain.
|
||||
|
||||
Before this slice, fresh public-driver measurements of one byte-identical
|
||||
command gave mode `0755` from both stages under umask `000`. Under umask `077`,
|
||||
Cstage still gave `0755` while WWstage gave `0700`. The C linker created through
|
||||
`fopen` and unconditionally applied `chmod(0755)` after emission; the WW linker
|
||||
created with base `0755`. Thus both discarded permitted group/other write bits,
|
||||
and Cstage additionally reintroduced bits forbidden by a restrictive mask.
|
||||
|
||||
The non-link branch had a separate stage mismatch under the same official rule.
|
||||
With umask `000`, Cstage published a byte-identical archive/interface pair as
|
||||
`0666` while WWstage published it as `0644`; both became `0600` under umask
|
||||
`077`. Cstage's fresh `fopen` data stage already had base `0666`, while
|
||||
WWstage's data-copy stage explicitly used base `0644`.
|
||||
|
||||
#### Ownership, publication, and identity boundaries
|
||||
|
||||
The C and WW linkers now open every fresh linked output with base `0777`. The C
|
||||
linker emits through the resulting descriptor instead of applying a fixed mode
|
||||
afterward; the WW linker uses the same creation base. The WWstage driver's
|
||||
archive/interface copy now uses `0666`, matching Cstage's existing data-file
|
||||
creation. No driver independently reads or stores a umask.
|
||||
|
||||
For public build routes, the coordinator has already rejected an occupied or
|
||||
dangling output `.new` before the selected linker or copy owner opens the
|
||||
request-private stage. Creation therefore receives the current child process's
|
||||
umask exactly once. The established transaction renames that same inode to the
|
||||
caller-visible destination, so neither the final name nor replacement of an old
|
||||
destination changes its mode. A failed compiler, assembler, archiver, linker,
|
||||
stage, or installation preserves the old destination's bytes and mode and
|
||||
removes all request stages. Directory fan-out gives each independent command
|
||||
the same request-local rule; concurrent driver processes retain independent
|
||||
umasks and publication paths.
|
||||
|
||||
Permission bits are presentation metadata, not semantic inputs. Package and
|
||||
action identity, graph edges, declared names, physical directory metadata,
|
||||
compiler/assembler/archive/link argv, `.wwi` contents, artifact bytes, and
|
||||
persistence keys are unchanged. An unchanged warm request may reuse every
|
||||
semantic action but still relinks or copies the requested public product so its
|
||||
mode reflects the current invocation. Source invalidation changes the applicable
|
||||
artifact bytes without changing the formula. Retained test-binary copying
|
||||
remains a distinct output-policy path and already uses the same `0777` linked-
|
||||
executable rule. No Go-style dummy is needed and no `-go-tmp-umask` residue is
|
||||
created because WW links or copies directly into its already-private fresh
|
||||
stage.
|
||||
|
||||
No persisted byte schema changed. Build workdir format remains `18`, test
|
||||
workdir format remains `19`, and semantic storage remains `3`.
|
||||
|
||||
The WW-native owner `build_output_permissions_follow_umask` uses a test-only
|
||||
exec launcher to arrange exact process umasks. It covers both Cstage and
|
||||
WWstage; cold, warm, and invalidated persistent builds; explicit, default,
|
||||
raw-file, and multi-command directory outputs; `0777`, `0700`, `0750`, and
|
||||
`0770` command results; `0666` and `0600` archive/interface results;
|
||||
assembly-only omission; retained test-binary non-regression; direct execution;
|
||||
injected late-link request rollback over old files and modes; occupied-stage
|
||||
rejection; simultaneous builds with different umasks; diagnostic parity;
|
||||
artifact and binary byte identity; and absence of `.new` or umask-probe residue.
|
||||
|
||||
## 12. Candidate architectures and hard-gate decision
|
||||
|
||||
Five candidates were developed as coherent systems, not as feature bins.
|
||||
|
||||
@@ -310,6 +310,15 @@ ImportPath = ident { "." ident } .
|
||||
`fn main`; path and directory spelling do not classify commands. An ordinary
|
||||
import of a package declared `main` is rejected, except for the toolchain's
|
||||
colocated external-test wiring.
|
||||
- A newly published `ww build` command is created with permission `0777`
|
||||
filtered by the invoking process's umask. A newly published non-command
|
||||
archive, and the adjacent WW interface required to consume it, use `0666`
|
||||
filtered by that same umask. These inode permissions are output metadata:
|
||||
they do not enter canonical package or action identity, artifact bytes,
|
||||
import binding, symbols, `.wwi` contents, or persistent invalidation. A warm
|
||||
build therefore reuses unchanged semantic actions while refreshing the
|
||||
caller-visible output with the current invocation's mode. Assembly-only
|
||||
builds publish no executable or archive.
|
||||
- Only names marked `export` (§5) are visible across module boundaries.
|
||||
|
||||
Import paths remain unquoted and dotted. Grouped imports, quoted import paths,
|
||||
|
||||
Reference in New Issue
Block a user