df6f270e7bfa30c406b806fbfced667324067b9f
4
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
df6f270e7b |
chore(safety): forbid unsafe on the crates that are already at zero
Five permanent ratchets, all free today — the point is that they cannot regress
tomorrow. Each crate was re-measured at the commit, not taken from a survey.
`forbid(unsafe_code)`:
punktfunk-encode-worker the binary that carries cap_sys_nice. Its header
claims "no Wayland, no D-Bus, no network, no
plugins"; this makes the memory-safety half of that
claim mechanical. `forbid`, not `deny`, so it cannot
be re-opened by an #[allow] further down.
pf-update-check parses a signed, network-fetched manifest and its own
header says it "owns the part where being wrong is a
security bug". Signature checking is worthless if the
parser around it can be walked out of bounds.
pf-vaadec its header states the design constraint outright — it
links no libva and compiles on macOS, "which is the
point". The crate is full of hand-declared libva
repr(C) mirrors; one raw deref and it stops being the
CPU-testable half.
tools/cursor-probe free, and a probe is where "just deref it to see" is
most tempting.
`deny(unsafe_code)` + one localized allow:
pf-update root runs this. Its single unsafe operation, a bare
geteuid, moves into a named `effective_uid()` helper
carrying the crate's one #[allow(unsafe_code)].
Deliberately NOT rewritten to rustix, contrary to the programme document's first
draft: pf-update's Cargo.toml states that its zero-dependency posture IS a
security invariant of a root helper ("no HTTP client, no TLS, no argument
parsing"), and the extern block says the same. Pulling a general-purpose syscall
crate into a root helper to delete one `unsafe` would trade a real property for
a cosmetic one. The localized allow keeps the ratchet: any NEW unsafe anywhere
in the crate is a build error.
Verified: `cargo check -p pf-vaadec -p pf-update-check` and
`cargo check -p pf-update -p cursor-probe` clean on macOS, plus
`cargo check -p pf-update --target x86_64-unknown-linux-gnu` — pf-update's whole
body is behind `cfg(target_os = "linux")`, so the macOS check does not reach the
line that changed. punktfunk-encode-worker is not built here (pf-encode's C
dependencies do not cross-compile from macOS) and needs the Linux CI leg.
|
||
|
|
5174a59832 |
fix(capture/kwin): a hidden cursor leaves the stream — KWin's id-0 meta is the hide
Since the 0.22.0 cursor work (the seat-pointer park + the metadata composite), a KWin capture-model stream always has a cursor — and it never went away again: not in game, not in Big Picture, not with a controller in hand (field report, 2026-08-01). The host blended the arrow forever because pf-capture deliberately ignores SPA_META_Cursor id 0, and once `visible` latched true nothing on Linux ever cleared it. Two producer contracts meet on id 0, and one flag now carries which one a stream follows. KWin rewrites the cursor meta on EVERY enqueued buffer and writes id 0 whenever Cursor::isOnOutput says the pointer is not in this stream — which covers both a globally hidden cursor and a client null-cursor surface (empty geometry intersects nothing). There id 0 IS the hide, and honoring it is what lets a game hide the pointer mid-stream. Mutter only rewrites a buffer's meta when the cursor changed, so recycled buffers carry stale id-0 regions between damage frames — honoring those flickered the cursor off between hovers (on-glass round 5), and that path keeps its last-known-state behavior. The flag rides from the backend that created the output (correct for registry-pooled reuse too — a kept display only ever matches its own backend) through capture_virtual_output into the parser's CursorState. The portal-monitor path stays on the stale-meta contract: the only thing routed through it today is Mutter's HDR mirror. Verified on .25: pf-capture 45/45, punktfunk-host 369/369, clippy -D warnings clean (pf-capture, punktfunk-host, cursor-probe), fmt clean. On-glass KDE validation still owed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
1f59498c5c |
fix(host/linux): a no-channel session composites the metadata cursor — Mutter never embeds on a virtual stream
ci / web (push) Successful in 3m26s
ci / docs-site (push) Successful in 3m32s
arch / build-publish (push) Failing after 4m29s
apple / swift (push) Successful in 4m38s
docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 5s
docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 5s
docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 4s
docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 5s
docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 5s
docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
ci / rust-arm64 (push) Failing after 4m50s
docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 12s
deb / build-publish (push) Failing after 5m6s
ci / rust (push) Failing after 5m47s
docker / builders-arm64cross (push) Successful in 6s
docker / deploy-docs (push) Successful in 34s
android / android (push) Canceled after 8m16s
apple / screenshots (push) Canceled after 3m46s
deb / build-publish-host (push) Canceled after 4m15s
deb / build-publish-client-arm64 (push) Canceled after 4m7s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Canceled after 3m6s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Canceled after 2m58s
windows-host / winget-source (push) Canceled after 0s
windows-host / package (push) Canceled after 8m21s
The capture-latched client (console.rs latched_mouse) never advertises CLIENT_CAP_CURSOR, so its session resolved cursor_blend=false and asked Mutter to EMBED the pointer. On a Mutter virtual stream that is a fiction: since Mutter 48 (7ff5334a, hw-cursor inhibition removed) the software cursor overlay is suppressed stage-globally whenever any physical head realizes a HW cursor — dmabuf-recorded frames blit the view without a pointer, and cursor-only motion schedules no re-record either (mutter#4939). Probed on-glass on Mutter 50.3: embedded + relative motion = frozen frame counter; SPA_META_Cursor positions kept flowing in the same setup. So the no-channel session now takes the path that was verified end to end: cursor-as-metadata + the host composites, permanently — the same arm a channel session lands in after its capture-model flip. Embedded remains only the can't-blend fallback (libav VAAPI/NVENC, software). - session_plan::cursor_blend_for grows the no-channel arm (codec + depth in, the same CUDA-payload prediction handshake makes); gamescope excluded so patch-2+ keeps its native-NV12 zero-copy shape - the encode loop's composite refresh + one-shot breadcrumbs now cover the no-channel session; the park schedule keeps retrying while its composite is starved (relative-only clients cannot park themselves) - the compositor retarget re-applies set_hw_cursor — the rebuilt display used to come up EMBEDDED even for channel sessions - the GameStream virtual source takes the same rule (it never has a channel); its stream_body blend flag mirrors the request - punktfunk-probe grows --cursor-nochannel (the latched-capture client, headless); cursor-probe grows --dump (PPM frames + a content-change counter, the pixel evidence the embedded A/B lacked) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a8744b98d1 |
feat(devtools): reproduce the capture-model cursor path without a real client
punktfunk-probe grows --cursor-capture: advertise CLIENT_CAP_CURSOR, flip the channel to the capture model (CursorRenderMode client_draws= false), and wiggle RELATIVE pointer motion for the whole dump — decode the .h265 and the host-composited pointer must be in the pixels. Plus --codec pyrowave (advertised only on request so the dump format of existing recipes never changes). tools/cursor-probe stands up the capture side alone: virtual output with the out-of-band cursor, production PipeWire capturer, production injector, absolute then relative motion — and reports whether SPA_META_Cursor ever yields an overlay. It is how Mutter's pointer-in-stream metadata gate was isolated on-glass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |