Skip to content

[BUG] linux-cachyos 7.2.4-1: TTM NULL dereference after global OOM on RX 7800 XT #1058

Closed

Description

@nekomario28

This is a CachyOS package report for a TTM Oops that may be covered by recent upstream fixes.

Pre-flight:

  • Existing issues were searched. [BUG] amdgpu TTM eviction livelock causes multi-second desktop freezes during Proton gaming (RX 9070 XT) #926 covers a different TTM eviction livelock on RX 9070 XT; this report has a global OOM followed by a NULL dereference in ttm_resource_add_bulk_move().
  • The current CachyOS 7.2.6 source was checked and still contains the old if (!ret) condition, but 7.2.6 has not been boot-tested on the affected host.
  • Arch vanilla and an untainted upstream kernel have not been tested. No native kernel A/B will be performed on this host.

I hit a kernel Oops in the AMDGPU/TTM swapout path on a Radeon RX 7800 XT. The
failure happened immediately after a global OOM condition and was followed by an
RCU stall and a host reset.

The kernel was 7.2.4-1-cachyos on CachyOS. The GPU is a Sapphire Navi32 / RX
7800 XT (1002:747e, subsystem 1da2:475d). The relevant userspace versions
were Mesa 26.2.2-2, KWin/Plasma 6.7.5-1.1, and libdrm 2.4.134-1.1.

The first failure in the affected boot was:

kswapd0 invoked oom-killer: gfp_mask=0xcc0(GFP_KERNEL), order=0
oom-kill: ... global_oom ...
Out of memory: Killed process <redacted>

amdgpu 0000:03:00.0: [drm] *ERROR* Not enough memory for command submission!
WARNING: drivers/gpu/drm/ttm/ttm_resource.c:235
    at ttm_resource_add_bulk_move+0x124/0x150 [ttm]
