[PATCH v6.6] erofs: fix NULL dereference of dif->bdev_handle in fscache mode

Hongbo Li lihongbo22 at huawei.com
Thu Jun 27 19:11:50 AEST 2024


When I run nydus on linux 6.6.35, the erofs crashed with the following
messages:

```
[ 2120.070101] RIP: 0010:erofs_map_dev+0x147/0x1e0 [erofs]
[ 2120.070188] Code: e8 4e bd 6d dc 8b 43 28 4c 89 ef 8d 70 ff e8 f0 ee 
69 dc 48 85 c0 0f 84 83 00 00 00 41 80 7d 44 00 75 31 48 8b 50 10 4c 89 
e7 <48> 8b 12 48 89 53 08 48 8b 50 18 48 89 53 10 48 8b 50 20 48 89 53
[ 2120.070288] RSP: 0018:ffff982a48adb9d8 EFLAGS: 00010246
[ 2120.070357] RAX: ffff8c2607e2f040 RBX: ffff982a48adba38 RCX: 
0000000000000000
[ 2120.070431] RDX: 0000000000000000 RSI: ffff8c25d17c7dc8 RDI: 
ffff8c354725e198
[ 2120.070522] RBP: ffff8c35466cf800 R08: ffff8c2607e2f040 R09: 
ffff8c354725e188
[ 2120.070631] R10: 0000000000000000 R11: 0000000000000000 R12: 
ffff8c354725e198
[ 2120.070741] R13: ffff8c354725e180 R14: ffff8c25d14d01c0 R15: 
0000000000001000
[ 2120.070853] FS:  000000c000a00090(0000) GS:ffff8c34ffe00000(0000) 
knlGS:0000000000000000
[ 2120.070965] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 2120.071054] CR2: 0000000000000000 CR3: 00000001067dc005 CR4: 
00000000001706f0
[ 2120.071163] Call Trace:
[ 2120.071245]  <TASK>
[ 2120.071325]  ? __die+0x24/0x70
[ 2120.071413]  ? page_fault_oops+0x82/0x150
[ 2120.071499]  ? fixup_exception+0x26/0x350
[ 2120.071585]  ? exc_page_fault+0x69/0x150
[ 2120.071671]  ? asm_exc_page_fault+0x26/0x30
[ 2120.071759]  ? erofs_map_dev+0x147/0x1e0 [erofs]
[ 2120.071853]  ? erofs_map_dev+0x130/0x1e0 [erofs]
[ 2120.071946]  erofs_fscache_data_read_slice+0xe7/0x390 [erofs]
[ 2120.072044]  ? xas_create+0x160/0x1b0
[ 2120.072130]  ? __kmem_cache_alloc_node+0x18c/0x2c0
[ 2120.072219]  ? erofs_fscache_readahead+0x49/0x110 [erofs]
[ 2120.072314]  ? xas_load+0xe/0x50
[ 2120.072397]  erofs_fscache_readahead+0xe0/0x110 [erofs]
[ 2120.072492]  read_pages+0x5a/0x220
[ 2120.072579]  page_cache_ra_order+0x1f0/0x2f0
[ 2120.072667]  filemap_get_pages+0xef/0x290
[ 2120.072755]  filemap_read+0xcb/0x310
[ 2120.072841]  ? ovl_open+0x9e/0xf0 [overlay]
[ 2120.072942]  ? ima_file_check+0x57/0x80
[ 2120.073028]  ? mntput_no_expire+0x4a/0x250
[ 2120.073116]  do_iter_readv_writev+0x12d/0x140
[ 2120.073204]  do_iter_read+0xfd/0x190
[ 2120.073288]  ovl_read_iter+0x1c3/0x210 [overlay]
[ 2120.073384]  vfs_read+0x1c7/0x300
[ 2120.073471]  ksys_read+0x63/0xe0
[ 2120.073555]  do_syscall_64+0x37/0x90
[ 2120.073640]  entry_SYSCALL_64_after_hwframe+0x78/0xe2
[ 2120.073729] RIP: 0033:0x403ace
```

The reason is the same with 8bd90b6ae7856("erofs: fix NULL dereference 
of dif->bdev_handle in fscache mode") in mainline. So we should backport 
this
patch into stable linux-6.6.y to avoid this bug.

On 2024/6/27 17:13, Hongbo Li wrote:
> From: Jingbo Xu <jefflexu at linux.alibaba.com>
> 
> Avoid NULL dereference of dif->bdev_handle, as dif->bdev_handle is NULL
> in fscache mode.
> 
>   BUG: kernel NULL pointer dereference, address: 0000000000000000
>   RIP: 0010:erofs_map_dev+0xbd/0x1c0
>   Call Trace:
>    <TASK>
>    erofs_fscache_data_read_slice+0xa7/0x340
>    erofs_fscache_data_read+0x11/0x30
>    erofs_fscache_readahead+0xd9/0x100
>    read_pages+0x47/0x1f0
>    page_cache_ra_order+0x1e5/0x270
>    filemap_get_pages+0xf2/0x5f0
>    filemap_read+0xb8/0x2e0
>    vfs_read+0x18d/0x2b0
>    ksys_read+0x53/0xd0
>    do_syscall_64+0x42/0xf0
>    entry_SYSCALL_64_after_hwframe+0x6e/0x76
> 
> Reported-by: Yiqun Leng <yqleng at linux.alibaba.com>
> Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=7245
> Fixes: 49845720080d ("erofs: Convert to use bdev_open_by_path()")
> Signed-off-by: Jingbo Xu <jefflexu at linux.alibaba.com>
> Reviewed-by: Gao Xiang <hsiangkao at linux.alibaba.com>
> Reviewed-by: Yue Hu <huyue2 at coolpad.com>
> Reviewed-by: Chao Yu <chao at kernel.org>
> Link: https://lore.kernel.org/r/20231114070704.23398-1-jefflexu@linux.alibaba.com
> Signed-off-by: Gao Xiang <hsiangkao at linux.alibaba.com>
> Signed-off-by: Hongbo Li <lihongbo22 at huawei.com>
> ---
>   fs/erofs/data.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/erofs/data.c b/fs/erofs/data.c
> index 029c761670bf..c98aeda8abb2 100644
> --- a/fs/erofs/data.c
> +++ b/fs/erofs/data.c
> @@ -220,7 +220,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
>   			up_read(&devs->rwsem);
>   			return 0;
>   		}
> -		map->m_bdev = dif->bdev_handle->bdev;
> +		map->m_bdev = dif->bdev_handle ? dif->bdev_handle->bdev : NULL;
>   		map->m_daxdev = dif->dax_dev;
>   		map->m_dax_part_off = dif->dax_part_off;
>   		map->m_fscache = dif->fscache;
> @@ -238,7 +238,8 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
>   			if (map->m_pa >= startoff &&
>   			    map->m_pa < startoff + length) {
>   				map->m_pa -= startoff;
> -				map->m_bdev = dif->bdev_handle->bdev;
> +				map->m_bdev = dif->bdev_handle ?
> +					      dif->bdev_handle->bdev : NULL;
>   				map->m_daxdev = dif->dax_dev;
>   				map->m_dax_part_off = dif->dax_part_off;
>   				map->m_fscache = dif->fscache;


More information about the Linux-erofs mailing list