Skip to content

Commit c278e45

Browse files
committed
FEATURE-ci-darwin-header-deadline: Match native diagnostic privilege context
Keep exact-archive download and overlay in the runner stage, strip both GitHub token variables before sudo, and run the existing build/test command tree with the original selected PATH and Git safety pattern. Record runner, privileged and test-process UID/GID plus selected build/runtime context; require test EUID zero. Preserve buffered traces, archive bindings, assertions and budgets. YAML, both Python stages, shell syntax, unchanged-overlay checks, actual token stripping and non-root rejection checks pass. Prior runner-context native successes remain diagnostic-only; corrected native execution and root cause are pending.
1 parent b801a05 commit c278e45

2 files changed

Lines changed: 105 additions & 6 deletions

File tree

‎.github/workflows/v3-package-validation.yml‎

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,9 @@ jobs:
104104
build, prefix, integration = [output / name for name in ('build', 'prefix', 'integration-shared')]
105105
for directory in (build, prefix, integration):
106106
directory.mkdir()
107-
command = Commands(output)
107+
runner_commands = output / 'runner'
108+
runner_commands.mkdir()
109+
command = Commands(runner_commands)
108110
provider = output.parent / 'prerequisites/provider'
109111
compiler, cc = os.environ['V3_CXX'], os.environ['V3_CC']
110112
toolchain = Path(os.environ['V3_PACKAGE_TOOLCHAIN'])
@@ -116,6 +118,7 @@ jobs:
116118
LDFLAGS='-Wl,-rpath,' + str(provider / 'lib'))
117119
receipt = dict(kind='diagnostic-only; not complete package validation', tls='no', linkage='shared',
118120
trace_mode='bounded memory; stderr emitted after all suite fixtures stop',
121+
runner_context=dict(uid=os.getuid(), euid=os.geteuid(), gid=os.getgid(), egid=os.getegid(), cwd=str(checkout)),
119122
revision=command(['git', 'rev-parse', 'HEAD'], checkout, env).strip(),
120123
compiler=command([compiler, '--version'], checkout, env),
121124
provider_header_sha256=hashlib.sha256((provider / 'include/openssl/opensslv.h').read_bytes()).hexdigest())
@@ -161,6 +164,44 @@ jobs:
161164
receipt['source_archive'] = dict(**expected, artifact_zip_sha256=zip_digest,
162165
archive_sha256=selected['sha256'], source_root=str(source), overlay=overlay,
163166
provenance='verified original archive plus explicit diagnostic overlay; not immutable release proof')
167+
receipt['status'] = 'archive overlay ready; privileged execution pending'
168+
except Exception as error:
169+
receipt.update(status='diagnostic failed', error=str(error))
170+
raise
171+
finally:
172+
(output / 'diagnostic.json').write_text(json.dumps(receipt, indent=2) + '\n')
173+
PY_DIAGNOSTIC
174+
diagnostic_script="$RUNNER_TEMP/package-evidence/header-deadline-build.py"
175+
cat > "$diagnostic_script" <<'PY_PRIVILEGED'
176+
import importlib.util, json, os, shlex, sys
177+
from pathlib import Path
178+
checkout = Path.cwd().resolve()
179+
sys.path.insert(0, str(checkout / 'scripts/lib'))
180+
import package_matrix as matrix
181+
from package_commands import Commands, runtime_environment
182+
from package_integration import compile_probe
183+
spec = importlib.util.spec_from_file_location('audit', checkout / 'scripts/audit-v3-installed-package.py')
184+
audit = importlib.util.module_from_spec(spec)
185+
spec.loader.exec_module(audit)
186+
output = Path(os.environ['RUNNER_TEMP']) / 'package-evidence/header-deadline-diagnostic'
187+
receipt = json.loads((output / 'diagnostic.json').read_text())
188+
source = Path(receipt['source_archive']['source_root'])
189+
build, prefix, integration = [output / name for name in ('build', 'prefix', 'integration-shared')]
190+
provider = output.parent / 'prerequisites/provider'
191+
os.environ['PATH'] = str(provider / 'bin') + os.pathsep + os.environ['PATH']
192+
compiler, cc = os.environ['V3_CXX'], os.environ['V3_CC']
193+
toolchain = Path(os.environ['V3_PACKAGE_TOOLCHAIN'])
194+
env = audit.clean_environment()
195+
env.update(CXX=compiler, CC=cc, CXXFLAGS='-O0 -g', CPPFLAGS='-DHTTPSERVER_DIAG_HEADER_DEADLINE',
196+
LDFLAGS='-Wl,-rpath,' + str(provider / 'lib'))
197+
command = Commands(output)
198+
receipt['privileged_context'] = dict(uid=os.getuid(), euid=os.geteuid(), gid=os.getgid(), egid=os.getegid(),
199+
cwd=str(checkout), compiler=compiler, cc=cc, toolchain=str(toolchain), provider_prefix=str(provider),
200+
path=env['PATH'], git_safe_directory=os.environ['GIT_CONFIG_VALUE_0'],
201+
build_environment={key: env.get(key) for key in ('CXX', 'CC', 'CPPFLAGS', 'CXXFLAGS', 'LDFLAGS')})
202+
try:
203+
assert os.geteuid() == 0, 'diagnostic build/test must match the original root execution'
204+
assert not any(key in os.environ for key in ('GH_TOKEN', 'GITHUB_TOKEN'))
164205
command(['bash', source / 'configure', '--enable-v3-tls=no', '--disable-examples', '--prefix=' + str(prefix)], build, env)
165206
command(['make', '-j2'], build, env)
166207
command(['make', 'install'], build, env)
@@ -180,17 +221,33 @@ jobs:
180221
graph = audit.dependency_graph([str(executable)])
181222
matrix.check_linkage(graph, 'shared', prefix)
182223
receipt['dependencies'] = graph
183-
result = command([str(executable)], source / 'test', runtime, timeout=180, allow_failure=True)
224+
launch = ('import json,os,sys; assert os.geteuid() == 0; '
225+
'assert not any(key in os.environ for key in ("GH_TOKEN", "GITHUB_TOKEN")); '
226+
'context=dict(uid=os.getuid(),euid=os.geteuid(),gid=os.getgid(),egid=os.getegid(),cwd=os.getcwd(),'
227+
'runtime={key:os.environ.get(key) for key in ("PATH","DYLD_LIBRARY_PATH","LD_LIBRARY_PATH","V3_PACKAGE_TOOLCHAIN")}); '
228+
'print("V3_DIAGNOSTIC_CONTEXT " + json.dumps(context),flush=True); '
229+
'os.execvpe(sys.argv[1],sys.argv[1:],os.environ)')
230+
result = command([sys.executable, '-c', launch, str(executable)], source / 'test', runtime, timeout=180, allow_failure=True)
184231
print(result, end='', flush=True)
185232
receipt['exit'] = command.records[-1]['exit']
233+
contexts = [line.removeprefix('V3_DIAGNOSTIC_CONTEXT ') for line in result.splitlines()
234+
if line.startswith('V3_DIAGNOSTIC_CONTEXT ')]
235+
assert len(contexts) == 1
236+
receipt['test_execution_context'] = json.loads(contexts[0])
237+
assert receipt['test_execution_context']['euid'] == 0
186238
receipt['suite'] = matrix.suite_result(result, receipt['exit'])
187239
receipt['status'] = 'diagnostic suite passed; full matrix not run'
188240
except Exception as error:
189241
receipt.update(status='diagnostic failed', error=str(error))
190242
raise
191243
finally:
192244
(output / 'diagnostic.json').write_text(json.dumps(receipt, indent=2) + '\n')
193-
PY_DIAGNOSTIC
245+
PY_PRIVILEGED
246+
diagnostic_python=$(command -v python3)
247+
env -u GH_TOKEN -u GITHUB_TOKEN sudo env "PATH=$PATH" \
248+
GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=safe.directory "GIT_CONFIG_VALUE_0=$PWD" \
249+
"RUNNER_TEMP=$RUNNER_TEMP" "V3_CXX=$V3_CXX" "V3_CC=$V3_CC" "V3_PACKAGE_TOOLCHAIN=$V3_PACKAGE_TOOLCHAIN" \
250+
"$diagnostic_python" "$diagnostic_script"
194251
- name: Make privileged proof readable by artifact upload
195252
if: always()
196253
run: |

