{"id":"CVE-2026-93241","revision":null,"records":[{"revision":"27dc8e832d1f477082d9b414101d2b2f","observedAt":"2026-10-23T15:48:27.903+00:00","statement":{"source":"cve-program","id":"CVE-2026-93241","aliases":[],"title":"memcg: bypass the reclaim and oom killer for dying tasks once oom_reaper is done","description":"In the Linux kernel, the following vulnerability has been resolved:\n\nmemcg: bypass the reclaim and oom killer for dying tasks once oom_reaper is done\n\nAt Meta, we are seeing instances where an OOM killed job is stuck in the\nexit path for several hours.  In one particular case, the job was stuck\nfor more than 8 hours and I had to manually remove the memory.max limits\nto allow the process to exit.\n\nThe job was a single process job and had ~55 GiB memory.max and zswap\nenabled.  It had almost 0 anon in memory and ~111 GiB in zswap compressed\nto ~51 GiB zswap pool (i.e.  almost all of memory.current was zswap). \nNothing was left on the LRUs to reclaim.\n\nOn further inspection, I observed ~20k threads of that process stuck with\nthe following stack:\n\n[<0>] mem_cgroup_out_of_memory+0x4e/0xa0\n[<0>] charge_memcg+0x8bf/0x990\n[<0>] mem_cgroup_swapin_charge_folio+0x4e/0x80\n[<0>] __read_swap_cache_async+0x10c/0x260\n[<0>] swapin_readahead+0x116/0x3f0\n[<0>] do_swap_page+0x13c/0x1ce0\n[<0>] handle_mm_fault+0x61d/0x11f0\n[<0>] do_user_addr_fault+0x3e7/0x6d0\n[<0>] exc_page_fault+0x8f/0x110\n[<0>] asm_exc_page_fault+0x22/0x30\n[<0>] __get_user_8+0x14/0x20\n[<0>] futex_cleanup+0x27/0x1c0\n[<0>] futex_exit_release+0x47/0x60\n[<0>] do_exit+0x107/0x940\n[<0>] do_group_exit+0x81/0xa0\n[<0>] get_signal+0x2b1/0x6e0\n[<0>] arch_do_signal_or_restart+0x1a/0x1c0\n[<0>] exit_to_user_mode_loop+0xa8/0x1c0\n[<0>] do_syscall_64+0x152/0x250\n[<0>] entry_SYSCALL_64_after_hwframe+0x4b/0x53\n\nIn addition the dmesg was filled with \"Out of memory and no killable\nprocesses...\" messages.\n\nI have no idea why oom reaper was not able to reap/unmap the process.  My\nguess is that since oom reaper tries to acquire mmap_lock in read mode\nlimited number of times and then gives up, there might be a thread of that\nprocess which had mmap_lock in write mode at that time.\n\nMy initial suspicion was the futex_cleanup and kernel page fault causing\ninfinite fault and charge retries but that was put to rest in previous\ndiscussions happened on similar problem [1].\n\nMy current theory is that it is just a simple slow serialization behind\nthe oom_lock.  Unlike page allocator, memcg charge code takes the oom_lock\nwithout the \"try\".  Though memcg oom code uses mutex_lock_killable(), note\nthat in the call stack get_signal() consumes SIGKILL (or\nsigdelset(SIGKILL)) before calling do_group_exit().  So this\nmutex_lock_killable() is just a mutex_lock() here.  Therefore 10s of\nthousands of threads are waiting on oom_lock and one by one they get\n-EFAULT from get_user() in the futex cleanup code and bails out.\n\nDiscussion from [1] led to commit a75ffa26122b (\"memcg, oom: do not bypass\noom killer for dying tasks\") which routes dying tasks into the OOM path\nprecisely so the oom_reaper can reap their mm and free the memory\nasynchronously.  But the reaper is best-effort and one-shot: if it cannot\ntake mmap_lock for read (e.g.  a sibling thread holds it for write) it\nsets MMF_OOM_SKIP and never retries, leaving only the glacial\noom_lock-serialized synchronous drain.\n\nOnce MMF_OOM_SKIP is set there is no more asynchronous reclaim coming for\nthe mm, so a dying task charging against it has nothing left to wait for:\nit frees its memory only once it finishes exiting.  Running reclaim and\nthe (no-victim) OOM killer for it is then pointless, and doing it for 10s\nof thousands of exiting threads is what serializes them behind oom_lock. \nSo before reclaim, if current is an OOM victim whose reaper is done, fail\nthe charge.\n\nReproduced with 20k threads, each parking a robust futex head on its own\nzswapped page, OOM-group-killed while a sibling holds mmap_lock for write\nso the reaper gives up and sets MMF_OOM_SKIP.  Tested on next-20260728 and\nbaseline show ~90 seconds exit time while with the patch the exit time\nreduced to ~3 seconds.","state":0,"publishedAt":"2026-09-24T15:34:36.237+00:00","modifiedAt":"2026-10-19T09:07:52.93+00:00","affected":[{"ecosystem":"Vendor product","name":"Linux","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"product\": \"Linux\",\n                    \"vendor\": \"Linux\",\n                    \"defaultStatus\": \"unaffected\",\n                    \"repo\": \"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git\",\n                    \"programFiles\": [\n                        \"mm/memcontrol.c\"\n                    ],\n                    \"versions\": [\n                        {\n                            \"version\": \"a75ffa26122bba4a3fa9372aa13b32d7a5590425\",\n                            \"lessThan\": \"801bcbdbfd595cc7f0de95f2802b5596c8971315\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"git\"\n                        },\n                        {\n                            \"version\": \"a75ffa26122bba4a3fa9372aa13b32d7a5590425\",\n                            \"lessThan\": \"d44c3c5986c7a4a5f913a813e18cda08a838f91b\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"git\"\n                        },\n                        {\n                            \"version\": \"a75ffa26122bba4a3fa9372aa13b32d7a5590425\",\n                            \"lessThan\": \"6b0d1083364fc8e7cc2f7d1f93ee3ee78f4d52f7\",\n                            \"status\": \"affected\",\n                            \"versionType\": \"git\"\n                        }\n                    ]\n                }"},{"ecosystem":"Vendor product","name":"Linux","ranges":[],"versions":[],"rawVersionEvidence":"{\n                    \"product\": \"Linux\",\n                    \"vendor\": \"Linux\",\n                    \"defaultStatus\": \"affected\",\n                    \"repo\": \"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git\",\n                    \"programFiles\": [\n                        \"mm/memcontrol.c\"\n                    ],\n                    \"versions\": [\n                        {\n                            \"version\": \"6.16\",\n                            \"status\": \"affected\"\n                        },\n                        {\n                            \"version\": \"0\",\n                            \"lessThan\": \"6.16\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        },\n                        {\n                            \"version\": \"6.18.51\",\n                            \"lessThanOrEqual\": \"6.18.*\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        },\n                        {\n                            \"version\": \"7.2.5\",\n                            \"lessThanOrEqual\": \"7.2.*\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"semver\"\n                        },\n                        {\n                            \"version\": \"7.3\",\n                            \"lessThanOrEqual\": \"*\",\n                            \"status\": \"unaffected\",\n                            \"versionType\": \"original_commit_for_fix\"\n                        }\n                    ]\n                }"}],"metrics":[],"references":["https://git.kernel.org/stable/c/801bcbdbfd595cc7f0de95f2802b5596c8971315","https://git.kernel.org/stable/c/d44c3c5986c7a4a5f913a813e18cda08a838f91b","https://git.kernel.org/stable/c/6b0d1083364fc8e7cc2f7d1f93ee3ee78f4d52f7"],"sourceUrl":"https://www.cve.org/CVERecord?id=CVE-2026-93241","license":"CVE Program Terms of Use","key":"cve-program:CVE-2026-93241","identifiers":["CVE-2026-93241"]},"retained":false,"historicalAffected":[]}],"coverage":[{"source":"cisa-kev:global","scope":"Complete CISA KEV catalog; all vendors. Missing entries do not establish absence of exploitation.","generation":"2026-11-09T02:08:49.7164208+00:00","complete":true,"records":1769,"lastAttemptAt":"2026-11-09T02:08:49.7164208+00:00","lastSuccessAt":"2026-11-09T02:08:49.9138759+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:49.9138791+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"cve-program","scope":"Official CVE Program baseline and cumulative hourly delta; all vendors, published and rejected records","generation":"cve-24e6fde7b744113daefb8f6135035fb8a5c69c9617c9c0d40574a0376532ffd3-2c51878ad7143765cecd1875e45367b3d7bc82d957efe97a97e8abc47229db89","complete":true,"records":421276,"lastAttemptAt":"2026-11-09T02:08:48.6040206+00:00","lastSuccessAt":"2026-11-09T02:08:48.5948774+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:48.6040206+00:00","snapshotPublishedAt":"2026-11-09T01:29:01+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"euvd","scope":"Rolling EUVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global EUVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-32d228e979494b54953746e62a2e4a72","complete":false,"records":13654,"lastAttemptAt":"2026-11-09T02:17:15.6922064+00:00","lastSuccessAt":"2026-11-09T02:17:15.7913434+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:17:15.7913434+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"first-epss:nuget","scope":"FIRST EPSS for explicit CVE aliases in the collected public NuGet archive. Not a global EPSS backfill.","generation":"2026-11-09T02:08:49.7164208+00:00","complete":true,"records":1096,"lastAttemptAt":"2026-11-09T02:08:49.7164208+00:00","lastSuccessAt":"2026-11-09T02:08:49.9145991+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:49.9145992+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"nvd","scope":"Rolling NVD lookups of CVE aliases in current public OSV archives; 500 identifiers per refresh, rechecked after 48 hours. Not a global NVD catalog. Successful not-found lookups count as checked; they do not imply withdrawal or safety. No reader inventory is sent.","generation":"enrichment-5a44a451442747cb81d83104fe1e7771","complete":true,"records":13666,"lastAttemptAt":"2026-11-09T02:08:52.2785198+00:00","lastSuccessAt":"2026-11-09T02:08:52.274+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:52.274+00:00","snapshotPublishedAt":null,"importing":false,"stagedRecords":0,"checkedIdentifiers":13706,"expectedIdentifiers":13706,"failedIdentifiers":0},{"source":"osv:Go","scope":"Complete OSV Go ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"go-980593e6977a6d1b4fb1eed5a1ffe88a468736f89f0a06f710924ad59132c023","complete":true,"records":9914,"lastAttemptAt":"2026-11-09T02:08:49.2635464+00:00","lastSuccessAt":"2026-11-08T11:07:07.068788+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:49.2635464+00:00","snapshotPublishedAt":"2026-11-08T11:02:46+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:NuGet","scope":"Complete OSV NuGet ecosystem archive, including GitHub Advisory Database records; NuGet version matching only","generation":"nuget-fde804134ecdda0ddd5ff5c26ee1fff5a6fa659311f7ef2e51c6ad54964db0e2","complete":true,"records":1971,"lastAttemptAt":"2026-11-09T02:08:48.7750517+00:00","lastSuccessAt":"2026-11-06T19:03:17.0399903+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:48.7750517+00:00","snapshotPublishedAt":"2026-11-06T18:17:57+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:crates.io","scope":"Complete OSV crates.io ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"crates.io-3b1150af6d7ada2c07356cbab4ead5224c1485027890f71c71d0742cddf0b9e8","complete":true,"records":3055,"lastAttemptAt":"2026-11-09T02:08:49.6317268+00:00","lastSuccessAt":"2026-11-09T00:02:23.4330288+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:49.6317268+00:00","snapshotPublishedAt":"2026-11-08T23:17:54+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null},{"source":"osv:npm","scope":"Complete OSV npm ecosystem archive, including withdrawn and malicious-package source records; statement counts are not unique CVE counts","generation":"npm-f8647d7ba64b1ba0dfdc7130944766d5b36d5b77d18fff0c79e651a4cff3c2b9","complete":true,"records":231293,"lastAttemptAt":"2026-11-09T02:08:49.149268+00:00","lastSuccessAt":"2026-11-08T11:06:56.2918717+00:00","error":null,"lastVerifiedAt":"2026-11-09T02:08:49.149268+00:00","snapshotPublishedAt":"2026-11-08T11:02:50+00:00","importing":false,"stagedRecords":0,"checkedIdentifiers":null,"expectedIdentifiers":null,"failedIdentifiers":null}]}