Message ID | 20250110061639.1280907-3-chenridong@huaweicloud.com |
---|---|
State | New |
Headers | show |
Series | padata: fix UAF issues | expand |
On Fri, Jan 10, 2025 at 06:16:38AM +0000, Chen Ridong wrote: > From: Chen Ridong <chenridong@huawei.com> > > A bug was found when run ltp test: > > BUG: KASAN: slab-use-after-free in padata_find_next+0x29/0x1a0 > Read of size 4 at addr ffff88bbfe003524 by task kworker/u113:2/3039206 > > CPU: 0 PID: 3039206 Comm: kworker/u113:2 Kdump: loaded Not tainted 6.6.0+ > Workqueue: pdecrypt_parallel padata_parallel_worker > Call Trace: > <TASK> > dump_stack_lvl+0x32/0x50 > print_address_description.constprop.0+0x6b/0x3d0 > print_report+0xdd/0x2c0 > kasan_report+0xa5/0xd0 > padata_find_next+0x29/0x1a0 > padata_reorder+0x131/0x220 > padata_parallel_worker+0x3d/0xc0 > process_one_work+0x2ec/0x5a0 > > If 'mdelay(10)' is added before calling 'padata_find_next' in the > 'padata_reorder' function, this issue could be reproduced easily with > ltp test (pcrypt_aead01). > > This can be explained as bellow: > > pcrypt_aead_encrypt > ... > padata_do_parallel > refcount_inc(&pd->refcnt); // add refcnt > ... > padata_do_serial > padata_reorder // pd > while (1) { > padata_find_next(pd, true); // using pd > queue_work_on > ... > padata_serial_worker crypto_del_alg > padata_put_pd_cnt // sub refcnt > padata_free_shell > padata_put_pd(ps->pd); > // pd is freed > // loop again, but pd is freed > // call padata_find_next, UAF > } > > In the padata_reorder function, when it loops in 'while', if the alg is > deleted, the refcnt may be decreased to 0 before entering > 'padata_find_next', which leads to UAF. > > As mentioned in [1], do_serial is supposed to be called with BHs disabled > and always happen under RCU protection, to address this issue, add > synchronize_rcu() in 'padata_free_shell' wait for all _do_serial calls > to finish. > > [1] https://lore.kernel.org/all/20221028160401.cccypv4euxikusiq@parnassus.localdomain/ > [2] https://lore.kernel.org/linux-kernel/jfjz5d7zwbytztackem7ibzalm5lnxldi2eofeiczqmqs2m7o6@fq426cwnjtkm/ > Fixes: b128a3040935 ("padata: allocate workqueue internally") > Signed-off-by: Chen Ridong <chenridong@huawei.com> > Signed-off-by: Qu Zicheng <quzicheng@huawei.com> Acked-by: Daniel Jordan <daniel.m.jordan@oracle.com>
diff --git a/kernel/padata.c b/kernel/padata.c index 7d79df1e3b33..de2c02a81469 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -1135,6 +1135,12 @@ void padata_free_shell(struct padata_shell *ps) if (!ps) return; + /* + * Wait for all _do_serial calls to finish to avoid touching + * freed pd's and ps's. + */ + synchronize_rcu(); + mutex_lock(&ps->pinst->lock); list_del(&ps->list); pd = rcu_dereference_protected(ps->pd, 1);