‎specs/tasks/FEATURE-ci-darwin-header-deadline.md‎

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,41 @@ was established from this successful trace. The next checkpoint reduces trace
5151
perturbation and records actual notify/signal/ack states to distinguish missing
5252
wake from retained lease when a failure is observed.
5353

54+
## Required privilege context correction
55+
56+
The original c0 archive log (lines 294–325) and package log (lines 287–303)
57+
show that binding port 443 failed for the runner, then the existing workflow
58+
invoked the matrix through `sudo env PATH=...` with the exact checkout marked
59+
Git-safe. Its build/test processes therefore ran as root. Both earlier
60+
diagnostic drivers lacked sudo and did not record UID/GID; their runner-context
61+
results are not like-for-like privilege evidence. Live tracing perturbation is
62+
not the only established context contrast.
63+
64+
The existing artifact download/strict extraction/unchanged overlay remains in
65+
the runner stage with its read-only GitHub token. A generated, retained Python
66+
build script now runs through the existing sudo/env pattern, with both token
67+
variables removed **before sudo**. Explicit selected compiler/runtime/temp paths
68+
and exact Git safe.directory are passed; the provider bin directory follows the
69+
existing archive platform PATH setup. The entire build/compile/inspect/test
70+
command tree runs in that privileged stage. Its receipt records runner and
71+
privileged UID/EUID/GID/EGID, cwd, compiler, provider, toolchain, PATH and build
72+
flags. The build stage asserts EUID 0 and token absence. A final assert-and-exec
73+
launcher records the actual test process UID/GID, cwd and selected runtime
74+
search environment before replacing itself with the unchanged test executable;
75+
its EUID must be 0 and its environment must exclude both token variables.
76+
77+
Buffered runner-context run `39978609885`, job `120499691522`, subsequently
78+
finishes successfully with four tests, 52 checks and zero failures/skips. It
79+
emits 677 deferred records after the suite statistics; the header timer again
80+
expires, resumes, enforces and closes normally around 303 ms with one retirement
81+
lease. This is useful buffered-trace evidence in the runner context, and remains
82+
incomplete comparison to the original root execution. It was allowed to finish
83+
without cancellation or an unchanged retry.
84+
85+
The driver correction matches required execution setup and justifies an affected
86+
native check. The caller reviews this driver-only change before publishing or
87+
dispatching any further required run.
88+
5489
## Action items
5590

