Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/plugin-confinement-proof.yml
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,59 @@ jobs:
assert diagnostic['pid'] == entry['observed']['pid'] > 0, entry
assert len(diagnostic['output']) <= 16384 and len(diagnostic['stderr']) <= 2048, entry
PYCONTROL
- name: Reject stale errno after a nonnegative send return
if: always() && !cancelled() && steps.native_setup.outcome == 'success'
shell: bash
run: |
set -euo pipefail
source=scripts/probes/plugin-confinement
xcrun clang -Wall -Wextra -Werror -pthread "$source/macos_datagram_send_test.c" -o "$RUNNER_TEMP/send-result-test"
"$RUNNER_TEMP/send-result-test" > "$RUNNER_TEMP/unix-zero-send.log" 2>&1
legacy="$RUNNER_TEMP/macos-stale-errno-guard"
python3 - "$legacy" <<'PYCONTROL'
from pathlib import Path
import shutil, sys
target = Path(sys.argv[1])
target.mkdir()
for name in ('macos_datagram_send.h', 'macos_datagram_send_test.c'):
shutil.copyfile(Path('scripts/probes/plugin-confinement') / name, target / name)
fixture = target / 'macos_datagram_send.h'
source = fixture.read_text()
changes = {
'result.error = result.returned == -1 ? errno : 0;': 'result.error = errno;',
'sent.attempted && sent.returned == -1 && (sent.error == EACCES || sent.error == EPERM)': '(sent.error == EACCES || sent.error == EPERM)',
}
for needle, replacement in changes.items():
assert source.count(needle) == 1
source = source.replace(needle, replacement)
fixture.write_text(source)
PYCONTROL
xcrun clang -Wall -Wextra -Werror -pthread "$legacy/macos_datagram_send_test.c" -o "$legacy/send-result-test"
if "$legacy/send-result-test" > "$RUNNER_TEMP/unix-stale-errno-guard.log" 2>&1; then
echo 'Missing raw-return guards unexpectedly passed the verifier regression' >&2
exit 1
fi
python3 - "$RUNNER_TEMP" <<'PYCONTROL'
from pathlib import Path
import hashlib, json, sys
root = Path(sys.argv[1])
fixed = [json.loads(line) for line in (root / 'unix-zero-send.log').read_text().splitlines()]
assert [row['case'] for row in fixed] == ['zero-stale-EPERM', 'short-stale-EACCES', 'failed-EACCES', 'failed-EPERM', 'failed-EINVAL', 'setup-with-stale-EPERM'], fixed
text = (root / 'unix-stale-errno-guard.log').read_text()
assert 'send-result regression failed: zero-stale-EPERM' in text, text
legacy = json.loads(next(line for line in text.splitlines() if line.startswith('{')))
assert legacy['case'] == 'zero-stale-EPERM' and legacy['returned'] == 0 and legacy['outcome'] == 'D', legacy
paths = ['macos_datagram_send.h', 'macos_datagram_send_test.c']
digest = hashlib.sha256()
legacy_digest = hashlib.sha256()
for name in paths:
digest.update((name + '\0').encode())
digest.update((Path('scripts/probes/plugin-confinement') / name).read_bytes())
legacy_digest.update((name + '\0').encode())
legacy_digest.update((root / 'macos-stale-errno-guard' / name).read_bytes())
report = {'scope': 'Deterministic fault-injected verifier regression, not native confinement acceptance.', 'sources': paths, 'source_sha256': digest.hexdigest(), 'legacy_source_sha256': legacy_digest.hexdigest(), 'fixed': fixed, 'invalid_legacy_guard': legacy}
(root / 'unix-send-result-control.json').write_text(json.dumps(report, indent=2) + '\n')
PYCONTROL
- name: Reject missing private descriptor reception
if: always() && !cancelled() && steps.native_setup.outcome == 'success'
shell: bash
Expand Down Expand Up @@ -309,6 +362,9 @@ jobs:
${{ runner.temp }}/unix-boundary.log
${{ runner.temp }}/unix-missing-scope.log
${{ runner.temp }}/unix-datagram-bind-failure.log
${{ runner.temp }}/unix-zero-send.log
${{ runner.temp }}/unix-send-result-control.json
${{ runner.temp }}/unix-stale-errno-guard.log
${{ runner.temp }}/unix-dropped-rights.log
${{ runner.temp }}/unix-rights-path-reader.log
${{ runner.temp }}/exec.json
Expand Down
12 changes: 8 additions & 4 deletions docs/goal-delivery.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,14 @@ checks passed and the optional diagnostic was intentionally skipped. Its merge
tree matches the reviewed/tested `e6fd3d2f` tree. The user approved continuing the
[Linux broker direction](../openspec/changes/complete-plugin-hook-runtime/native-host-integration.md)
with runtime kernel capability checks and full private IPC/network compatibility
remaining required before activation. Continue on the single
[draft #80](https://github.com/CyberdyneCorp/cybercode-cli/pull/80), branch
`feat/plugin-native-host-admission`, retaining its original
tested sources on `evidence/plugin-native-host-pre-76-merge` across rebase.
remaining required before activation. The original tested sources remain on
`evidence/plugin-native-host-pre-76-merge`. Follow-up #80 merged at `2745b4f0`
and #83 at `c3bd34c4` on 2026-10-31. These are foundations, diagnostics and the
observer resource correction; production native admission remains incomplete.
Continue the first workstream on one follow-up branch,
`feat/plugin-native-admission-followup`, retaining the same review and acceptance
gates. The raw datagram send-result correction strengthens measurement and does
not authorize Linux support changes or production activation.

Native confinement foundations and regressions exist, but
production enforcement and the remaining plugin/hook scope are incomplete. The
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ assertion; compilation failure cannot satisfy the control. The exact control
was executed locally and failed at that assertion. Platform CI and composed-feature
acceptance remain required. Task 5.2 stays open, as do the separate plugin native
admission and protocol gates.

## Composed platform verification at 3f7067dd

The [fresh workflow](https://github.com/CyberdyneCorp/cybercode-cli/actions/runs/41180219218)
completed successfully on Linux, macOS and Windows after the main integrations.
Its exact source is `3f7067dd058b91c11320c99c556b60451b103098`. This supplies
current composed platform results rather than treating the earlier d689d2f3
jobs as evidence for later main changes. Full task-5.2 requirement-by-requirement
acceptance review remains open; native plugin admission is a separate gate.
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,12 @@ The IPC source digest at `cf695982` is
These results establish diagnostic behavior, not a fix for the Intel failure.
Fresh hosted verification remains required.

## Intel EINVAL result and kernel-context follow-up
## Intel errno-22 observation and kernel-context follow-up

The diagnostic [Intel job at cf695982](https://github.com/CyberdyneCorp/cybercode-cli/actions/runs/41143313110/job/124362484197)
failed again at `r0w1s1`, now identifying `send` with errno 22 (`EINVAL`). Ten
failed again at `r0w1s1`, recording stage `send` and errno 22. The raw send
return was not retained; the [result-validation correction](macos-send-result-validation.md)
shows why this cannot establish a -1/EINVAL syscall failure. Ten
attempts were recorded: four private acknowledgements, five policy refusals and
one unknown error. The thread settled and the owner recorded zero host packets;
this incomplete row still fails acceptance. The exact cause remains unresolved.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Native datagram send-result validation

This corrects the native measurement contract. It does not activate the App's
native launcher, approve the Linux dependency revision or close parent tasks.

## Reproduced defect

The earlier datagram helper reduced the send return value to a boolean. Its
caller then inspected errno whenever the expected twelve bytes were not sent.
A nonnegative short result could therefore inherit an unrelated permission errno
and be counted as a policy refusal. A copied fixture returning zero with stale
EPERM for the r0w1s1 race's sendmsg calls passed all nine cases before this fix,
including sixteen outcomes classified as refusals in that case. Those were not
sixteen demonstrated failed native sends.

The [Apple send manual](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/send.2.html)
distinguishes a byte count from a -1 failure accompanied by errno. The corrected
helper preserves the raw result, captures errno immediately only after -1, and
requires both an attempted syscall and -1 plus EACCES/EPERM for a refusal.
An invalid setup cannot manufacture a send attempt. Cleanup preserves a socket
setup error instead of rereading errno after close.

The first unexpected send or private reply retains `failure_return` and its
error code. A nonnegative short send is `send_size` with error code zero; it
fails the existing acceptance assertion. A -1 error outside the two permission
codes still fails as `send`. `failure_return` is null when no unexpected send or
reply result was captured, including successful rows and failures in other
stages. No error is retried or silently recategorized as a successful exchange.

## Regression and missing-guard control

The initial control injected zero with stale EPERM into a copied full IPC matrix,
then required a second matrix with the old guards to falsely pass. That design
coupled a deterministic send-result regression to unrelated concurrent alias
lookups. The corrected control compiles the exact shared send/result helpers in
`macos_datagram_send_test.c`, with only sendmsg replaced by an explicit fault
injector. It is verifier regression evidence, not native syscall or confinement
acceptance. The normal nine-case IPC matrix still performs all real concurrent
host/private alias replacements and retains every existing assertion.

Six deterministic cases cover zero with stale EPERM, short with stale EACCES,
actual -1 permission results, -1/EINVAL, and setup refusal before any send. They
also verify first-failure preservation. The shared helper reports ENAMETOOLONG
for an oversized socket path instead of leaving stale errno. Only -1 plus a
permission error can count as refusal; nonnegative and unknown results must fail.

A copied shared header restores both old guards: unconditional errno capture and
permission classification without an attempted -1 send. The same compiled test
must execute and fail specifically at `zero-stale-EPERM`, showing raw zero and
outcome D. Compiler/startup failure cannot satisfy this control. The workflow
retains both logs and a source-bound report that labels the legacy classification
invalid. It does not demand that an unrelated native race falsely pass.

## Hosted failure at 3f7067dd

The [Intel job](https://github.com/CyberdyneCorp/cybercode-cli/actions/runs/41173821688/job/124457138622)
passed all nine primary IPC rows, then correctly rejected the injected zero send
at `r0w1s1`. Its legacy comparison failed earlier at the unmodified `r0w0s1` race:
raw return -1, errno 22, seven private acknowledgements and eight classifications
as refusals in sixteen attempts. The thread settled and host receipts were zero.
This new raw-return witness establishes an actual failed send in that copied
comparison run. It does not establish the cause, nor prove that an earlier
historical report without a raw result had the same cause.

The failed job remains failed evidence, retained under
`scripts/probes/plugin-confinement/evidence/macos-send-result-intel-3f7067dd`.
The archive digest, actual tested merge/head tree equality, and normal IPC
manifest were independently verified. The deterministic regression removes the
unrelated-race dependency; it does not fix or accept an unknown native race
outcome. Unknown send errors still fail the full normal matrix without retries.

## Evidence and remaining work

The historical d689d2f3 run completed 68 checks successfully with one intentional
historical skip. Its arm64/x64 native signing reports are retained under
`scripts/probes/plugin-confinement/evidence/macos-owned-unix-d689d2f3`. Archive
checksums, actual checkout/tree equality and each declared IPC source byte were
independently verified. These reports predate the raw-result fix; their refusal
classification does not resolve the earlier errno ambiguity.

The earlier Intel cf695982 report records errno 22, but lacks the raw syscall
result. It cannot establish that send returned -1/EINVAL rather than a short
nonnegative result with stale errno. The cause of that historical row remains
unresolved. Fresh native results must use the corrected raw-result witness.

The initial local arm64/Darwin checks and copied-matrix counterexample remain
historical evidence under `scripts/probes/plugin-confinement/evidence/macos-send-result-local`.
After isolating the regression, all eight exact native-signing workflow steps
pass locally, including all nine real IPC rows, the native capability matrix,
signature/exec controls, missing scratch/scope/rights/path controls, and the six
send-result cases with their precise missing-guard failure. Current-source
reports/logs are retained under
`scripts/probes/plugin-confinement/evidence/macos-send-result-deterministic-local`;
the actual source bytes were independently matched to every report manifest.
Current-source hosted/runtime/platform acceptance remains required; neither a
passing diagnostic nor this verifier correction completes production enforcement.

## Review and checks

The change is confined to diagnostic fixtures, their verifier/workflow and
evidence/documentation; production launch policy is unchanged. Review covered
errno lifetime, attempted-send qualification, first-failure preservation,
nullable JSON output, cleanup and control specificity. No blocking code or
security findings remain in this diff. The injected copies remain outside the
source checkout, and only the corrected normal reports count as positive evidence.

Verification: all nine local normal IPC rows; all eight native-signing workflow steps,
including the zero/short/unknown/setup cases and its deliberately failing
legacy-guard counterexample; native capability/signature/exec setup; YAML, shell and embedded
Python syntax; `git diff --check`; strict OpenSpec validation (114 passed, zero
failed); spec lint (zero errors, 25 warnings). The evidence report source hashes
were independently recomputed against the actual fixture bytes. No Rust tests
were run for this probe-only change. Hosted macOS arm64/x64 and the configured
Linux checks have not yet been run on this revision.
5 changes: 5 additions & 0 deletions openspec/changes/complete-plugin-hook-runtime/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ also have source-bound native receipts. Its [trusted-worker capacity/recovery ca
passed on x64/arm64 in run 41049265434, with source-bound receipts retained. These
experiments change no production policy or accepted support floor.

The [raw datagram send-result correction](macos-send-result-validation.md) adds a
real copied-fixture regression for stale errno after a zero return and retains
current-source local evidence. Hosted verification and native admission remain
required; this correction does not close tasks 2.1–2.4.

## 3. Host contribution lifecycle

- [ ] 3.1 Validate initialize contributions and add plugin/digest/Location/generation ownership, collision handling, atomic replacement and late-result fences.
Expand Down
13 changes: 11 additions & 2 deletions scripts/probes/plugin-confinement/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ Its first unexpected operation/errno is retained in `failure_stage` and
`failure_errno`; successful rows require both to be empty/zero. The occupied-bind
control must report `client_bind`/`EADDRINUSE` and fail the real private exchange
assertion. Unknown errors never count as policy refusals. The retained Intel
failure now identifies a race-time send returning `EINVAL`, with its cause
still unresolved. The follow-up collects bounded kernel messages for the exact
failure recorded errno 22 without its raw send result; its cause remains
unresolved. [Raw send-result validation](../../../openspec/changes/complete-plugin-hook-runtime/macos-send-result-validation.md)
now distinguishes a -1 error from a short result with stale errno. The follow-up collects bounded kernel messages for the exact
fixture PID/directory on error and runs differential controls independently after
a positive-test failure. The positive failure still fails the job; missing logs
cannot count as confinement.
Expand Down Expand Up @@ -400,3 +401,11 @@ results remain required. CI separately checks both configured and OS-provided
Python, including direct framework-image resolution. The existing runtime
bootstrap matrices continue to run independently. All production identity,
package, lifecycle and support-review gates above remain open.

The deterministic `macos_datagram_send_test.c` compiles the actual shared
`macos_datagram_send.h` helpers with explicit sendmsg fault injection. It checks
zero/short returns with stale errno, true permission failures, unknown errors,
setup-before-send and first-failure preservation. Its copied missing-guard control
must fail specifically on zero/stale-EPERM classification. These are verifier
regressions, separate from the unchanged nine-row real IPC/concurrent alias
matrix; they do not count as native confinement acceptance.
Loading
Loading