CVE-2024-53111

In the Linux kernel, the following vulnerability has been resolved: mm/mremap: fix address wraparound in move_page_tables() On 32-bit platforms, it is possible for the expression `len + old_addr < old_end` to be false-positive if `len + old_addr` wraps around. `old_addr` is the cursor in the old range up to which page table entries have been moved; so if the operation succeeded, `old_addr` is the *end* of the old region, and adding `len` to it can wrap. The overflow causes mremap() to mistakenly believe that PTEs have been copied; the consequence is that mremap() bails out, but doesn't move the PTEs back before the new VMA is unmapped, causing anonymous pages in the region to be lost. So basically if userspace tries to mremap() a private-anon region and hits this bug, mremap() will return an error and the private-anon region's contents appear to have been zeroed. The idea of this check is that `old_end - len` is the original start address, and writing the check that way also makes it easier to read; so fix the check by rearranging the comparison accordingly. (An alternate fix would be to refactor this function by introducing an "orig_old_start" variable or such.) Tested in a VM with a 32-bit X86 kernel; without the patch: ``` user@horn:~/big_mremap$ cat test.c #define _GNU_SOURCE #include <stdlib.h> #include <stdio.h> #include <err.h> #include <sys/mman.h> #define ADDR1 ((void*)0x60000000) #define ADDR2 ((void*)0x10000000) #define SIZE 0x50000000uL int main(void) { unsigned char *p1 = mmap(ADDR1, SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED_NOREPLACE, -1, 0); if (p1 == MAP_FAILED) err(1, "mmap 1"); unsigned char *p2 = mmap(ADDR2, SIZE, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED_NOREPLACE, -1, 0); if (p2 == MAP_FAILED) err(1, "mmap 2"); *p1 = 0x41; printf("first char is 0x%02hhx\n", *p1); unsigned char *p3 = mremap(p1, SIZE, SIZE, MREMAP_MAYMOVE|MREMAP_FIXED, p2); if (p3 == MAP_FAILED) { printf("mremap() failed; first char is 0x%02hhx\n", *p1); } else { printf("mremap() succeeded; first char is 0x%02hhx\n", *p3); } } user@horn:~/big_mremap$ gcc -static -o test test.c user@horn:~/big_mremap$ setarch -R ./test first char is 0x41 mremap() failed; first char is 0x00 ``` With the patch: ``` user@horn:~/big_mremap$ setarch -R ./test first char is 0x41 mremap() succeeded; first char is 0x41 ```
Configurations

Configuration 1 (hide)

OR cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc5:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc6:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc7:*:*:*:*:*:*

History

11 Dec 2024, 20:27

Type Values Removed Values Added
First Time Linux linux Kernel
Linux
CPE cpe:2.3:o:linux:linux_kernel:6.12:rc6:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc7:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc5:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.12:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
CVSS v2 : unknown
v3 : unknown
v2 : unknown
v3 : 5.5
Summary
  • (es) En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: mm/mremap: se corrige el envoltorio de direcciones en move_page_tables() En plataformas de 32 bits, es posible que la expresión `len + old_addr &lt; old_end` sea un falso positivo si `len + old_addr` realiza un envoltorio. `old_addr` es el cursor en el rango antiguo hasta el cual se han movido las entradas de la tabla de páginas; por lo que si la operación tuvo éxito, `old_addr` es el *final* de la región antigua, y agregarle `len` puede realizar un envoltorio. El desbordamiento hace que mremap() crea erróneamente que se han copiado las PTE; la consecuencia es que mremap() se retira, pero no mueve las PTE de nuevo antes de que se desasigne el nuevo VMA, lo que provoca que se pierdan las páginas anónimas en la región. Básicamente, si el espacio de usuario intenta ejecutar mremap() en una región privada-anon y encuentra este error, mremap() devolverá un error y el contenido de la región privada-anon parecerá haber sido puesto a cero. La idea de esta comprobación es que `old_end - len` sea la dirección de inicio original, y escribir la comprobación de esa manera también facilita la lectura; por lo tanto, arregle la comprobación reorganizando la comparación en consecuencia. (Un workaround sería refactorizar esta función introduciendo una variable "orig_old_start" o algo similar). Probado en una máquina virtual con un núcleo X86 de 32 bits; sin el parche: ``` usuario@horn:~/big_mremap$ cat test.c #define _GNU_SOURCE #include #include #include #include #define ADDR1 ((void*)0x60000000) #define ADDR2 ((void*)0x10000000) #define SIZE 0x50000000uL int main(void) { unsigned char *p1 = mmap(ADDR1, SIZE, PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED_NOREPLACE, -1, 0); if (p1 == MAP_FAILED) err(1, "mmap 1"); carácter sin signo *p2 = mmap(ADDR2, SIZE, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED_NOREPLACE, -1, 0); si (p2 == MAP_FAILED) err(1, "mmap 2"); *p1 = 0x41; printf("el primer carácter es 0x%02hhx\n", *p1); carácter sin signo *p3 = mremap(p1, SIZE, SIZE, MREMAP_MAYMOVE|MREMAP_FIXED, p2); si (p3 == MAP_FAILED) { printf("mremap() falló; el primer carácter es 0x%02hhx\n", *p1); } de lo contrario { printf("mremap() tuvo éxito; el primer carácter es 0x%02hhx\n", *p3); } } usuario@horn:~/big_mremap$ gcc -static -o test test.c usuario@horn:~/big_mremap$ setarch -R ./test el primer carácter es 0x41 mremap() falló; el primer carácter es 0x00 ``` Con el parche: ``` usuario@horn:~/big_mremap$ setarch -R ./test el primer carácter es 0x41 mremap() tuvo éxito; el primer carácter es 0x41 ```
CWE CWE-190
References () https://git.kernel.org/stable/c/909543dc279a91122fb08e4653a72b82f0ad28f4 - () https://git.kernel.org/stable/c/909543dc279a91122fb08e4653a72b82f0ad28f4 - Patch
References () https://git.kernel.org/stable/c/a4a282daf1a190f03790bf163458ea3c8d28d217 - () https://git.kernel.org/stable/c/a4a282daf1a190f03790bf163458ea3c8d28d217 - Patch

02 Dec 2024, 14:15

Type Values Removed Values Added
New CVE

Information

Published : 2024-12-02 14:15

Updated : 2024-12-11 20:27


NVD link : CVE-2024-53111

Mitre link : CVE-2024-53111

CVE.ORG link : CVE-2024-53111


JSON object : View

Products Affected

linux

  • linux_kernel
CWE
CWE-190

Integer Overflow or Wraparound