[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