UVC camera compat & stability hardening (v0.0.7.3→v0.0.7.8): transfer-buffers property, negotiation diagnostics, quirk seam, camera-compat docs - #16
Merged
Conversation
…,100], reconnect-idempotent)
…rk seam (empty by default)
The main test_transfer_buffers target's three ON-path cases (applied, clamped, reconnect_reapply) asserted the fork-only uvc_set_transfer_buffers() effect unconditionally. The file already defined TB_API_AVAILABLE for exactly this purpose but never used it, so a real -DLIBUVC_USE_FORK=OFF full-suite run (first exercised by the todo-13 integration gate) failed those three cases: with the fork API absent the element correctly warns and no-ops, so no setter call is made. Activate the guard so each case asserts the fork ON behavior when TB_API_AVAILABLE and the warn-and-no-op behavior otherwise; the max-payload reconnect re-arm (not fork-gated) stays asserted on both paths. No product code changed; the OFF no-op remains covered by test_transfer_buffers_off_noop.
…am_close timeout path)
…or late-callback UAF) Round 1 (v0.0.7.4, dfba86f) quarantined the stream handle but uvc_close() still freed strmh->devh, so a late LIBUSB_TRANSFER_COMPLETED callback dereferencing strmh->devh->is_isight in _uvc_process_payload was a use-after-free on the freed device handle. v0.0.7.5 (a1949ae) propagates the quarantine to the device handle: uvc_close() intentionally leaks devh when a stream was quarantined, so the late deref lands on live memory. Bounded-wait preserved; common path still frees both. Only FORK_SHA + its comment change. UPSTREAM_SHA and patches/ untouched. Gate re-run against the build-libuvc.sh clone of a1949ae: ASan 148/148, plain 93/93, CVE oob+null + usb_teardown + pts/frame(+tsan) all Passed; plugin .so and test_cve_2026_1991 resolve libuvc.so.0 -> pinned install (RUNPATH).
…x for handler-thread/libusb_exit race) FORK_SHA a1949ae -> 3ede00e (tag ceralive-v0.0.7.6). Round 3 quarantines the uvc_context on the stop-timeout path: uvc_exit() now leaks the context (skips libusb_exit + free) and uvc_open_internal() skips a duplicate event-handler thread while a still-running _uvc_handle_events loops on ctx->usb_ctx after a quarantining uvc_close(). Fixes a UAF/race on the libusb context on every plugin stop() after a quarantine, and a double handler thread on reconnect. Re-gated against the build-libuvc.sh clone of 3ede00e (fresh dirs): ASan 148/148, plain 93/93; cve_2026_1991 oob+null, usb_teardown(+asan), pts_thread_safety(+tsan), frame_throughput(+tsan), reconnect_* all Passed; real plugin .so + test_cve_2026_1991 resolve libuvc.so.0 => the pinned install. UPSTREAM_SHA + patches/ untouched.
…ll/join on quarantine state)
…exit over open_devices)
The 5 emergency hotfix rounds (v0.0.7.4->v0.0.7.8) bumped FORK_SHA in scripts/build-libuvc.sh but the fork ADR's primary pin block was never advanced past v0.0.7.2, so scripts/check-libuvc-fork.sh (the CI fork-guard) reported PIN DRIFT: build 71588db != ADR eae7f49. Add an authoritative CURRENT PIN callout at the top of the Fork URL section (71588db / ceralive-v0.0.7.8) so the guard's first-GIT_TAG / first-Tag-HEAD-SHA reads agree with the build pin, and add a v0.0.7.8 addendum documenting the UAF/lifetime hotfix chain. All prior v0.0.7.2 and v0.0.7.3 records are preserved verbatim as historical provenance. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR lands the culmination of the uvc-camera-compat-stability hardening plan: it adopts a substantially hardened
CeraLive/libuvcfork and adds a set of opt-in, off-by-default plugin knobs and diagnostics for UVC camera compatibility.No default-behavior change. Every new knob is sentinel-off; existing DJI/UVC setups negotiate byte-identically when nothing is set.
What this does
uvc_stream_stop), metadata-buffer leaks, degenerate/broken frame-descriptor repair, zero/corrupt/oversized payload guards, and composite-device VC-headerdwClockFrequencypreservation. Fixes were extracted individually rather than merging any fork wholesale, each behind a mandatory per-fix equivalence audit.transfer-buffersproperty. USB transfer-buffer count hint, mirroring the existingmax-payloadcontract exactly: sentinel0= library default (no device write), nonzero clamped to[2, 100], applied right beforeuvc_start_streaming()on both initialstart()and every reconnect re-arm (reconnect-idempotent), read-back logged. Fork-only; a no-op with one warning on theLIBUVC_USE_FORK=OFFupstream-fallback build (feature-guarded viaHAVE_UVC_TRANSFER_BUFFERS).QUIRK_DOUBLE_PROBEas the first behavior — table + lookup + logging, empty by default (no entries enabled), so it's a pure seam with zero runtime effect until a quirk is deliberately added.docs/notes/camera-compat.md— mechanism-per-family compatibility matrix, field-triage guide, and fork provenance table.Fork pin
The fork is now pinned at
ceralive-v0.0.7.8(71588dbc23c5204e07c575c3b2ae6ac7ee9bf90d), up fromceralive-v0.0.7.2/eae7f49before this work. The fork is public and already released/tagged onhttps://github.com/CeraLive/libuvc.git; CI'sfork-guardclones it with no credentials.After the initial
v0.0.7.3release, an adversarial code-quality review of the new boundeduvc_stream_stop()(A5) teardown path caught a use-after-free chain reachable when a stop-timeout leaves an event/handler thread alive during teardown. Five narrowly-scoped hotfix rounds were required:v0.0.7.4strmhon the A5 stop-timeout path inuvc_stream_close.v0.0.7.5devhinuvc_closeso a lateLIBUSB_TRANSFER_COMPLETEDcallback deref ofstrmh->devh->is_isightis lifetime-safe.v0.0.7.6uvc_contextsouvc_exitskipslibusb_exit/free while a stop-timeout event thread still runs onctx->usb_ctx.v0.0.7.7uvc_close's last-device handler-thread kill/join on!has_quarantined_device.v0.0.7.8uvc_exititeratesctx->open_deviceswithDL_FOREACH_SAFE(safe againstuvc_closefreeing the current node).Full per-round detail:
libuvch264src/docs/notes/camera-compat.mdand the fork's ownCHANGELOG.ceralive.md.CI fix included in this PR
The 5 hotfix commits bumped
FORK_SHAinscripts/build-libuvc.shbut the fork ADR's primary pin block was never advanced pastv0.0.7.2, so thefork-guardCI job (scripts/check-libuvc-fork.sh) would report PIN DRIFT (build71588db≠ ADReae7f49). This PR adds onedocs(libuvc)commit that syncs the ADR's authoritative pin tov0.0.7.8and documents the hotfix chain — all priorv0.0.7.2/v0.0.7.3records preserved verbatim as historical provenance.Scope boundaries
No XU-based Logitech H.264, no GoPro non-UVC mode, no capture-card handling, no upstream-fallback (
patches/) changes, noforce_usb_release()-before-uvc_close()reintroduction, and no sibling-repo changes. Real-hardware validation remains a separate follow-up (the full ctest suite is mock-backed and hardware-independent).Verification
Full evidence trail (fresh-clone builds, real ctest runs incl. TSan/ASan, fork CI checks, per-fix equivalence audits) exists under
.omo/evidence/task-*.md/.txtin this repo — gitignored, so not part of the PR diff, but available for review context on request.Ultraworked with Sisyphus