CVE-2022-49850

In the Linux kernel, the following vulnerability has been resolved: nilfs2: fix deadlock in nilfs_count_free_blocks() A semaphore deadlock can occur if nilfs_get_block() detects metadata corruption while locating data blocks and a superblock writeback occurs at the same time: task 1 task 2 ------ ------ * A file operation * nilfs_truncate() nilfs_get_block() down_read(rwsem A) <-- nilfs_bmap_lookup_contig() ... generic_shutdown_super() nilfs_put_super() * Prepare to write superblock * down_write(rwsem B) <-- nilfs_cleanup_super() * Detect b-tree corruption * nilfs_set_log_cursor() nilfs_bmap_convert_error() nilfs_count_free_blocks() __nilfs_error() down_read(rwsem A) <-- nilfs_set_error() down_write(rwsem B) <-- *** DEADLOCK *** Here, nilfs_get_block() readlocks rwsem A (= NILFS_MDT(dat_inode)->mi_sem) and then calls nilfs_bmap_lookup_contig(), but if it fails due to metadata corruption, __nilfs_error() is called from nilfs_bmap_convert_error() inside the lock section. Since __nilfs_error() calls nilfs_set_error() unless the filesystem is read-only and nilfs_set_error() attempts to writelock rwsem B (= nilfs->ns_sem) to write back superblock exclusively, hierarchical lock acquisition occurs in the order rwsem A -> rwsem B. Now, if another task starts updating the superblock, it may writelock rwsem B during the lock sequence above, and can deadlock trying to readlock rwsem A in nilfs_count_free_blocks(). However, there is actually no need to take rwsem A in nilfs_count_free_blocks() because it, within the lock section, only reads a single integer data on a shared struct with nilfs_sufile_get_ncleansegs(). This has been the case after commit aa474a220180 ("nilfs2: add local variable to cache the number of clean segments"), that is, even before this bug was introduced. So, this resolves the deadlock problem by just not taking the semaphore in nilfs_count_free_blocks().
Configurations

Configuration 1 (hide)

OR cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.1:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.1:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.1:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.1:rc4:*:*:*:*:*:*

History

07 May 2025, 13:32

Type Values Removed Values Added
CWE CWE-667
CPE cpe:2.3:o:linux:linux_kernel:6.1:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.1:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.1:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:6.1:rc1:*:*:*:*:*:*
References () https://git.kernel.org/stable/c/1d4ff73062096c21b47954d2996b4df259777bda - () https://git.kernel.org/stable/c/1d4ff73062096c21b47954d2996b4df259777bda - Patch
References () https://git.kernel.org/stable/c/36ff974b0310771417c0be64b64aa221bd70d63d - () https://git.kernel.org/stable/c/36ff974b0310771417c0be64b64aa221bd70d63d - Patch
References () https://git.kernel.org/stable/c/3c89ca6d3dfa6c09c515807a7a97a521f5d5147e - () https://git.kernel.org/stable/c/3c89ca6d3dfa6c09c515807a7a97a521f5d5147e - Patch
References () https://git.kernel.org/stable/c/8ac932a4921a96ca52f61935dbba64ea87bbd5dc - () https://git.kernel.org/stable/c/8ac932a4921a96ca52f61935dbba64ea87bbd5dc - Patch
References () https://git.kernel.org/stable/c/8b4506cff6630bb474bb46a2a75c31e533a756ba - () https://git.kernel.org/stable/c/8b4506cff6630bb474bb46a2a75c31e533a756ba - Patch
References () https://git.kernel.org/stable/c/abc082aac0d9b6b926038fc3adb7008306581be2 - () https://git.kernel.org/stable/c/abc082aac0d9b6b926038fc3adb7008306581be2 - Patch
References () https://git.kernel.org/stable/c/cb029b54953420f7a2d65100f1c5107f14411bdc - () https://git.kernel.org/stable/c/cb029b54953420f7a2d65100f1c5107f14411bdc - Patch
References () https://git.kernel.org/stable/c/f0cc93080d4c09510b74ecba87fd778cca390bb1 - () https://git.kernel.org/stable/c/f0cc93080d4c09510b74ecba87fd778cca390bb1 - Patch
First Time Linux linux Kernel
Linux
CVSS v2 : unknown
v3 : unknown
v2 : unknown
v3 : 5.5

02 May 2025, 13:53

Type Values Removed Values Added
Summary
  • (es) En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad: nilfs2: corregir bloqueo en nilfs_count_free_blocks() Un bloqueo de semáforo puede ocurrir si nilfs_get_block() detecta corrupción de metadatos mientras localiza bloques de datos y ocurre una escritura diferida de superbloque al mismo tiempo: tarea 1 tarea 2 ------ ------ * Una operación de archivo * nilfs_truncate() nilfs_get_block() down_read(rwsem A) &lt;-- nilfs_bmap_lookup_contig() ... generic_shutdown_super() nilfs_put_super() * Preparar para escribir superbloque * down_write(rwsem B) &lt;-- nilfs_cleanup_super() * Detectar corrupción de árbol b * nilfs_set_log_cursor() nilfs_bmap_convert_error() nilfs_count_free_blocks() __nilfs_error() down_read(rwsem A) &lt;-- nilfs_set_error() down_write(rwsem B) &lt;-- *** DEADLOCK *** Aquí, nilfs_get_block() vuelve a bloquear rwsem A (= NILFS_MDT(dat_inode)-&gt;mi_sem) y luego llama a nilfs_bmap_lookup_contig(), pero si falla debido a la corrupción de metadatos, se llama a __nilfs_error() desde nilfs_bmap_convert_error() dentro de la sección de bloqueo. Dado que __nilfs_error() llama a nilfs_set_error() a menos que el sistema de archivos sea de solo lectura y nilfs_set_error() intente bloquear la escritura de rwsem B (= nilfs-&gt;ns_sem) para reescribir exclusivamente el superbloque, la adquisición del bloqueo jerárquico se produce en el orden rwsem A -&gt; rwsem B. Ahora bien, si otra tarea comienza a actualizar el superbloque, puede bloquear la escritura de rwsem B durante la secuencia de bloqueo anterior y puede bloquearse al intentar bloquear la lectura de rwsem A en nilfs_count_free_blocks(). Sin embargo, no es necesario tomar rwsem A en nilfs_count_free_blocks() porque, dentro de la sección de bloqueo, solo lee un único dato entero en una estructura compartida con nilfs_sufile_get_ncleansegs(). Esto ha sucedido después del commit aa474a220180 ("nilfs2: añadir variable local para almacenar en caché el número de segmentos limpios"), incluso antes de que se introdujera este error. Por lo tanto, esto resuelve el problema de interbloqueo simplemente eliminando el semáforo en nilfs_count_free_blocks().

01 May 2025, 15:16

Type Values Removed Values Added
New CVE

Information

Published : 2025-05-01 15:16

Updated : 2025-05-07 13:32


NVD link : CVE-2022-49850

Mitre link : CVE-2022-49850

CVE.ORG link : CVE-2022-49850


JSON object : View

Products Affected

linux

  • linux_kernel
CWE
CWE-667

Improper Locking