Symptom
`chmod-undo-linux.sh` smoke times out after 10s waiting for `discriminant = 'FilePreImage'` (or any event) on a `chmod 0755 foo.txt` operation. Journal dump after the chmod is empty.
Reproduction
Run `chmod-undo-linux.sh` against the self-hosted runner (or any host where `pick_linux_tier` selects `ebpf-lsm`).
Confirmed on the linux-kernel-capture (L02/L03/L04) matrix job, run 26253871697 rerun — rest of the matrix passes after the helper-side startup race fix (PR #20).
What we know
- Helper log shows `ebpf-lsm inode_setattr loaded and attached hook="inode_setattr" prog="shit_inode_setattr" ringbuf="setattr_events"` well before the chmod runs.
- Tier picked is `ebpf-lsm (L04)` (`SHIT_FORCE_TIER=ebpf-lsm`).
- BPF feature detection reports BTF + bpf_perf_link + bpf_cookie all available.
- Other LSM hooks attached on the same boot DO produce events: `file_open` (edit-undo smoke ✓), `inode_unlink` (rm-undo ✓), `inode_mkdir` (mkdir-undo ✓), `inode_rename` (mv-undo ✓).
- Only `inode_setattr` is silent.
Contract from the smoke
The chmod smoke explicitly expects `inode_setattr → FilePreImage` (`tests/smoke/chmod-undo-linux.sh:92-94`):
```
eBPF-LSM setattr emits the same FilePreImage event wire as fanotify-perm
does for open-then-write. The daemon's metadata-restore path reads the
old mode/uid/gid from the FilePreImage record on undo.
smoke_wait_for_event "discriminant = 'FilePreImage'" 1 10
```
So the protocol intent is: chmod fires inode_setattr → BPF writes to setattr_events ringbuf → helper translates to a FilePreImage event carrying old mode/uid/gid → daemon journals it.
Three places the bug could live
- BPF program does not fire on chmod(2) — the LSM hook may need an explicit `fmod_ret` / `fexit` signature, or it's attached but the kernel doesn't trigger it for chmod (e.g., chmod goes through `inode_setattr` only when `mode` changes; ATTR_MODE in the iattr).
- BPF program fires but doesn't write to setattr_events — early return on filter (pid exclusion, watch-tree empty), or ringbuf reserve/submit bug.
- Helper reads setattr_events but doesn't translate to FilePreImage — the userspace consumer in shit-helper/src/ebpf/ may emit a different discriminant (MetadataChange) or drop the event.
Next steps for investigation
- Add a `bpf_printk` (or `trace_printk`) at the top of `shit_inode_setattr` and run a chmod under the helper; check `/sys/kernel/debug/tracing/trace_pipe`. If silent: case (1). If chatty: case (2) or (3).
- Audit the helper's ringbuf reader for `setattr_events` (probably in `crates/shit-helper/src/ebpf/reader.rs` or similar) — verify it constructs a `FilePreImage` capture event with the captured mode/uid/gid, not a `MetadataChange`.
- Cross-check the iattr.ia_valid flag handling in the BPF program — chmod sets ATTR_MODE only, while `chown` sets ATTR_UID/ATTR_GID, and `touch` sets ATTR_ATIME/ATTR_MTIME. The program may be filtering for the wrong flags.
References
Symptom
`chmod-undo-linux.sh` smoke times out after 10s waiting for `discriminant = 'FilePreImage'` (or any event) on a `chmod 0755 foo.txt` operation. Journal dump after the chmod is empty.
Reproduction
Run `chmod-undo-linux.sh` against the self-hosted runner (or any host where `pick_linux_tier` selects `ebpf-lsm`).
Confirmed on the linux-kernel-capture (L02/L03/L04) matrix job, run 26253871697 rerun — rest of the matrix passes after the helper-side startup race fix (PR #20).
What we know
Contract from the smoke
The chmod smoke explicitly expects `inode_setattr → FilePreImage` (`tests/smoke/chmod-undo-linux.sh:92-94`):
```
eBPF-LSM setattr emits the same FilePreImage event wire as fanotify-perm
does for open-then-write. The daemon's metadata-restore path reads the
old mode/uid/gid from the FilePreImage record on undo.
smoke_wait_for_event "discriminant = 'FilePreImage'" 1 10
```
So the protocol intent is: chmod fires inode_setattr → BPF writes to setattr_events ringbuf → helper translates to a FilePreImage event carrying old mode/uid/gid → daemon journals it.
Three places the bug could live
Next steps for investigation
References