[Devel] [PATCH RHEL8 COMMIT] ve: Fix double-free if cgroup_mark_ve_roots() fails
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Apr 14 19:39:18 MSK 2021
The commit is pushed to "branch-rh8-4.18.0-240.1.1.vz8.5.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh8-4.18.0-240.1.1.vz8.5.13
------>
commit a288f3ade0ade86a656546f6a647cd556b02f36f
Author: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
Date: Fri Apr 9 20:29:57 2021 +0300
ve: Fix double-free if cgroup_mark_ve_roots() fails
Below is a dmesg output when cgroup_mark_ve_roots exits with error.
[ +0.973416] ============================================================
[ +0.000140] BUG: KASAN: double-free or invalid-free in kfree+0xd6/0x2d0
[ +0.000088] CPU: 0 PID: 285 Comm: kworker/0:3 ve: / Not tainted
[ +0.000002] Hardware name: Virtuozzo KVM, BIOS
[ +0.000017] Workqueue: cgroup_destroy css_killed_work_fn
[ +0.000007] Call Trace:
[ +0.000019] dump_stack+0x9a/0xf0
[ +0.000006] print_address_description.cold.3+0x9/0x23b
[ +0.000004] ? kfree+0xd6/0x2d0
[ +0.000005] kasan_report_invalid_free+0x65/0xa0
[ +0.000004] ? kfree+0xd6/0x2d0
[ +0.000003] __kasan_slab_free+0x157/0x170
[ +0.000006] slab_free_freelist_hook+0x5e/0x140
[ +0.000012] ? ve_offline+0x34/0x70
[ +0.000005] kfree+0xd6/0x2d0
[ +0.000007] ve_offline+0x34/0x70
[ +0.000004] css_killed_work_fn+0xa5/0x490
[ +0.000015] process_one_work+0x8f0/0x17a0
[ +0.000013] ? pwq_dec_nr_in_flight+0x320/0x320
[ +0.000003] ? lock_acquire+0x14f/0x3b0
[ +0.000015] worker_thread+0x87/0xb50
[ +0.000010] ? __kthread_parkme+0xb6/0x180
[ +0.000006] ? process_one_work+0x17a0/0x17a0
[ +0.000004] kthread+0x30e/0x3d0
[ +0.000003] ? kthread_create_fn+0x70/0x70
[ +0.000012] ret_from_fork+0x3a/0x50
[ +0.000036] Allocated by task 2817:
[ +0.000038] kasan_kmalloc+0xbf/0xe0
[ +0.000003] __kmalloc+0x157/0x320
[ +0.000022] ext4_htree_store_dirent+0x88/0x570 [ext4]
[ +0.000018] htree_dirblock_to_tree+0x235/0x540 [ext4]
[ +0.000016] ext4_htree_fill_tree+0x1e0/0x880 [ext4]
[ +0.000014] ext4_readdir+0xf5e/0x2910 [ext4]
[ +0.000010] iterate_dir+0x3b0/0x610
[ +0.000003] ksys_getdents64+0x11f/0x1f0
[ +0.000003] __x64_sys_getdents64+0x6f/0xb0
[ +0.000004] do_syscall_64+0xa5/0x4d0
[ +0.000006] entry_SYSCALL_64_after_hwframe+0x6a/0xdf
[ +0.000003] 0xffffffffffffffff
[ +0.000022] Freed by task 2817:
[ +0.000034] __kasan_slab_free+0x125/0x170
[ +0.000003] slab_free_freelist_hook+0x5e/0x140
[ +0.000003] kfree+0xd6/0x2d0
[ +0.000015] free_rb_tree_fname+0x67/0xb0 [ext4]
[ +0.000014] ext4_release_dir+0x3c/0x60 [ext4]
[ +0.000003] __fput+0x272/0x7b0
[ +0.000003] task_work_run+0x115/0x180
[ +0.000003] exit_to_usermode_loop+0x152/0x170
[ +0.000003] do_syscall_64+0x41e/0x4d0
[ +0.000003] entry_SYSCALL_64_after_hwframe+0x6a/0xdf
[ +0.000003] 0xffffffffffffffff
[ +0.000022] The buggy address belongs to the object at ffff888107da8b80
which belongs to the cache kmalloc-64 of size 64
[ +0.000120] The buggy address is located 0 bytes inside of
64-byte region [ffff888107da8b80, ffff888107da8bc0)
[ +0.000107] The buggy address belongs to the page:
[ +0.000054] page:ffffea00041f6a00 refcount:1 mapcount:0
mapping:ffff888107c0f000 index:0xffff888107da8b80
[ +0.000004] flags: 0x17ffffc0000100(slab)
[ +0.000004] raw: 0017ffffc0000100 ffffea000436a0c8 ffffea000428c748
[ +0.000003] raw: ffff888107da8b80 000000000020001f 00000001ffffffff
[ +0.000002] page dumped because: kasan: bad access detected
[ +0.000021] Memory state around the buggy address:
[ +0.000117] ffff888107da8a80: 00 00 00 00 00 00 00 fc fc fc fc fc fc fc
[ +0.000071] ffff888107da8b00: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc
[ +0.000103] >ffff888107da8b80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc
[ +0.000102] ^
[ +0.000035] ffff888107da8c00: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc
[ +0.000069] ffff888107da8c80: 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
[ +0.000069]
==================================================================
When this happens, ve_start_container() proceeds to error path and does
kfree(ve->ve_owner). The same kfree is later done in ve_offline() function.
v2 changes by khorenko@:
in fact the "kfree(ve->ve_owner)" in ve_start_container() error path is
redundant because ve_offline() is always called in case ve_online()
succeeds (i.e. ve::ve_name is allocated).
So drop the redundant kfree(ve->ve_name).
Signed-off-by: Valeriy Vdovin <valeriy.vdovin at virtuozzo.com>
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
kernel/ve/ve.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 8dbf56e78bb9..41e81aec3822 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -656,7 +656,6 @@ static int ve_start_container(struct ve_struct *ve)
ve_list_del(ve);
err_list:
ve_drop_context(ve);
- kfree(ve->ve_name);
return err;
}
More information about the Devel
mailing list