5691
- [x] Preserve and read prior/current evidence without repeating the closed Linux probe.
@@ -64,7 +99,9 @@ wake from retained lease when a failure is observed.
6499
ordinary-build argument elision, workflow syntax and changed-file lint.
65100
- [x] Execute the first native diagnostic and retain actual installed-library provenance.
66101
- [x] Prepare bounded in-memory capture with deferred output and explicit event timestamps.
67-
- [ ] Execute one reviewed buffered-trace native diagnostic against the same exact archive.
102+
- [x] Retain the completed runner-context buffered diagnostic result without cancellation.
103+
- [x] Correct required privileged build/test execution and record/assert its context.
104+
- [ ] Execute the reviewed privileged buffered diagnostic when required after caller review.
68105
- [ ] Establish cause from native evidence, then write and observe a failing
69106
regression before applying a narrow repair.
70107
- [ ] Remove all temporary trace code/header and workflow edits before final merge.
@@ -108,7 +145,7 @@ archive. Original/modified source manifests and per-file overlay hashes are
108145
retained. The original archive is preserved separately; the overlaid source is
109146
explicitly a diagnostic modified snapshot, not immutable release proof, and does
110147
not set `V3_RELEASE_IDENTITY`. Build and test source paths/cwd use this extracted
111-
tree. No build command receives the download token.
148+
tree. No sudo, build or test process receives the download token.
112149

113150
Compile/dependency hashes, commands, runtime selection and the failing suite log
114151
are retained in `package-evidence/header-deadline-diagnostic`. This partial run is
@@ -135,7 +172,12 @@ shared by executable/library events, and no diagnostic symbols or argument
135172
evaluation in ordinary builds. The updated literal archive overlay and
136173
workflow/test-preservation checks pass; both enabled/disabled extracted-source
137174
syntax checks and changed-file lint pass. Buffered native execution and the
138-
original required gate remain incomplete.
175+
original required gate remain incomplete. For the privilege-only follow-up,
176+
YAML, both Python stages and all macOS shell syntax pass; artifact/overlay code,
177+
permissions, other jobs and all C++ files are unchanged. An actual local env
178+
check proves both token variables are stripped while ordinary context survives;
179+
the literal test launcher rejects local EUID 1000 before exec. These are setup
180+
checks; native sudo/build/test EUID 0 execution remains pending.
139181

140182
The caller reviews/publishes only this task branch and dispatches the existing
141183
workflow, then resumes this same worktree with actual native evidence. No root

0 commit comments

Comments
 (0)