BUG: kernel NULL pointer dereference, address: 0000000000000008
Oops: Oops: 0000 [#1] SMP NOPTI
RIP: ttm_resource_add_bulk_move+0xc9/0x150 [ttm]

The call chain was:

ttm_resource_add_bulk_move
ttm_resource_alloc
ttm_bo_swapout_cb
ttm_lru_walk_for_evict
ttm_bo_swapout
ttm_global_swapout
ttm_tt_populate
ttm_bo_populate
ttm_bo_vm_fault_reserved
amdgpu_gem_fault

After the Oops, an amdgpu KFD cleanup worker and an amdgpu_drm_release
path were both blocked on TTM-related spinlocks. The journal does not contain
Kernel panic - not syncing; I am calling this an Oops followed by a lockup or
reset, not a confirmed formal panic.

This looks related to the recent TTM fixes:

  • 3db7d7d
    fixes swapped-out resources remaining in a bulk_move range.
  • fcfe647
    changes the cleanup condition after ttm_tt_swapout() from if (!ret) to
    if (ret > 0).

I checked the source release used for linux-cachyos 7.2.4-1:
cachyos-7.2.4-1.
It still contains:

ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
if (!ret) {
        ttm_resource_del_bulk_move_unevictable(bo->resource, bo);
        ttm_resource_move_to_lru_tail(bo->resource);
}

The installed ttm.ko has the matching test eax,eax / jne branch, so the
installed binary also has the old zero-only condition. The CachyOS 7.2.4
packaging recipe does not list a TTM bulk-move patch. The current
cachyos-7.2.6-1 source release also still contains if (!ret) at this call
site; 7.2.6 has not been boot-tested on the affected host.

The kernel was tainted with CPU_OUT_OF_SPEC, OOT_MODULE, and
UNSIGNED_MODULE; the Oops also set WARN and DIE.

Does this match the stale bulk_move endpoint issue fixed by 3db7d7d/fcfe647,
and should those fixes be backported to kernels based on 7.2.4?

Activity

  1. kvnloo commented on Sep 20, 2026

    @kvnloo

    One backport detail that may be worth making explicit: "3db7d7d" should not be taken by itself.

    I traced both upstream commits. "3db7d7d" intended to change the condition after "ttm_tt_swapout()", but the one-line change was accidentally applied to the earlier "ttm_resource_try_charge()" check instead. "fcfe647" then does two things together:

    1. restores "ttm_resource_try_charge()" from "if (ret > 0)" back to "if (ret)";
    2. changes the intended swapout condition from "if (!ret)" to "if (ret > 0)".

    Both commits carry "Cc: stable@vger.kernel.org # v7.1+".

    I also checked "cachyos-7.2.6-1", and its "ttm_bo_swapout_cb()" still has the old "if (!ret)" condition.

    So if this is backported before the corresponding stable update lands, I think the safe unit is the corrected two-commit state rather than cherry-picking "3db7d7d" alone.

  2. nekomario28 commented on Sep 25, 2026

    @nekomario28
    Author

    A ready-to-apply backport for the swapout-site condition, verified against the cachyos-7.2.7-1 source release (patch --dry-run -p1 applies with zero fuzz; a real apply produces the intended if (ret > 0) in ttm_bo_swapout_cb()).

    Upstream fcfe64715b carries two hunks: (1) revert the misapplied if (ret > 0) in ttm_bo_alloc_at_place(), and (2) change the intended if (!ret) in ttm_bo_swapout_cb() to if (ret > 0). CachyOS 7.2.x does not carry 3db7d7d, so hunk (1) is unnecessary — this is the swapout-site hunk only:

    From fcfe64715b425262af1b36f498f9197f3537ceed Mon Sep 17 00:00:00 2001
    From: Vadim Nikitushkin <bub4z0r@gmail.com>
    Date: Thu, 10 Sep 2026 17:34:51 +0300
    Subject: [PATCH] drm/ttm: apply the swapout bulk_move fix to the intended
     condition (backport hunk)
    
    Backport of the swapout-site hunk of upstream fcfe647
    ("drm/ttm: apply the swapout bulk_move fix to the intended condition").
    CachyOS 7.2.x does not carry 3db7d7d, so the companion revert hunk in
    ttm_bo_alloc_at_place() is not needed; only the ttm_bo_swapout_cb()
    condition change applies.
    
    ttm_tt_swapout() returns the number of pages swapped out on success
    (>0 for a populated ttm), so gating the bulk_move removal on "if (!ret)"
    skips it on every successful swapout. A swapped-out resource then stays
    inside its BO's bulk_move range while unevictable; a later
    ttm_resource_free()/ttm_bo_set_bulk_move() skips it via the
    !ttm_resource_unevictable() guard and the range endpoint dangles —
    seen as WARN in ttm_lru_bulk_move_add(), "list_del corruption" in
    ttm_resource_move_to_lru_tail(), or NULL dereference in
    ttm_resource_add_bulk_move()/ttm_resource_manager_next().
    
    Observed on RX 7800 XT (Navi32): kernel NULL dereference in
    ttm_resource_add_bulk_move+0xc9 after a global OOM, reached via
    amdgpu_gem_fault -> ttm_tt_populate -> ttm_global_swapout, followed by
    an RCU stall and host reset (CachyOS/linux-cachyos issue #1058).
    
    Fixes: b2ed01e7ad3d ("drm/ttm: Fix ttm_bo_swapout() infinite LRU walk on swapout failure")
    Upstream: fcfe64715b425262af1b36f498f9197f3537ceed (Cc: stable # v7.1+)
    Signed-off-by: Vadim Nikitushkin <bub4z0r@gmail.com>
    ---
     drivers/gpu/drm/ttm/ttm_bo.c | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
    --- a/drivers/gpu/drm/ttm/ttm_bo.c
    +++ b/drivers/gpu/drm/ttm/ttm_bo.c
    @@ -1343,7 +1343,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
     
     	if (ttm_tt_is_populated(tt)) {
     		ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
    -		if (!ret) {
    +		if (ret > 0) {
     			spin_lock(&bdev->lru_lock);
     			ttm_resource_del_bulk_move_unevictable(bo->resource, bo);
     			ttm_resource_move_to_lru_tail(bo->resource);

    To carry it ahead of the stable queue: drop the file into kernel-patches under 7.2/misc/ and add one source+=() line in the PKGBUILD. fcfe647 already has Cc: stable # v7.1+, so the same line will arrive via the next 7.2.y regardless — this just skips the wait.

  3. nekomario28 commented on Oct 24, 2026

    @nekomario28
    Author

    Closing this, as the issue is fixed upstream now.

    • Fixed in Linux 7.2.8 (commit 1169fe8c11ca45e3f91d59a73eb271d0ca8a7fb0), and assigned CVE-2026-98166.
    • The developer reply linked above confirmed the crash signature matches the dangling bulk_move endpoint fixed by 3db7d7d / fcfe647.

    Thanks to everyone who helped with the confirmation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions