[PATCH OLK-5.10] fs: aio: set VMA_DONTCOPY_BIT in mmap to fix NULL-pointer-dereference error
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8927 -------------------------------- [BUG] Recently, our internal syzkaller testing uncovered a null pointer dereference issue: BUG: kernel NULL pointer dereference, address: 0000000000000000 ... [ 51.111664] filemap_read_folio+0x25/0xe0 [ 51.112410] filemap_fault+0xad7/0x1250 [ 51.113112] __do_fault+0x4b/0x460 [ 51.113699] do_pte_missing+0x5bc/0x1db0 [ 51.114250] ? __pte_offset_map+0x23/0x170 [ 51.114822] __handle_mm_fault+0x9f8/0x1680 [ 51.115408] handle_mm_fault+0x24c/0x570 [ 51.115958] do_user_addr_fault+0x226/0xa50 ... Crash analysis showed the file involved was an AIO ring file. [CAUSE] PARENT process CHILD process t=0 io_setup(1, &ctx) [access ctx addr] fork() io_destroy vm_munmap // not affect child vma percpu_ref_put ... put_aio_ring_file t=1 [access ctx addr] // pagefault ... __do_fault filemap_fault max_idx = DIV_ROUND_UP t=2 truncate_setsize truncate_pagecache t=3 filemap_get_folio // no folio __filemap_get_folio(FGP_CREAT, ...) filemap_read_folio(xxx->read_folio) At t=0, the parent process calls io_setup and then fork. The child process gets its own VMA but without any PTEs. The parent then calls io_destroy. Before i_size is truncated to 0, at t=1 the child process accesses this AIO ctx address and triggers a pagefault. After the max_idx check passes, at t=2 the parent calls truncate_setsize and truncate_pagecache. At t=3 the child fails to obtain the folio, falls into the "page_not_uptodate" path, and hits this problem because AIO does not implement "read_folio". [Fix] Fix this by marking the AIO ring buffer VMA with VM_DONTCOPY so that fork()'s dup_mmap() skips it entirely. This is the correct semantic because: 1) The child's ioctx_table is already reset to NULL by mm_init_aio() during fork(), so the child has no AIO context and no way to perform any AIO operations on this mapping. 2) The AIO ring VMA is only meaningful in conjunction with its associated kioctx, which is never inherited across fork(). So child process with no AIO context has no legitimate reason to access the ring buffer. Delivering SIGSEGV on such an erroneous access is preferable to a kernel crash. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Signed-off-by: Zizhi Wo <wozizhi@huawei.com> --- fs/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/aio.c b/fs/aio.c index 78aaeaf35436..4ab74699cd3d 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -366,11 +366,11 @@ static const struct vm_operations_struct aio_ring_vm_ops = { #endif }; static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma) { - vma->vm_flags |= VM_DONTEXPAND; + vma->vm_flags |= VM_DONTEXPAND | VM_DONTCOPY; vma->vm_ops = &aio_ring_vm_ops; return 0; } static const struct file_operations aio_ring_fops = { -- 2.39.2
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/21749 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/KKR... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/21749 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/KKR...
participants (2)
-
patchwork bot -
Zizhi Wo