{ "dataType": "CVE_RECORD", "dataVersion": "5.2", "cveMetadata": { "cveId": "CVE-2024-40949", "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "state": "PUBLISHED", "assignerShortName": "Linux", "dateReserved": "2024-07-12T12:17:45.591Z", "datePublished": "2024-07-12T12:31:54.134Z", "dateUpdated": "2026-08-05T11:34:11.784Z" }, "containers": { "cna": { "providerMetadata": { "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "shortName": "Linux", "dateUpdated": "2026-08-05T11:34:11.784Z" }, "descriptions": [ { "lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nmm: shmem: fix getting incorrect lruvec when replacing a shmem folio\n\nWhen testing shmem swapin, I encountered the warning below on my machine. \nThe reason is that replacing an old shmem folio with a new one causes\nmem_cgroup_migrate() to clear the old folio's memcg data. As a result,\nthe old folio cannot get the correct memcg's lruvec needed to remove\nitself from the LRU list when it is being freed. This could lead to\npossible serious problems, such as LRU list crashes due to holding the\nwrong LRU lock, and incorrect LRU statistics.\n\nTo fix this issue, we can fallback to use the mem_cgroup_replace_folio()\nto replace the old shmem folio.\n\n[ 5241.100311] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x5d9960\n[ 5241.100317] head: order:4 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0\n[ 5241.100319] flags: 0x17fffe0000040068(uptodate|lru|head|swapbacked|node=0|zone=2|lastcpupid=0x3ffff)\n[ 5241.100323] raw: 17fffe0000040068 fffffdffd6687948 fffffdffd69ae008 0000000000000000\n[ 5241.100325] raw: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000\n[ 5241.100326] head: 17fffe0000040068 fffffdffd6687948 fffffdffd69ae008 0000000000000000\n[ 5241.100327] head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000\n[ 5241.100328] head: 17fffe0000000204 fffffdffd6665801 ffffffffffffffff 0000000000000000\n[ 5241.100329] head: 0000000a00000010 0000000000000000 00000000ffffffff 0000000000000000\n[ 5241.100330] page dumped because: VM_WARN_ON_ONCE_FOLIO(!memcg && !mem_cgroup_disabled())\n[ 5241.100338] ------------[ cut here ]------------\n[ 5241.100339] WARNING: CPU: 19 PID: 78402 at include/linux/memcontrol.h:775 folio_lruvec_lock_irqsave+0x140/0x150\n[...]\n[ 5241.100374] pc : folio_lruvec_lock_irqsave+0x140/0x150\n[ 5241.100375] lr : folio_lruvec_lock_irqsave+0x138/0x150\n[ 5241.100376] sp : ffff80008b38b930\n[...]\n[ 5241.100398] Call trace:\n[ 5241.100399] folio_lruvec_lock_irqsave+0x140/0x150\n[ 5241.100401] __page_cache_release+0x90/0x300\n[ 5241.100404] __folio_put+0x50/0x108\n[ 5241.100406] shmem_replace_folio+0x1b4/0x240\n[ 5241.100409] shmem_swapin_folio+0x314/0x528\n[ 5241.100411] shmem_get_folio_gfp+0x3b4/0x930\n[ 5241.100412] shmem_fault+0x74/0x160\n[ 5241.100414] __do_fault+0x40/0x218\n[ 5241.100417] do_shared_fault+0x34/0x1b0\n[ 5241.100419] do_fault+0x40/0x168\n[ 5241.100420] handle_pte_fault+0x80/0x228\n[ 5241.100422] __handle_mm_fault+0x1c4/0x440\n[ 5241.100424] handle_mm_fault+0x60/0x1f0\n[ 5241.100426] do_page_fault+0x120/0x488\n[ 5241.100429] do_translation_fault+0x4c/0x68\n[ 5241.100431] do_mem_abort+0x48/0xa0\n[ 5241.100434] el0_da+0x38/0xc0\n[ 5241.100436] el0t_64_sync_handler+0x68/0xc0\n[ 5241.100437] el0t_64_sync+0x14c/0x150\n[ 5241.100439] ---[ end trace 0000000000000000 ]---\n\n[baolin.wang@linux.alibaba.com: remove less helpful comments, per Matthew]" } ], "metrics": [ { "cvssV3_1": { "version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "baseScore": 7.8, "baseSeverity": "HIGH" }, "scenarios": [ { "lang": "en", "value": "AV:L - The path is reached from a local process — a page fault or read on a shmem-backed mapping (`shmem_fault` → `shmem_get_folio_gfp` → `shmem_swapin_folio` → `shmem_replace_folio`), or a DRM GEM ioctl that pins a swapped-out shmem-backed buffer object. No network or remote peer data is involved.\nAC:L - Once the zone-mismatch replace path is taken, the wrong lruvec is obtained deterministically, and the attacker controls both sides of the resulting LRU list race — allocating and unpinning GEM buffer objects, driving memory pressure to force swap-out, shaping swap-cluster layout so readahead brings the folio back in the wrong zone, then generating concurrent LRU churn in the same memcg. The whole sequence is repeatable in a loop with no condition outside attacker influence; CONFIG_MEMCG with a non-root cgroup is the default on systemd, Android and container hosts.\nPR:L - Only an ordinary unprivileged local account is needed — no capability, LSM or namespace check exists anywhere between the syscall/fault entry and `shmem_replace_folio()`, and DRM render nodes (`/dev/dri/renderD*`) that back the zone-constrained shmem mappings are routinely accessible to logged-in users, Android apps and VM guests.\nUI:N - The attacker triggers the swap-out and swap-in of its own shmem/GEM pages entirely within its own process; no action by any other user or administrator is required.\nS:U - The corruption is confined to kernel memory-management structures within the same security authority; no VM, IOMMU or sandbox boundary is crossed.\nC:H - Manipulating a memcg LRU list under the wrong `lru_lock` corrupts the list and its size counters, which can leave a freed folio linked or cause reclaim to evict/reuse a still-mapped page, exposing another process's or the kernel's data; per kernel CNA guidance, memory corruption of this kind is scored as a potential arbitrary-read primitive.\nI:H - `list_del()` performed without the lock that protects the list gives an unsynchronized unlink write (`prev->next = next; next->prev = prev`) through pointers that a racing `list_add` can leave stale, yielding a write primitive into `struct page`/`folio` memory, plus corrupted `lru_zone_size` accounting — a classic path to heap grooming and control-flow hijack.\nA:H - The commit explicitly warns of \"LRU list crashes due to holding the wrong LRU lock\"; in practice this produces list-corruption BUGs, GPFs, and `mem_cgroup_update_lru_size()`'s `WARN_ONCE`/`VM_BUG_ON(1)` on negative sizes, and the skewed LRU counters can drive reclaim into looping or premature OOM — all kernel-wide denial of service." } ] } ], "affected": [ { "product": "Linux", "vendor": "Linux", "defaultStatus": "unaffected", "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git", "programFiles": [ "mm/memcontrol.c", "mm/shmem.c" ], "versions": [ { "version": "85ce2c517ade0d51b7ad95f2e88be9bbe294379a", "lessThan": "8c6c3719ebb7913f8a665d11816d2e38b0eadbab", "status": "affected", "versionType": "git" }, { "version": "85ce2c517ade0d51b7ad95f2e88be9bbe294379a", "lessThan": "9094b4a1c76cfe84b906cc152bab34d4ba26fa5c", "status": "affected", "versionType": "git" } ] }, { "product": "Linux", "vendor": "Linux", "defaultStatus": "affected", "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git", "programFiles": [ "mm/memcontrol.c", "mm/shmem.c" ], "versions": [ { "version": "6.7", "status": "affected" }, { "version": "0", "lessThan": "6.7", "status": "unaffected", "versionType": "semver" }, { "version": "6.9.7", "lessThanOrEqual": "6.9.*", "status": "unaffected", "versionType": "semver" }, { "version": "6.10", "lessThanOrEqual": "*", "status": "unaffected", "versionType": "original_commit_for_fix" } ] } ], "cpeApplicability": [ { "nodes": [ { "operator": "OR", "negate": false, "cpeMatch": [ { "vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.7", "versionEndExcluding": "6.9.7" }, { "vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.7", "versionEndExcluding": "6.10" } ] } ] } ], "references": [ { "url": "https://git.kernel.org/stable/c/8c6c3719ebb7913f8a665d11816d2e38b0eadbab" }, { "url": "https://git.kernel.org/stable/c/9094b4a1c76cfe84b906cc152bab34d4ba26fa5c" } ], "title": "mm: shmem: fix getting incorrect lruvec when replacing a shmem folio", "x_generator": { "engine": "bippy-1.2.0" } }, "adp": [ { "providerMetadata": { "orgId": "af854a3a-2127-422b-91ae-364da2661108", "shortName": "CVE", "dateUpdated": "2024-08-02T04:39:55.330Z" }, "title": "CVE Program Container", "references": [ { "url": "https://git.kernel.org/stable/c/8c6c3719ebb7913f8a665d11816d2e38b0eadbab", "tags": [ "x_transferred" ] }, { "url": "https://git.kernel.org/stable/c/9094b4a1c76cfe84b906cc152bab34d4ba26fa5c", "tags": [ "x_transferred" ] } ] }, { "metrics": [ { "other": { "type": "ssvc", "content": { "id": "CVE-2024-40949", "role": "CISA Coordinator", "options": [ { "Exploitation": "none" }, { "Automatable": "no" }, { "Technical Impact": "partial" } ], "version": "2.0.3", "timestamp": "2024-09-10T17:04:04.999520Z" } } } ], "title": "CISA ADP Vulnrichment", "providerMetadata": { "orgId": "134c704f-9b21-4f2e-91b3-4a467353bcc0", "shortName": "CISA-ADP", "dateUpdated": "2024-09-11T17:34:24.967Z" } } ] } }