[Devel] [PATCH VZ10 v2 2/6] ve/namespace: Fix UAF in alloc_mnt_ns
Vladimir Riabchun
vladimir.riabchun at virtuozzo.com
Wed Jul 22 16:09:18 MSK 2026
On 21.07.2026 17:57, Pavel Tikhomirov wrote:
>
>
> On 7/16/26 22:50, Vladimir Riabchun wrote:
>> KASAN reports a UAF in alloc_mnt_ns when running ve_ns_owner_test
>> selftest with low per-VE mount limit:
>>
>> [ 2011.939093] CT#0 reached the limit on mounts.
>> [ 2012.049101] ==================================================================
>> [ 2012.050328] BUG: KASAN: slab-use-after-free in __list_add_valid_or_report+0xaa/0xb0
>> [ 2012.051686] Read of size 8 at addr ffff8881f4321cd0 by task (coredump)/6230
>>
>> [ 2012.053069] CPU: 1 UID: 0 PID: 6230 Comm: (coredump) ve: 0 Kdump: loaded Not tainted 6.12.0-211.16.1.12.5.ovz10-v3-debug #1 12.5.ovz10 PREEMPT(voluntary)
>> [ 2012.053076] Hardware name: Acronis OpenStack Compute/Virtuozzo, BIOS 1.16.1-1.vz9.2 04/01/2014
>> [ 2012.053079] Call Trace:
>> [ 2012.053083] <TASK>
>> [ 2012.053087] dump_stack_lvl+0x6f/0xb0
>> [ 2012.053097] ? __list_add_valid_or_report+0xaa/0xb0
>> [ 2012.053102] print_address_description.constprop.0+0x88/0x380
>> [ 2012.053109] ? __list_add_valid_or_report+0xaa/0xb0
>> [ 2012.053113] print_report+0x108/0x209
>> [ 2012.053117] ? __virt_addr_valid+0x1a3/0x370
>> [ 2012.053123] ? __list_add_valid_or_report+0xaa/0xb0
>> [ 2012.053127] kasan_report+0xa3/0xe0
>> [ 2012.053133] ? __list_add_valid_or_report+0xaa/0xb0
>> [ 2012.053139] __list_add_valid_or_report+0xaa/0xb0
>> [ 2012.053143] alloc_mnt_ns+0x25c/0x620
>> [ 2012.053149] open_detached_copy+0xa4/0x480
>> [ 2012.053155] __x64_sys_open_tree+0x2c2/0x330
>> [ 2012.053161] ? __pfx___x64_sys_open_tree+0x10/0x10
>> [ 2012.053168] do_syscall_64+0x92/0x180
>> [ 2012.053175] ? rcu_is_watching+0x15/0xb0
>> [ 2012.053180] ? trace_irq_enable.constprop.0+0x14d/0x1c0
>> [ 2012.053187] entry_SYSCALL_64_after_hwframe+0x76/0x7e
>> [ 2012.053193] RIP: 0033:0x7f096c12db3b
>> [ 2012.053219] Code: 73 01 c3 48 8b 0d d5 82 0c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa b8 ac 01 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d a5 82 0c 00 f7 d8 64 89 01 48
>> [ 2012.053223] RSP: 002b:00007ffce7d6dff8 EFLAGS: 00000206 ORIG_RAX: 00000000000001ac
>> [ 2012.053230] RAX: ffffffffffffffda RBX: 000055ab331ebdc0 RCX: 00007f096c12db3b
>> [ 2012.053234] RDX: 0000000000081001 RSI: 000055ab220012fb RDI: 0000000000000003
>> [ 2012.053237] RBP: 00007ffce7d6e190 R08: 0000000000000000 R09: 000055ab331f12e0
>> [ 2012.053241] R10: 000055ab331ebe40 R11: 0000000000000206 R12: 000055ab331ecd50
>> [ 2012.053244] R13: 00007ffce7d6e7f0 R14: 00007ffce7d6e900 R15: 000055ab331ebdc0
>> [ 2012.053256] </TASK>
>>
>> [ 2012.080481] Allocated by task 6228:
>> [ 2012.081075] kasan_save_stack+0x30/0x50
>> [ 2012.081723] kasan_save_track+0x14/0x30
>> [ 2012.082358] __kasan_kmalloc+0x8f/0xa0
>> [ 2012.082976] alloc_mnt_ns+0xcf/0x620
>> [ 2012.083576] copy_mnt_ns+0xb2/0xa30
>> [ 2012.084159] create_new_namespaces+0xd7/0x940
>> [ 2012.084946] copy_namespaces+0x323/0x3f0
>> [ 2012.085605] copy_process+0x1d3c/0x53e0
>> [ 2012.086235] kernel_clone+0xc8/0x5f0
>> [ 2012.086928] __do_sys_clone3+0x172/0x1c0
>> [ 2012.087599] do_syscall_64+0x92/0x180
>> [ 2012.088218] entry_SYSCALL_64_after_hwframe+0x76/0x7e
>>
>> [ 2012.089332] Freed by task 6228:
>> [ 2012.089871] kasan_save_stack+0x30/0x50
>> [ 2012.090497] kasan_save_track+0x14/0x30
>> [ 2012.091262] kasan_save_free_info+0x3b/0x70
>> [ 2012.091944] __kasan_slab_free+0x37/0x50
>> [ 2012.092631] kfree+0x129/0x3f0
>> [ 2012.093194] copy_mnt_ns+0x74e/0xa30
>> [ 2012.093817] create_new_namespaces+0xd7/0x940
>> [ 2012.094554] copy_namespaces+0x323/0x3f0
>> [ 2012.095215] copy_process+0x1d3c/0x53e0
>> [ 2012.095868] kernel_clone+0xc8/0x5f0
>> [ 2012.096503] __do_sys_clone3+0x172/0x1c0
>> [ 2012.097174] do_syscall_64+0x92/0x180
>> [ 2012.097770] entry_SYSCALL_64_after_hwframe+0x76/0x7e
>>
>> The root cause is an incorrect rebase in commit
>> 229fd15908fe ("fs: don't try and remove empty rbtree node").
>> The error path in copy_mnt_ns didn't include list removal,
>> so after the free list contained an invalid element.
>>
>> To reduce the probability of such issues in the future,
>> extract ve-specific logic in a special helper and use it
>> in free_mnt_ns and copy_mnt_ns error path.
>>
>> https://virtuozzo.atlassian.net/browse/VSTOR-135520
>>
>> Fixes: 229fd15908fe ("fs: don't try and remove empty rbtree node")
>
> I think it should actually be:
> Fixes: e9d24527e7897 ("ve/mntns: make mnt_namespace->ve_owner present in not CONFIG_VE case")
>
> The mentioned above 229fd15908fe is the reason why it started to fail,
> but it's not the patch we are fixing, we want to fix our patches which
> add ve related stuff to free_mnt_ns().
I'll update tag in v2.
>
> Except that looks good.
>
> Reviewed-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
>
>> Signed-off-by: Vladimir Riabchun <vladimir.riabchun at virtuozzo.com>
>> ---
>> fs/namespace.c | 15 ++++++++++-----
>> 1 file changed, 10 insertions(+), 5 deletions(-)
>>
>> diff --git a/fs/namespace.c b/fs/namespace.c
>> index 0f4a3668e558..cd6aa2127203 100644
>> --- a/fs/namespace.c
>> +++ b/fs/namespace.c
>> @@ -4179,17 +4179,21 @@ static void dec_mnt_namespaces(struct ucounts *ucounts)
>> static LIST_HEAD(all_mntns_list);
>> static DEFINE_SPINLOCK(all_mntns_list_lock);
>>
>> -static void free_mnt_ns(struct mnt_namespace *ns)
>> +static void ve_cleanup_mnt_ns(struct mnt_namespace *ns)
>> {
>> - if (!is_anon_ns(ns))
>> - ns_free_inum(&ns->ns);
>> - dec_mnt_namespaces(ns->ucounts);
>> -
>> spin_lock(&all_mntns_list_lock);
>> list_del(&ns->mntns_list);
>> spin_unlock(&all_mntns_list_lock);
>>
>> put_ve(ns->ve_owner);
>> +}
>> +
>> +static void free_mnt_ns(struct mnt_namespace *ns)
>> +{
>> + if (!is_anon_ns(ns))
>> + ns_free_inum(&ns->ns);
>> + dec_mnt_namespaces(ns->ucounts);
>> + ve_cleanup_mnt_ns(ns);
>>
>> mnt_ns_tree_remove(ns);
>> }
>> @@ -4283,6 +4287,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
>> namespace_unlock();
>> ns_free_inum(&new_ns->ns);
>> dec_mnt_namespaces(new_ns->ucounts);
>> + ve_cleanup_mnt_ns(new_ns);
>> mnt_ns_release(new_ns);
>> return ERR_CAST(new);
>> }
>
--
--
Best regards, Riabchun Vladimir
Linux Kernel Developer, Virtuozzo
More information about the Devel
mailing list