Skip to content

Caleb/krn 1117 stackdepot port codeql - #3

Draft
caleb-kan wants to merge 147 commits into
linux-6.18.yfrom
caleb/KRN-1117-stackdepot-port-codeql
Draft

Caleb/krn 1117 stackdepot port codeql#3
caleb-kan wants to merge 147 commits into
linux-6.18.yfrom
caleb/KRN-1117-stackdepot-port-codeql

Conversation

@caleb-kan

Copy link
Copy Markdown
Owner

No description provided.

Caleb Kan 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>
Caleb Kan 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>
Copilot AI review requested due to automatic review settings July 6, 2026 17:07
@caleb-kan
caleb-kan marked this pull request as draft July 6, 2026 17:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 in lib/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
Caleb Kan 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 caleb-kan self-assigned this Jul 9, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants