Show plain JSON{"configurations": [{"nodes": [{"cpeMatch": [{"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "matchCriteriaId": "73AB7DAD-2B10-4FC2-84A0-E5F06C6F1489", "versionEndExcluding": "6.6.51", "versionStartIncluding": "4.3", "vulnerable": true}, {"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "matchCriteriaId": "ACDEE48C-137A-4731-90D0-A675865E1BED", "versionEndExcluding": "6.10.10", "versionStartIncluding": "6.7", "vulnerable": true}, {"criteria": "cpe:2.3:o:linux:linux_kernel:6.11:rc1:*:*:*:*:*:*", "matchCriteriaId": "8B3CE743-2126-47A3-8B7C-822B502CF119", "vulnerable": true}, {"criteria": "cpe:2.3:o:linux:linux_kernel:6.11:rc2:*:*:*:*:*:*", "matchCriteriaId": "4DEB27E7-30AA-45CC-8934-B89263EF3551", "vulnerable": true}, {"criteria": "cpe:2.3:o:linux:linux_kernel:6.11:rc3:*:*:*:*:*:*", "matchCriteriaId": "E0005AEF-856E-47EB-BFE4-90C46899394D", "vulnerable": true}, {"criteria": "cpe:2.3:o:linux:linux_kernel:6.11:rc4:*:*:*:*:*:*", "matchCriteriaId": "39889A68-6D34-47A6-82FC-CD0BF23D6754", "vulnerable": true}, {"criteria": "cpe:2.3:o:linux:linux_kernel:6.11:rc5:*:*:*:*:*:*", "matchCriteriaId": "B8383ABF-1457-401F-9B61-EE50F4C61F4F", "vulnerable": true}, {"criteria": "cpe:2.3:o:linux:linux_kernel:6.11:rc6:*:*:*:*:*:*", "matchCriteriaId": "B77A9280-37E6-49AD-B559-5B23A3B1DC3D", "vulnerable": true}], "negate": false, "operator": "OR"}]}], "cveTags": [], "descriptions": [{"lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nuserfaultfd: fix checks for huge PMDs\n\nPatch series \"userfaultfd: fix races around pmd_trans_huge() check\", v2.\n\nThe pmd_trans_huge() code in mfill_atomic() is wrong in three different\nways depending on kernel version:\n\n1. The pmd_trans_huge() check is racy and can lead to a BUG_ON() (if you hit\n the right two race windows) - I've tested this in a kernel build with\n some extra mdelay() calls. See the commit message for a description\n of the race scenario.\n On older kernels (before 6.5), I think the same bug can even\n theoretically lead to accessing transhuge page contents as a page table\n if you hit the right 5 narrow race windows (I haven't tested this case).\n2. As pointed out by Qi Zheng, pmd_trans_huge() is not sufficient for\n detecting PMDs that don't point to page tables.\n On older kernels (before 6.5), you'd just have to win a single fairly\n wide race to hit this.\n I've tested this on 6.1 stable by racing migration (with a mdelay()\n patched into try_to_migrate()) against UFFDIO_ZEROPAGE - on my x86\n VM, that causes a kernel oops in ptlock_ptr().\n3. On newer kernels (>=6.5), for shmem mappings, khugepaged is allowed\n to yank page tables out from under us (though I haven't tested that),\n so I think the BUG_ON() checks in mfill_atomic() are just wrong.\n\nI decided to write two separate fixes for these (one fix for bugs 1+2, one\nfix for bug 3), so that the first fix can be backported to kernels\naffected by bugs 1+2.\n\n\nThis patch (of 2):\n\nThis fixes two issues.\n\nI discovered that the following race can occur:\n\n mfill_atomic other thread\n ============ ============\n <zap PMD>\n pmdp_get_lockless() [reads none pmd]\n <bail if trans_huge>\n <if none:>\n <pagefault creates transhuge zeropage>\n __pte_alloc [no-op]\n <zap PMD>\n <bail if pmd_trans_huge(*dst_pmd)>\n BUG_ON(pmd_none(*dst_pmd))\n\nI have experimentally verified this in a kernel with extra mdelay() calls;\nthe BUG_ON(pmd_none(*dst_pmd)) triggers.\n\nOn kernels newer than commit 0d940a9b270b (\"mm/pgtable: allow\npte_offset_map[_lock]() to fail\"), this can't lead to anything worse than\na BUG_ON(), since the page table access helpers are actually designed to\ndeal with page tables concurrently disappearing; but on older kernels\n(<=6.4), I think we could probably theoretically race past the two\nBUG_ON() checks and end up treating a hugepage as a page table.\n\nThe second issue is that, as Qi Zheng pointed out, there are other types\nof huge PMDs that pmd_trans_huge() can't catch: devmap PMDs and swap PMDs\n(in particular, migration PMDs).\n\nOn <=6.4, this is worse than the first issue: If mfill_atomic() runs on a\nPMD that contains a migration entry (which just requires winning a single,\nfairly wide race), it will pass the PMD to pte_offset_map_lock(), which\nassumes that the PMD points to a page table.\n\nBreakage follows: First, the kernel tries to take the PTE lock (which will\ncrash or maybe worse if there is no \"struct page\" for the address bits in\nthe migration entry PMD - I think at least on X86 there usually is no\ncorresponding \"struct page\" thanks to the PTE inversion mitigation, amd64\nlooks different).\n\nIf that didn't crash, the kernel would next try to write a PTE into what\nit wrongly thinks is a page table.\n\nAs part of fixing these issues, get rid of the check for pmd_trans_huge()\nbefore __pte_alloc() - that's redundant, we're going to have to check for\nthat after the __pte_alloc() anyway.\n\nBackport note: pmdp_get_lockless() is pmd_read_atomic() in older kernels."}, {"lang": "es", "value": "En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: userfaultfd: corregir comprobaciones para PMD enormes Serie de parches \"userfaultfd: corregir ejecuci\u00f3ns en torno a la comprobaci\u00f3n pmd_trans_huge()\", v2. El c\u00f3digo pmd_trans_huge() en mfill_atomic() es incorrecto de tres maneras diferentes seg\u00fan la versi\u00f3n del kernel: 1. La comprobaci\u00f3n pmd_trans_huge() es r\u00e1pida y puede llevar a un BUG_ON() (si alcanza las dos ventanas de ejecuci\u00f3n correctas) - He probado esto en una compilaci\u00f3n del kernel con algunas llamadas mdelay() adicionales. Vea el mensaje de confirmaci\u00f3n para obtener una descripci\u00f3n del escenario de ejecuci\u00f3n. En kernels m\u00e1s antiguos (antes de 6.5), creo que el mismo error puede incluso te\u00f3ricamente llevar a acceder a los contenidos de la p\u00e1gina transhuge como una tabla de p\u00e1ginas si alcanza las 5 ventanas de ejecuci\u00f3n estrechas correctas (no he probado este caso). 2. Como se\u00f1al\u00f3 Qi Zheng, pmd_trans_huge() no es suficiente para detectar PMD que no apuntan a tablas de p\u00e1ginas. En kernels m\u00e1s antiguos (anteriores a 6.5), solo tendr\u00edas que ganar una \u00fanica ejecuci\u00f3n bastante amplia para alcanzar esto. He probado esto en 6.1 estable haciendo una ejecuci\u00f3n de migraci\u00f3n (con un mdelay() parcheado en try_to_migrate()) contra UFFDIO_ZEROPAGE - en mi VM x86, eso causa un error de kernel en ptlock_ptr(). 3. En kernels m\u00e1s nuevos (>=6.5), para asignaciones shmem, khugepaged puede arrancar tablas de p\u00e1ginas de debajo de nosotros (aunque no lo he probado), as\u00ed que creo que las comprobaciones BUG_ON() en mfill_atomic() son simplemente incorrectas. Decid\u00ed escribir dos correcciones separadas para estos (una correcci\u00f3n para los errores 1+2, una correcci\u00f3n para el error 3), de modo que la primera correcci\u00f3n pueda ser retroportada a kernels afectados por errores 1+2. Este parche (de 2): Esto corrige dos problemas. Descubr\u00ed que puede ocurrir la siguiente ejecuci\u00f3n: mfill_atomic other thread ============ ============ pmdp_get_lockless() [reads none pmd] __pte_alloc [no-op] BUG_ON(pmd_none(*dst_pmd)) He verificado esto experimentalmente en un kernel con llamadas mdelay() adicionales; se activa BUG_ON(pmd_none(*dst_pmd)). En los kernels m\u00e1s nuevos que el commit 0d940a9b270b (\"mm/pgtable: permitir que pte_offset_map[_lock]() falle\"), esto no puede llevar a nada peor que un BUG_ON(), ya que los ayudantes de acceso a la tabla de p\u00e1ginas est\u00e1n manipulados para lidiar con la desaparici\u00f3n simult\u00e1nea de tablas de p\u00e1ginas; pero en kernels m\u00e1s antiguos (<=6.4), creo que probablemente podr\u00edamos te\u00f3ricamente pasar por alto las dos comprobaciones de BUG_ON() y terminar tratando una p\u00e1gina enorme como una tabla de p\u00e1ginas. El segundo problema es que, como se\u00f1al\u00f3 Qi Zheng, hay otros tipos de PMD enormes que pmd_trans_huge() no puede detectar: PMD de devmap y PMD de intercambio (en particular, PMD de migraci\u00f3n). En <=6.4, esto es peor que el primer problema: si mfill_atomic() se ejecuta en un PMD que contiene una entrada de migraci\u00f3n (que solo requiere ganar una ejecuci\u00f3n \u00fanica y bastante amplia), pasar\u00e1 el PMD a pte_offset_map_lock(), que asume que el PMD apunta a una tabla de p\u00e1ginas. A continuaci\u00f3n, se produce una ruptura: primero, el n\u00facleo intenta tomar el bloqueo PTE (que se bloquear\u00e1 o tal vez ser\u00e1 peor si no hay una \"p\u00e1gina de estructura\" para los bits de direcci\u00f3n en el PMD de la entrada de migraci\u00f3n; creo que al menos en X86 no suele haber una \"p\u00e1gina de estructura\" correspondiente gracias a la mitigaci\u00f3n de inversi\u00f3n de PTE; amd64 se ve diferente). Si eso no se bloquea, el n\u00facleo intentar\u00e1 escribir un PTE en lo que cree err\u00f3neamente que es una tabla de p\u00e1ginas. Como parte de la soluci\u00f3n de estos problemas, elimine la verificaci\u00f3n de pmd_trans_huge() antes de __pte_alloc(); eso es redundante, vamos a tener que verificar eso despu\u00e9s de __pte_alloc() de todos modos. --- truncada ----"}], "id": "CVE-2024-46787", "lastModified": "2024-11-20T15:33:08.557", "metrics": {"cvssMetricV31": [{"cvssData": {"attackComplexity": "HIGH", "attackVector": "LOCAL", "availabilityImpact": "HIGH", "baseScore": 4.7, "baseSeverity": "MEDIUM", "confidentialityImpact": "NONE", "integrityImpact": "NONE", "privilegesRequired": "LOW", "scope": "UNCHANGED", "userInteraction": "NONE", "vectorString": "CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H", "version": "3.1"}, "exploitabilityScore": 1.0, "impactScore": 3.6, "source": "nvd@nist.gov", "type": "Primary"}]}, "published": "2024-09-18T08:15:05.833", "references": [{"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"], "url": "https://git.kernel.org/stable/c/3c6b4bcf37845c9359aed926324bed66bdd2448d"}, {"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"], "url": "https://git.kernel.org/stable/c/71c186efc1b2cf1aeabfeff3b9bd5ac4c5ac14d8"}, {"source": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "tags": ["Patch"], "url": "https://git.kernel.org/stable/c/98cc18b1b71e23fe81a5194ed432b20c2d81a01a"}], "sourceIdentifier": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "vulnStatus": "Analyzed", "weaknesses": [{"description": [{"lang": "en", "value": "NVD-CWE-noinfo"}], "source": "nvd@nist.gov", "type": "Primary"}]}