{"id":"CVE-2026-90201","summary":"net: page_pool: fix UAF in __page_pool_release_netmem_dma on xa_cmpxchg race","details":"In the Linux kernel, the following vulnerability has been resolved:\n\nnet: page_pool: fix UAF in __page_pool_release_netmem_dma on xa_cmpxchg race\n\nThis bug was discovered while testing the hns3 driver under channel\nreconfiguration (`ethtool -L` / `ethtool -G`) with iperf3 traffic on\narm64. The race is intermittently triggered when page_pool_destroy()\nruns page_pool_scrub() concurrently with page return via\npage_pool_put_netmem() on a different CPU. A WARN in\npage_pool_clear_pp_info() surfaced the dangling DMA index bits left\nby the cmpxchg loser, which led to the investigation.\n\npage_pool_scrub() iterates pool-\u003edma_mapped via xa_for_each() with no\npage ref held. __page_pool_release_netmem_dma() currently reads and\nwrites netmem fields (dma_addr, DMA index bits in pp_magic) after\nxa_cmpxchg() returns. The unref path calls put_page() unconditionally\nregardless of the cmpxchg outcome; when it loses the cmpxchg, it still\nfrees the page before the scrub winner finishes these netmem accesses,\nso scrub touches a freed page -- a Use-After-Free.\n\nFix this by splitting the DMA release into two functions:\n\n1. __page_pool_unmap_netmem_dma() caches dma_addr before xa_cmpxchg(),\n   does the cmpxchg to remove the DMA mapping, and calls dma_unmap on\n   the cached address. It never touches netmem fields after the cmpxchg,\n   making it safe for the scrub path which holds no page ref.\n\n2. __page_pool_release_netmem_dma() wraps the above and additionally\n   clears dma_addr and DMA index bits in netmem fields. This is safe\n   only when the caller holds a page ref, so it is used by the return\n   path (page_pool_return_netmem).\n\nThe scrub path calls __page_pool_unmap_netmem_dma() directly; the return\npath calls __page_pool_release_netmem_dma().","modified":"2026-10-28T02:31:05.381482687Z","published":"2026-09-17T16:07:18.838Z","related":["openSUSE-SU-2026:11880-1"],"database_specific":{"osv_generated_from":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/90xxx/CVE-2026-90201.json","cna_assigner":"Linux"},"references":[{"type":"WEB","url":"https://git.kernel.org/stable/c/24ef02f934eeb48830cff6b739abc3c62b1d107b"},{"type":"WEB","url":"https://git.kernel.org/stable/c/424a9fc4876cc7f28e9cb0aa8d92e920d726e350"},{"type":"WEB","url":"https://git.kernel.org/stable/c/9b65b0253ad5a66f73efee9a79a21a1e2b57cf59"},{"type":"WEB","url":"https://git.kernel.org/stable/c/bbfef303f980c1c078b8fa142e10a0e2fbcdd247"},{"type":"ADVISORY","url":"https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/90xxx/CVE-2026-90201.json"},{"type":"ADVISORY","url":"https://nvd.nist.gov/vuln/detail/CVE-2026-90201"},{"type":"PACKAGE","url":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"}],"affected":[{"ranges":[{"type":"GIT","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","events":[{"introduced":"4f51fb0d257ff4d406ec27966902de075e3b118e"},{"fixed":"bbfef303f980c1c078b8fa142e10a0e2fbcdd247"}]},{"type":"GIT","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","events":[{"introduced":"ee62ce7a1d909ccba0399680a03c2dee83bcae95"},{"fixed":"424a9fc4876cc7f28e9cb0aa8d92e920d726e350"},{"fixed":"9b65b0253ad5a66f73efee9a79a21a1e2b57cf59"},{"fixed":"24ef02f934eeb48830cff6b739abc3c62b1d107b"}]},{"type":"GIT","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","events":[{"introduced":"6.12.34"},{"fixed":"6.12.110"}]},{"type":"GIT","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","events":[{"introduced":"6.15.3"},{"fixed":"6.16"}]},{"type":"GIT","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","events":[{"introduced":"c30ae60f41f9edd6e1b5cad41cf28ce04dae39e4"}]}],"versions":["v6.12.109","v6.12.108","v6.12.107","v6.12.106","v6.12.105","v6.12.104","v6.12.103","v6.12.102","v6.12.101","v6.12.100","v6.12.99","v6.12.98","v6.12.97","v6.12.96","v6.12.95","v6.12.94","v6.12.93","v6.12.92","v6.12.91","v6.12.90","v6.12.89","v6.12.88","v6.12.87","v6.12.86","v6.12.85","v6.12.84","v6.12.83","v6.12.82","v6.12.81","v6.12.80","v6.12.79","v6.12.78","v6.12.77","v6.12.76","v6.12.75","v6.12.74","v6.12.73","v6.12.72","v6.12.71","v6.12.70","v6.12.69","v6.12.68","v6.12.67","v6.12.66","v6.12.65","v6.12.64","v6.12.63","v6.12.62","v6.12.61","v6.12.60","v6.12.59","v6.12.58","v6.12.57","v6.12.56","v6.12.55","v6.12.54","v6.12.53","v6.12.52","v6.12.51","v6.12.50","v6.12.49","v6.12.48","v6.12.47","v6.12.46","v6.12.45","v6.12.44","v6.12.43","v6.12.42","v6.12.41","v6.12.40","v6.12.39","v6.12.38","v6.12.37","v6.12.36","v6.12.35","v6.12.34","v6.15.11","v6.15.10","v6.15.9","v6.15.8","v6.15.7","v6.15.6","v6.15.5","v6.15.4","v6.15.3"],"database_specific":{"source":"https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-90201.json"}},{"package":{"name":"Kernel","ecosystem":"Linux"},"ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0"},{"fixed":"6.12.110"}]},{"type":"ECOSYSTEM","events":[{"introduced":"6.13.0"},{"fixed":"6.18.52"}]},{"type":"ECOSYSTEM","events":[{"introduced":"6.16.0"},{"fixed":"7.2.6"}]}],"database_specific":{"source":"https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-90201.json"}}],"schema_version":"1.9.2"}