Message ID | 20241203153426.62794-1-zachwade.k@gmail.com |
---|---|
State | New |
Headers | show |
Series | padata: Fix refcnt handling in padata_free_shell() again | expand |
Hello Zach, On Tue, Dec 03, 2024 at 11:34:26PM +0800, Zach Wade wrote: > testcases/kernel/crypto/pcrypt_aead01.c of LTP project has UAF. > > Steps to reproduce: > 1. /sys/module/cryptomgr/parameters/notests is N > 2. run LTP ./testcases/bin/pcrypt_aead01 > > There is a race condition when padata_free_shell is released, which > causes it to be accessed after being released. We should use the rcu > mechanism to protect it. > cpu0 | cpu1 > ================================================================ > padata_do_parallel | padata_free_shell > rcu_read_lock_bh | refcount_dec_and_test > # run to here <- 1 | # run to here <- 2 > refcount_inc(&pd->refcnt); | padata_free_pd <- 3 > padata_work_alloc | ... > rcu_read_unlock_bh | I'm not sure this scenario is possible. For padata_free_shell to be called, I think there can't be any allocated pcrypt aead transforms (so that the alg refcount is low enough for crypto_del_alg to call padata_free_shell), but here cpu0 has called padata_do_parallel which implies it has such a transform. > There is a possibility of UAF after refcount_inc(&pd->refcnt). > > kasan report: > [158753.658839] ================================================================== > [158753.658851] BUG: KASAN: slab-use-after-free in padata_find_next+0x2d6/0x3f0 > [158753.658868] Read of size 4 at addr ffff88812f8b8524 by task kworker/u158:0/988818 > [158753.658878] > [158753.658885] CPU: 23 UID: 0 PID: 988818 Comm: kworker/u158:0 Kdump: loaded Tainted: G W E 6.12.0-dirty #33 > [158753.658902] Tainted: [W]=WARN, [E]=UNSIGNED_MODULE > [158753.658907] Hardware name: VMware, Inc. VMware20,1/440BX Desktop Reference Platform, BIOS VMW201.00V.20192059.B64.2207280713 07/28/2022 > [158753.658914] Workqueue: pdecrypt_parallel padata_parallel_worker > [158753.658927] Call Trace: > [158753.658932] <TASK> > [158753.658938] dump_stack_lvl+0x5d/0x80 > [158753.658960] print_report+0x174/0x505 > [158753.658992] kasan_report+0xe0/0x160 > [158753.659013] padata_find_next+0x2d6/0x3f0 > [158753.659035] padata_reorder+0x1cc/0x400 > [158753.659043] padata_parallel_worker+0x70/0x160 This report shows the uaf in find_next, not do_parallel. I think this is the same issue reported recently in this series: https://lore.kernel.org/all/20241123080509.2573987-1-chenridong@huaweicloud.com/
diff --git a/include/linux/padata.h b/include/linux/padata.h index 0146daf34430..ee6155689e47 100644 --- a/include/linux/padata.h +++ b/include/linux/padata.h @@ -103,6 +103,7 @@ struct parallel_data { int cpu; struct padata_cpumask cpumask; struct work_struct reorder_work; + struct rcu_head rcu; spinlock_t ____cacheline_aligned lock; }; diff --git a/kernel/padata.c b/kernel/padata.c index d51bbc76b227..3afdccc7e20e 100644 --- a/kernel/padata.c +++ b/kernel/padata.c @@ -1109,6 +1109,14 @@ struct padata_shell *padata_alloc_shell(struct padata_instance *pinst) } EXPORT_SYMBOL(padata_alloc_shell); +static void __padata_put_pd(struct rcu_head *head) +{ + struct parallel_data *pd = container_of(head, struct parallel_data, rcu); + + if (refcount_dec_and_test(&pd->refcnt)) + padata_free_pd(pd); +} + /** * padata_free_shell - free a padata shell * @@ -1124,9 +1132,8 @@ void padata_free_shell(struct padata_shell *ps) mutex_lock(&ps->pinst->lock); list_del(&ps->list); pd = rcu_dereference_protected(ps->pd, 1); - if (refcount_dec_and_test(&pd->refcnt)) - padata_free_pd(pd); mutex_unlock(&ps->pinst->lock); + call_rcu(&pd->rcu, __padata_put_pd); kfree(ps); }