Caleb/krn 1117 stackdepot port codeql - #3
Draft
caleb-kan wants to merge 147 commits into
Draft
Conversation
added 30 commits
June 1, 2026 21:14
Add stack_depot_fetch_into() so callers can copy a saved stack trace into caller-owned storage instead of receiving a pointer to stackdepot-owned memory. This is a preparatory API for trie-backed stack storage, where a saved stack may be spread across multiple trie nodes and must be materialized before use. Add KUnit coverage for successful copy-out and invalid or too-small buffer handling. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Cover the stackdepot public header and KUnit test under LIBRARY CODE so get_maintainer.pl reports the library maintainer for the new test file and checkpatch no longer warns that MAINTAINERS may need updating. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Document the caller-owned copy and handle lifetime contract for stack_depot_fetch_into() so the helper is explicit about how trie-backed materialization will be consumed. Cover the exact-fit, oversized-buffer, and zero-sized-buffer cases in KUnit to lock the all-or-nothing copy semantics. Keep the stackdepot KUnit entry ordered with nearby tests and broaden MAINTAINERS coverage so future stackdepot tests are routed to the library maintainer. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Use stack_depot_fetch_into() when rendering page_owner_stacks so the diagnostic path no longer depends on stackdepot's flat entries[] storage. Store the materialized stack in seq_file private data to avoid a large stack buffer and keep output formatting unchanged. Clarify the fetch_into() oversized-buffer documentation while adding the first page_owner caller that relies on caller-owned stack materialization. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Store page_owner stack handles in the show_stacks list instead of stackdepot internal stack_record pointers. This keeps the debugfs listing path from depending on stackdepot's flat record storage while preserving the existing page count accounting for a later helper conversion. Materialize stack frames into seq_file private storage with stack_depot_fetch_into() when printing page_owner_stacks so the output format stays unchanged and no large stack-local buffer is needed. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add internal stackdepot count helpers and use them from page_owner so page_owner no longer reads or mutates struct stack_record directly. This keeps page_owner behind handle-based stackdepot access before the persistent stack storage layout changes for trie-backed records. Keep the stackdepot KUnit test built-in-only because it exercises internal helpers, and add coverage for the saturated-to-counted transition and count boundary cases. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Move the flat stackdepot record and handle bitfield layout out of the public stackdepot header and into lib/stackdepot.c. Runtime callers now use handle-based helpers, so the flat storage details no longer need to be exposed before the persistent storage backend changes. Keep the page_owner count helpers internal to stackdepot, document their counted-mode semantics, and extend KUnit coverage for saturated, counted, and invalid-count cases. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add generic architecture hooks for stackdepot frame compression so future x86-64 and arm64 implementations can opt in without changing common stackdepot callers. The generic asm fallback keeps today's behavior by declining compression and storing raw frames. Keep stackdepot_fetch_into() safe across the copy by holding the same notrace RCU read-side section used by stackdepot lookups, and cover the raw frame fallback plus count-helper edge cases in KUnit. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Keep the stackdepot count decrement helper from silently discarding attempts to subtract more than the current counted value. Preserve the old refcount diagnostic behavior by warning before returning false on an underflow attempt. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the x86-64 stackdepot frame compression hook for frames whose high 32 bits match the kernel-text prefix. This keeps non-x86-64 builds on the generic raw fallback while allowing the common code to use the architecture hook added earlier. Extend stackdepot KUnit coverage for the x86-64 round trip and for non-compressible direct-map frames. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the internal frame-run encoding layer used by the trie-backed stackdepot prototype. Runs are described as either raw frames or compressed low 32-bit frame values that share one architecture prefix, with caller-provided scratch storage so the kernel port does not hide CONFIG_STACKDEPOT_MAX_FRAMES-sized arrays on the stack. Enable the corresponding arm64 compression hook using the runtime _text prefix plus adjacent 4 GiB prefixes so KASLR and module windows round-trip exactly, while non-matching frames keep the raw fallback. Harden the existing x86 and generic hooks and extend KUnit coverage for raw, compressed, invalid, and max-frame cases. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Keep the page_owner stack display buffer sized to the depth that page_owner actually saves, and make count_threshold use the same unsigned int range as the stackdepot page counters. This keeps the stack-list marker subtraction explicit before threshold filtering and rejects oversized debugfs thresholds instead of silently suppressing every stack. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the private trie-node storage primitive from the userspace prototype. A node stores one homogeneous raw or compressed frame run in caller-provided storage and records immutable parent and stack-length metadata so a leaf parent chain can be materialized into caller-owned output. Keep the helper inert for now: stack_depot_save() and the public fetch path still use existing hash records. KUnit covers node sizing, raw and compressed round trips, parent-chain materialization, mixed-run rejection, short storage, and invalid fetch inputs. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the sorted child-array helper layer from the userspace trie prototype. Child arrays are built in caller-owned storage, reject duplicate first-frame keys and in-place replacement, and remain unpublished so no RCU or COW visibility rules change yet. Cover initialization, lookup, empty insertion, middle insertion, unsorted input, duplicate insertion, and in-place update rejection in stackdepot KUnit. Also document the page_owner stack listing race as best-effort because counts can change while seq_file output is being generated. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Tighten the private trie helper contracts after adding child arrays. Reject overlapping frame-run buffers, validate old child-array storage alignment, and use an explicit ULONG_MAX arm64 prefix bound. Keep the page_owner count helper limits consistent across set/inc paths and document best-effort page_owner stack listing semantics. Extend stackdepot KUnit coverage for arm64 compressed frame-run round trips, compressed trie nodes without scratch storage, count-boundary handling, and child-array edge cases. The trie helpers remain inert: they only build caller-owned unpublished storage and do not change stack_depot_save() or public fetch routing. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the private trie node matching primitive from the userspace prototype. It decodes one raw or compressed node run and returns the matching prefix length against caller-provided frames without walking parent or child links. Extend stackdepot KUnit coverage for raw and compressed exact matches, partial matches, shorter and longer inputs, first-frame mismatches, and invalid inputs. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the private append-chain primitive from the userspace trie prototype. The helper builds unpublished raw or compressed trie nodes from caller-owned storage, splitting chains at frame-run boundaries and linking newly-created nodes with one-child arrays. Keep the helper inert for now: it does not publish nodes, allocate memory, or change stack_depot_save() and fetch routing. Cover raw chains, parent chains, frame-run boundary splits, and invalid storage inputs in stackdepot KUnit. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the private append-publication primitive from the userspace trie prototype. The helper builds a replacement child array around an unpublished appended chain and installs it into caller-owned root or parent storage only after validation succeeds. Cover root publication, parent publication, duplicate rejection, root replacement, and bad input handling in stackdepot KUnit. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Make the private append-publication helper read the current child array with READ_ONCE() and publish the replacement with release ordering. This keeps the helper safe for future lockless trie readers. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the private trie lookup-step classifier from the userspace trie prototype. The helper reads one root or parent child array with acquire ordering, compares the matching child node against caller frames, and reports whether the caller should append, descend, split, promote, or return an existing leaf. Keep the helper inert for now: it does not allocate, publish, or change stack_depot_save() and fetch routing. Cover append, descend, found, promote, split, and invalid-input classifications in stackdepot KUnit. Also make the counted-stack increment helper fail closed if the cmpxchg loser path observes a non-positive count instead of delegating that case to refcount_add(). Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Harden the private stackdepot trie preparation helpers before the backend starts routing production saves through them. The lookup step now keeps parent-chain validation with the multi-step walker that has the full matched prefix context, and the publication and scratch-buffer contracts document the required writer serialization and aliasing rules. Tighten page_owner stack-list accounting so a failed list-node allocation cannot leave an untracked marker count behind, and keep diagnostic stack counts from being resurrected after they reach zero. The arm64 frame compression helper now rejects the synthetic zero prefix explicitly. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add the private append-only insertion helper from the userspace trie prototype. The helper handles the case where no existing child starts with the next input frame: it preflights root or parent context, storage aliasing, existing-child state, and publication storage before building the unpublished append chain and publishing the replacement child array last. Cover root and parent append insertion, multi-run append insertion, zero-frame rejection, alias rejection, existing-child rejection, and failure atomicity in stackdepot KUnit. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Extend the private append-insertion helper so it can descend through fully matched trie nodes before appending the remaining stack suffix. The helper still rejects found, promote, and split cases so those operations can be implemented as separate, reviewable steps. Preflight descend storage against the published child arrays and subtrees before mutating caller-owned staging slots, preserving the copy-on-write publication contract. Cover one-level and multi-level descend insertion plus sibling-alias rejection in stackdepot KUnit. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Give stackdepot files an explicit MAINTAINERS section so stackdepot changes route to the mm tree and linux-kernel list directly instead of being matched only through the broad library-code entry. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Document the stackdepot prep assumptions that came up during review: arm64 frame compression uses adjacent high-bit buckets around the 2 GB module relocation window, saturated refcounts must fail positive-count tests, and page_owner keeps saturated stacks retryable when list marker tracking cannot be allocated. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Keep the trie and frame-run prep interfaces private to stackdepot so the public header only exposes APIs used outside lib/. The helpers are still inert, but their contracts now reject aliasing, overlong parent chains, count overflows, and untracked page_owner handles before later storage-routing patches can depend on them. Strengthen KUnit coverage for those edge cases and remove fixed-size test buffers so the tests scale with the configured stack depth. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Teach the private append insertion helper to promote a fully matched, childless internal trie node into a terminal leaf by publishing a copy-on-write replacement child array. Keep split and promote-with- children cases rejected until subtree COW support lands. Cover root-level promotion, descended promotion, and the childful rejection path in stackdepot KUnit. Also keep raw node matching on the direct raw-frame path so mismatch handling avoids the generic decoder. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Allow the private trie promotion path to promote internal nodes that already have children by carrying the child array into the replacement node and reparenting descendants before publication. This keeps the copy-on-write shape intact while preparing split insertion to preserve existing subtrees. Cover the childful promotion path in stackdepot KUnit and keep the test node-slot allocator limited to single-run inputs. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add a private helper that initializes a trie node from a contiguous slice of an existing node's frame run. This gives split insertion a copy-on-write building block for prefix and old-tail nodes without decoding or recompressing stored frame payloads. Cover raw, compressed, parent-chain, and invalid slice cases in stackdepot KUnit. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add a private helper that builds the child array for a future split prefix from the displaced old tail and an optional new stack tail. The helper keeps child ordering centralized and reuses existing child-array validation so split insertion can publish a fully initialized prefix subtree later. Cover one-child, sorted two-child, duplicate-key, short-storage, and storage-overlap cases in stackdepot KUnit. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
added 20 commits
June 25, 2026 14:02
Remove the remaining helper layers and defensive state that obscured the trie backend without enforcing real invariants. Keep page_owner on hash-backed countable records, make hash lookup separate plain, refcounted, and countable lifetimes, and let page_owner use struct stack_record counts directly. Fold single-use trie walkers, remove duplicated validation and derived side-table state, use RCU accessors consistently for published child arrays, and keep arch frame decompression hooks to the production contract. Add KUnit coverage for countable records not aliasing plain or refcounted hash records. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Document that trie-backed saves do not fall back to hash storage when trie insertion cannot proceed. This keeps trie_enabled pool pressure visible instead of mixing backends in the same run. Also fix a indentation issue in trie lookup. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Document that stack_depot_save() may return trie-backed handles when trie storage is enabled. Callers that need backend-independent stack contents must use stack_depot_fetch_into(), stack_depot_print(), or stack_depot_snprint(). Also tighten the stack_depot_fetch() kernel-doc to state that it only accepts hash-backed handles, matching the legacy pointer-returning API. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Make debugfs persistent counters explicitly hash-backed now that normal persistent saves can use trie storage. This avoids reading hash-only record counts as total stackdepot usage during trie validation. Also make the gdb stackdepot helper reject trie-backed handles instead of decoding them as hash pool offsets, and fix its pool-index diagnostic. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Initialize trie free-list buckets once during trie init instead of lazily checking and deriving that state from allocation paths. This removes repeated hot-path checks while keeping trie enablement as the single publication point for initialized trie state. Also remove a single-use transaction init wrapper, make side-table ID commit warn-only on impossible ordering, and drop a useless KUnit assertion that only checked a local initializer. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Type replacement child-array storage, warn when trie pool rollback cannot unwind, and avoid a redundant parent-chain length walk during trie lookup. Also keep arch frame decompression infallible to match the compressor contract, retry side-table boundary races once, and drop small page_owner and KUnit dead checks. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Keep the page_owner changes in this series limited to routing stack saves through countable stackdepot records. Drop the independent seq_file and threshold fixes, along with formatting-only churn, so those changes do not get buried in the trie series. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add a branch-restricted GitHub Actions workflow for running CodeQL on the stackdepot scratch branch. The workflow builds targeted kernel objects on ubuntu-latest, filters SARIF results to changed files, and uploads compact TSV artifacts for manual triage. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Use a shallow checkout for the scratch CodeQL workflow and fetch only the base branch tip needed for changed-file filtering. Compare the base tree directly with HEAD so the workflow avoids a full Linux history checkout. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Remove a dead trie leaf-ID bound check and make trie pool byte arithmetic explicit so CodeQL no longer has to infer GNU void pointer semantics. Move the KUnit stress-test completion and failure counter into test-managed storage so worker contexts do not reference parent stack state. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Add scratch CodeQL queries that flag normal error returns and state rediscovery in trusted stackdepot trie insertion helpers. These queries turn the review feedback into review tripwires for the scratch workflow without making them final kernel-tree checks. Wire the query pack into the existing scratch CodeQL workflow so its findings are included in the filtered TSV artifacts. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Rename the scratch CodeQL workflow and query pack around the workflow's actual purpose, then make the artifacts less likely to mislead review. The filtered TSV now records both the primary CodeQL location and the changed location that caused inclusion, while the workflow also uploads the generated config and target list used for each matrix job. Share common stackdepot query predicates across the custom queries and align their metadata with their role as review tripwires rather than proof of kernel correctness. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Broaden the node-size revalidation query after the first renamed CodeQL run showed it no longer matched known positive examples. Keep the query as a review tripwire by lowering its precision and describing the result as recomputing trie node size rather than proving a bug. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Delete the remaining transaction-shaped trie insertion machinery and narrow the helper contracts so insertion owns the append, split, promote, duplicate, side-table publication, and structural publication decisions directly. Keep page_owner on countable hash-backed saves, preserve caller-owned stack fetching for trie-capable callers, and drop review-only churn that is not required for trie storage. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Refresh the scratch CodeQL query pack around the current stackdepot trie implementation and add focused review tripwires: deleted abstraction shapes, trusted-helper errors, state rediscovery, NULL mode selectors, side-table publication ordering, once-primitives, KUnit-only hooks, and page_owner countable saves. Keep these checks scratch-only for the CodeQL branch; the final kernel branch must exclude the .github workflow and query files. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Bind the forbidden-abstraction query predicate so CodeQL can compile the scratch query pack, and use simpler string-based matching in the new tripwire queries to avoid version-fragile C/C++ library predicates. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Narrow the scratch CodeQL tripwires after the first successful run showed noise from legitimate trie structs, exported public APIs, correct countable page_owner saves, and line-order-only publication checks. Keep the queries focused on actionable review prompts so the next CodeQL run surfaces contract regressions instead of known-safe kernel patterns. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Require a ret-based failure guard immediately after trie publication before flagging publish-then-failure findings. This keeps the tripwire focused on real post-publication failure paths instead of matching independent branches. Also emit a stackdepot-only changed-file TSV artifact so custom query findings can be triaged separately from broader built-in CodeQL noise. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Remove the remaining trie helper state that made insertion look more complex than the underlying append, split, and promote operations require. Delete the side-table entry wrapper, derive free-node sizing from the free-list class, remove NULL-mode helper paths, and keep allocator cleanup local to the pool carving helper. Keep side-table publication and tail append as explicit operation-specific paths so expected failures happen before leaf publication and structural trie publication. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Drop follow-up churn that is not needed for the trie port and keep the caller and test changes focused on trie-capable handles. Use the backend-neutral stackdepot print helper in the DRM warning path, keep the DRM stack-depth cap documented, and avoid test naming that assumes plain saves are hash-backed. Also remove unnecessary include and Makefile comment churn from the cleanup. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
There was a problem hiding this comment.
Pull request overview
This PR extends stackdepot with a trie-based storage backend (including optional per-arch frame compression) and migrates key callers away from stack_depot_fetch() to a new backend-independent stack_depot_fetch_into() API. It also adds KUnit coverage for the new API/flags and introduces a GitHub Actions workflow plus custom CodeQL queries to help review/validate the new trie implementation.
Changes:
- Add trie-backed stackdepot storage (plus x86_64/arm64 frame compression hooks) and a new
stack_depot_fetch_into()API inlib/stackdepot.c/include/linux/stackdepot.h. - Update in-kernel users (SLUB, kmemleak, KMSAN, DRM modeset lock diagnostics, page_owner) to use trie-safe fetch/print paths and to request hash-backed storage where required (COUNTABLE).
- Add stackdepot KUnit tests and CodeQL automation (workflow + custom queries) targeting the new trie implementation.
Reviewed changes
Copilot reviewed 29 out of 30 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| mm/slub.c | Switch stack trace retrieval to stack_depot_fetch_into() using caller-owned buffers. |
| mm/page_owner.c | Save stacks via stack_depot_save_flags(... COUNTABLE ...) to ensure hash-backed/count-accessible records. |
| mm/kmsan/report.c | Use stack_depot_fetch_into() and reuse a fixed buffer for chained origins. |
| mm/kmsan/kmsan_test.c | Update stackdepot roundtrip test to use stack_depot_fetch_into(). |
| mm/kmemleak.c | Fetch into a fixed buffer to avoid relying on hash-backed contiguous storage. |
| lib/tests/stackdepot_kunit.c | New KUnit test suite covering fetch_into, flags behavior, extra bits, and arch compression hooks. |
| lib/tests/Makefile | Build the new stackdepot KUnit test when enabled. |
| lib/stackdepot.c | Major refactor: trie backend, side-table mapping, workspace + publication logic, new stack_depot_fetch_into(), and updated handle/flag behavior. |
| lib/Kconfig.debug | Add STACKDEPOT_KUNIT_TEST Kconfig option. |
| include/linux/stackdepot.h | Add COUNTABLE flag, stack_depot_fetch_into() API/docs, and adjust struct stack_record metadata. |
| include/asm-generic/stackdepot.h | Provide generic (no-compression) arch hooks for trie frame compression. |
| include/asm-generic/Kbuild | Export the new asm-generic/stackdepot.h header. |
| drivers/gpu/drm/drm_modeset_lock.c | Use stack_depot_snprint() for trie-safe stack rendering; define explicit max frame count. |
| arch/x86/include/asm/stackdepot.h | Add x86_64 frame compression/decompression hooks. |
| arch/um/include/asm/Kbuild | Ensure UML uses the generic stackdepot arch header. |
| arch/arm64/include/asm/stackdepot.h | Add arm64 frame compression/decompression hooks based on signed offset from _text. |
| .github/workflows/codeql.yml | New workflow to build selected objects and run CodeQL + custom queries. |
| .github/codeql/stackdepot/StackDepotTrustedHelperReturnEinval.ql | Custom query to flag direct -EINVAL returns in trusted trie helpers. |
| .github/codeql/stackdepot/StackDepotTrieStateRediscovery.ql | Custom query to flag “rediscovery” calls inside trusted insertion helpers. |
| .github/codeql/stackdepot/StackDepotTrieSidePublishInTrustedHelper.ql | Custom query to flag side-table publication inside trusted helpers. |
| .github/codeql/stackdepot/StackDepotTriePublishThenFailure.ql | Custom query to flag normal failure returns immediately after publication begins. |
| .github/codeql/stackdepot/StackDepotTrieOncePrimitive.ql | Custom query to flag trie-related READ_ONCE/WRITE_ONCE usage for review. |
| .github/codeql/stackdepot/StackDepotTrieNullModeSelector.ql | Custom query to flag pointer-NULL branching patterns in trusted helpers. |
| .github/codeql/stackdepot/StackDepotTrieNodeSizeRevalidation.ql | Custom query to flag defensive checks in __stack_depot_trie_node_size(). |
| .github/codeql/stackdepot/StackDepotPageOwnerCountableSaves.ql | Custom query to enforce COUNTABLE saves in page_owner. |
| .github/codeql/stackdepot/StackDepotKunitOnlyProductionHook.ql | Custom query to detect production helpers that appear to exist only for KUnit. |
| .github/codeql/stackdepot/StackDepotGenericStateCarrier.ql | Custom query to flag suspicious “generic carrier” trie structs. |
| .github/codeql/stackdepot/StackDepotForbiddenTrieAbstractions.ql | Custom query to prevent reintroducing deleted trie abstraction patterns. |
| .github/codeql/stackdepot/StackDepot.qll | Shared predicates for the custom stackdepot CodeQL query pack. |
| .github/codeql/stackdepot/qlpack.yml | CodeQL pack metadata for the custom stackdepot queries. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+3
to
+7
| on: | ||
| workflow_dispatch: | ||
| push: | ||
| branches: | ||
| - caleb/KRN-1117-stackdepot-port-codeql |
added 4 commits
July 7, 2026 11:05
Rename trie helpers and variables whose names still reflected removed abstractions or hid side effects. Make side-table ID selection, side-table slot backing, leaf publication, writer serialization, and structural publish helpers describe their actual contracts. Use payload terminology for arm64 compressed frames because the value is a signed _text offset rather than low address bits, and update the KUnit helper names to describe countable saves instead of hash internals. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Fold helper layers and defensive checks that made the trie insertion path look more general than its append, split, promote, and duplicate cases require. Keep expected failures ahead of side-table and structural publication, while preserving sorted child arrays, live tail append, and stackdepot pool reuse. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Sync the scratch CodeQL queries with the simplified trie helper names and deleted state carriers. Keep the tripwires focused on side-table publication, trusted helper boundaries, and state rediscovery after the kernel cleanup. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
Use insertion terminology for trie preallocation comments so the text does not suggest the deleted reservation or transaction machinery still exists. Signed-off-by: Caleb Kan <ckan@cloudflare.com>
caleb-kan
pushed a commit
that referenced
this pull request
Jul 22, 2026
commit 40ef3ed upstream. The current implementation uses pci_num_vf() while holding the memory_lock to prevent changing the power state of a PF when VFs are enabled. This creates a lockdep circular dependency warning because memory_lock is held during device probing. [ 286.997167] ====================================================== [ 287.003363] WARNING: possible circular locking dependency detected [ 287.009562] 7.0.0-dbg-DEV #3 Tainted: G S [ 287.015074] ------------------------------------------------------ [ 287.021270] vfio_pci_sriov_/18636 is trying to acquire lock: [ 287.026942] ff45bea2294d4968 (&vdev->memory_lock){+.+.}-{4:4}, at: vfio_pci_core_runtime_resume+0x1f/0xa0 [ 287.036530] [ 287.036530] but task is already holding lock: [ 287.042383] ff45bea3a96b8230 (&new_dev_set->lock){+.+.}-{4:4}, at: vfio_group_fops_unl_ioctl+0x44d/0x7b0 [ 287.051879] [ 287.051879] which lock already depends on the new lock. [ 287.051879] [ 287.060070] [ 287.060070] the existing dependency chain (in reverse order) is: [ 287.067568] [ 287.067568] -> #2 (&new_dev_set->lock){+.+.}-{4:4}: [ 287.073941] __mutex_lock+0x92/0xb80 [ 287.078058] vfio_assign_device_set+0x66/0x1b0 [ 287.083042] vfio_pci_core_register_device+0xd1/0x2a0 [ 287.088638] vfio_pci_probe+0xd2/0x100 [ 287.092933] local_pci_probe_callback+0x4d/0xa0 [ 287.098001] process_scheduled_works+0x2ca/0x680 [ 287.103158] worker_thread+0x1e8/0x2f0 [ 287.107452] kthread+0x10c/0x140 [ 287.111230] ret_from_fork+0x18e/0x360 [ 287.115519] ret_from_fork_asm+0x1a/0x30 [ 287.119983] [ 287.119983] -> #1 ((work_completion)(&arg.work)){+.+.}-{0:0}: [ 287.127219] __flush_work+0x345/0x490 [ 287.131429] pci_device_probe+0x2e3/0x490 [ 287.135979] really_probe+0x1f9/0x4e0 [ 287.140180] __driver_probe_device+0x77/0x100 [ 287.145079] driver_probe_device+0x1e/0x110 [ 287.149803] __device_attach_driver+0xe3/0x170 [ 287.154789] bus_for_each_drv+0x125/0x150 [ 287.159346] __device_attach+0xca/0x1a0 [ 287.163720] device_initial_probe+0x34/0x50 [ 287.168445] pci_bus_add_device+0x6e/0x90 [ 287.172995] pci_iov_add_virtfn+0x3c9/0x3e0 [ 287.177719] sriov_add_vfs+0x2c/0x60 [ 287.181838] sriov_enable+0x306/0x4a0 [ 287.186038] vfio_pci_core_sriov_configure+0x184/0x220 [ 287.191715] sriov_numvfs_store+0xd9/0x1c0 [ 287.196351] kernfs_fop_write_iter+0x13f/0x1d0 [ 287.201338] vfs_write+0x2be/0x3b0 [ 287.205286] ksys_write+0x73/0x100 [ 287.209233] do_syscall_64+0x14d/0x750 [ 287.213529] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 287.219120] [ 287.219120] -> #0 (&vdev->memory_lock){+.+.}-{4:4}: [ 287.225491] __lock_acquire+0x14c6/0x2800 [ 287.230048] lock_acquire+0xd3/0x2f0 [ 287.234168] down_write+0x3a/0xc0 [ 287.238019] vfio_pci_core_runtime_resume+0x1f/0xa0 [ 287.243436] __rpm_callback+0x8c/0x310 [ 287.247730] rpm_resume+0x529/0x6f0 [ 287.251765] __pm_runtime_resume+0x68/0x90 [ 287.256402] vfio_pci_core_enable+0x44/0x310 [ 287.261216] vfio_pci_open_device+0x1c/0x80 [ 287.265947] vfio_df_open+0x10f/0x150 [ 287.270148] vfio_group_fops_unl_ioctl+0x4a4/0x7b0 [ 287.275476] __se_sys_ioctl+0x71/0xc0 [ 287.279679] do_syscall_64+0x14d/0x750 [ 287.283975] entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 287.289559] [ 287.289559] other info that might help us debug this: [ 287.289559] [ 287.297582] Chain exists of: [ 287.297582] &vdev->memory_lock --> (work_completion)(&arg.work) --> &new_dev_set->lock [ 287.297582] [ 287.310023] Possible unsafe locking scenario: [ 287.310023] [ 287.315961] CPU0 CPU1 [ 287.320510] ---- ---- [ 287.325059] lock(&new_dev_set->lock); [ 287.328917] lock((work_completion)(&arg.work)); [ 287.336153] lock(&new_dev_set->lock); [ 287.342523] lock(&vdev->memory_lock); [ 287.346382] [ 287.346382] *** DEADLOCK *** [ 287.346382] [ 287.352315] 2 locks held by vfio_pci_sriov_/18636: [ 287.357125] #0: ff45bea208ed3e18 (&group->group_lock){+.+.}-{4:4}, at: vfio_group_fops_unl_ioctl+0x3e3/0x7b0 [ 287.367048] #1: ff45bea3a96b8230 (&new_dev_set->lock){+.+.}-{4:4}, at: vfio_group_fops_unl_ioctl+0x44d/0x7b0 [ 287.376976] [ 287.376976] stack backtrace: [ 287.381353] CPU: 191 UID: 0 PID: 18636 Comm: vfio_pci_sriov_ Tainted: G S 7.0.0-dbg-DEV #3 PREEMPTLAZY [ 287.381355] Tainted: [S]=CPU_OUT_OF_SPEC [ 287.381356] Call Trace: [ 287.381357] <TASK> [ 287.381358] dump_stack_lvl+0x54/0x70 [ 287.381361] print_circular_bug+0x2e1/0x300 [ 287.381363] check_noncircular+0xf9/0x120 [ 287.381364] ? __lock_acquire+0x5b4/0x2800 [ 287.381366] __lock_acquire+0x14c6/0x2800 [ 287.381368] ? pci_mmcfg_read+0x4f/0x220 [ 287.381370] ? pci_mmcfg_write+0x57/0x220 [ 287.381371] ? lock_acquire+0xd3/0x2f0 [ 287.381373] ? pci_mmcfg_write+0x57/0x220 [ 287.381374] ? lock_release+0xef/0x360 [ 287.381376] ? vfio_pci_core_runtime_resume+0x1f/0xa0 [ 287.381377] lock_acquire+0xd3/0x2f0 [ 287.381378] ? vfio_pci_core_runtime_resume+0x1f/0xa0 [ 287.381379] ? lock_is_held_type+0x76/0x100 [ 287.381382] down_write+0x3a/0xc0 [ 287.381382] ? vfio_pci_core_runtime_resume+0x1f/0xa0 [ 287.381383] vfio_pci_core_runtime_resume+0x1f/0xa0 [ 287.381384] ? __pfx_pci_pm_runtime_resume+0x10/0x10 [ 287.381385] __rpm_callback+0x8c/0x310 [ 287.381386] ? ktime_get_mono_fast_ns+0x3d/0xb0 [ 287.381389] ? __pfx_pci_pm_runtime_resume+0x10/0x10 [ 287.381390] rpm_resume+0x529/0x6f0 [ 287.381392] ? lock_is_held_type+0x76/0x100 [ 287.381394] __pm_runtime_resume+0x68/0x90 [ 287.381396] vfio_pci_core_enable+0x44/0x310 [ 287.381398] vfio_pci_open_device+0x1c/0x80 [ 287.381399] vfio_df_open+0x10f/0x150 [ 287.381401] vfio_group_fops_unl_ioctl+0x4a4/0x7b0 [ 287.381402] __se_sys_ioctl+0x71/0xc0 [ 287.381404] do_syscall_64+0x14d/0x750 [ 287.381405] ? entry_SYSCALL_64_after_hwframe+0x77/0x7f [ 287.381406] ? trace_irq_disable+0x25/0xd0 [ 287.381409] entry_SYSCALL_64_after_hwframe+0x77/0x7f Introduce a private flag 'sriov_active' in the vfio_pci_core_device struct. This allows the driver to track the SR-IOV power state requirement without relying on pci_num_vf() while holding the memory_lock. The lock is now only held to set the flag and ensure the device is in D0, after which pci_enable_sriov() can be called without the lock. Fixes: f4162eb ("vfio/pci: Change the PF power state to D0 before enabling VFs") Cc: stable@vger.kernel.org Suggested-by: Jason Gunthorpe <jgg@ziepe.ca> Suggested-by: Alex Williamson <alex@shazbot.org> Signed-off-by: Raghavendra Rao Ananta <rananta@google.com> Link: https://lore.kernel.org/r/20260514173449.3282188-1-rananta@google.com [promote bitfield to plain bool to avoid storage-unit races] Signed-off-by: Alex Williamson <alex@shazbot.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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.
No description provided.