{
  "affected": [
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:12",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:13",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "6.12.113-1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    },
    {
      "ecosystem_specific": {
        "urgency": "not yet assigned"
      },
      "package": {
        "ecosystem": "Debian:14",
        "name": "linux"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "7.2.9-1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "details": "In the Linux kernel, the following vulnerability has been resolved:  mm/rmap: fix missing barrier between anon_vma init and vma-\u003eanon_vma publish  On arm64 server, we find that a task trying to grab the anon_vma lock triggers hungtask.  INFO: task main:2354726 blocked for more than 120 seconds.       Tainted: G            E     5.10.0-0021.aarch64 #1 \"echo 0 \u003e /proc/sys/kernel/hung_task_timeout_secs\" disables this message. task:main            state:D stack:    0 pid:2354726 ppid:2350673 flags:0x00000a01 Call trace:  __switch_to+0x7c/0xbc  __schedule+0x3b4/0x8a0  schedule+0x50/0xe0  rwsem_down_write_slowpath+0x3cc/0x6cc  down_write+0x60/0x260  __anon_vma_prepare+0x6c/0x210  do_anonymous_page+0x258/0x660  handle_pte_fault+0x188/0x214  __handle_mm_fault+0x1b0/0x380  handle_mm_fault+0xf4/0x284  do_page_fault+0x19c/0x494  do_translation_fault+0xcc/0xf8  do_mem_abort+0x48/0xac  el0_da+0x44/0x80  el0_sync_handler+0x88/0xb4  el0_sync+0x160/0x180  After analyzing the vmcore, we found the anon_vma-\u003eroot-\u003erwsem.count is -1.  There is another anon_vma whose anon_vma-\u003eroot-\u003erwsem.count is 1, the anon_vma-\u003eroot-\u003erwsem.owner shows the lock is held, but the stack of the task shows the task doesn't hold the anon_vma lock.  After adding more debugging info, we found __anon_vma_prepare() reuses anon_vma and triggers the UAF of anon_vma-\u003eroot due to missing memory barrier, leading to locking and unlocking two different anon_vma-\u003eroot, thus leading to an anon_vma will never be unlocked, and another anon_vma couldn't be locked anymore.  This race requires two adjacent VMAs that are not merged but are anon_vma-compatible (e.g., they differ in VMA_ACCESS_FLAGS that can be changed by mprotect()).  Two threads fault on each VMA concurrently, both calling __anon_vma_prepare() with only mmap_lock held for reading.      THREAD A                             THREAD B __anon_vma_prepare                __anon_vma_prepare  find_mergeable_anon_vma() -\u003e NULL  anon_vma = anon_vma_alloc();    anon_vma-\u003eroot = anon_vma;  // the two stores may be reordered  vma-\u003eanon_vma = anon_vma;                                    // finds A's anon_vma                                    anon_vma = find_mergeable_anon_vma(vma);                                    anon_vma_lock_write(anon_vma);                                      // may still see the old root                                      down_write(\u0026anon_vma-\u003eroot-\u003erwsem);                                    anon_vma_unlock_write(anon_vma);                                      // see the new root, never unlock old                                      up_write(\u0026anon_vma-\u003eroot-\u003erwsem);  thread A triggers page fault and calls __anon_vma_prepare() to prepare anon_vma for the faulting vma.  __anon_vma_prepare() allocates and initializes a new anon_vma, and then publishes it to the vma with a plain store.  anon_vma_prepare() only requires the mmap_lock to be held for reading, so two threads can fault on adjacent VMAs at the same time.  While thread A publishes a new anon_vma, thread B could find the anon_vma via find_mergeable_anon_vma() and then locks anon_vma-\u003eroot-\u003erwsem.  The store to anon_vma-\u003eroot in anon_vma_alloc() and the store to vma-\u003eanon_vma can be reordered.  The anon_vma_lock_write() and spin_lock() only provide acquire semantics, which do not prevent prior stores from being reordered after them.  The release semantics of the corresponding spin_unlock() and anon_vma_unlock_write() come too late, the store to vma-\u003eanon_vma is already published before they take effect.  As a result, thread B can observe the following order:      vma-\u003eanon_vma = anon_vma;     anon_vma-\u003eroot = anon_vma;  The anon_vma slab is SLAB_TYPESAFE_BY_RCU, so a newly allocated anon_vma may reuse memory from a previously freed one.  The constructor (anon_vma_ctor) does not reset anon_vma-\u003eroot, and __put_anon_vma() doesn't clear it either, so the old root value persists until anon_vma_alloc() overwrites it.  If that store isn't v ---truncated---",
  "id": "DEBIAN-CVE-2026-98507",
  "modified": "2026-10-19T04:47:24.297677813Z",
  "references": [
    {
      "type": "ADVISORY",
      "url": "https://security-tracker.debian.org/tracker/CVE-2026-98507"
    }
  ],
  "upstream": [
    "CVE-2026-98507"
  ]
}