Skip to content

Commit 652f8a2

Browse files
committed
Merge: CVE-2025-21726: padata: avoid UAF for reorder_work
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6499 JIRA: https://issues.redhat.com/browse/RHEL-81522 CVE: CVE-2025-21726 MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6499 This MR backports the 3-patch series that includes the fix to CVE-2025-21726 as well as two other minor cleanup and fix patches. Signed-off-by: Waiman Long <longman@redhat.com> Approved-by: Herton R. Krzesinski <herton@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
2 parents b0e9183 + 916d1a5 commit 652f8a2

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

kernel/padata.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ struct padata_mt_job_state {
4747
static void padata_free_pd(struct parallel_data *pd);
4848
static void __init padata_mt_helper(struct work_struct *work);
4949

50+
static inline void padata_get_pd(struct parallel_data *pd)
51+
{
52+
refcount_inc(&pd->refcnt);
53+
}
54+
55+
static inline void padata_put_pd_cnt(struct parallel_data *pd, int cnt)
56+
{
57+
if (refcount_sub_and_test(cnt, &pd->refcnt))
58+
padata_free_pd(pd);
59+
}
60+
61+
static inline void padata_put_pd(struct parallel_data *pd)
62+
{
63+
padata_put_pd_cnt(pd, 1);
64+
}
65+
5066
static int padata_index_to_cpu(struct parallel_data *pd, int cpu_index)
5167
{
5268
int cpu, target_cpu;
@@ -206,7 +222,7 @@ int padata_do_parallel(struct padata_shell *ps,
206222
if ((pinst->flags & PADATA_RESET))
207223
goto out;
208224

209-
refcount_inc(&pd->refcnt);
225+
padata_get_pd(pd);
210226
padata->pd = pd;
211227
padata->cb_cpu = *cb_cpu;
212228

@@ -336,8 +352,14 @@ static void padata_reorder(struct parallel_data *pd)
336352
smp_mb();
337353

338354
reorder = per_cpu_ptr(pd->reorder_list, pd->cpu);
339-
if (!list_empty(&reorder->list) && padata_find_next(pd, false))
355+
if (!list_empty(&reorder->list) && padata_find_next(pd, false)) {
356+
/*
357+
* Other context(eg. the padata_serial_worker) can finish the request.
358+
* To avoid UAF issue, add pd ref here, and put pd ref after reorder_work finish.
359+
*/
360+
padata_get_pd(pd);
340361
queue_work(pinst->serial_wq, &pd->reorder_work);
362+
}
341363
}
342364

343365
static void invoke_padata_reorder(struct work_struct *work)
@@ -348,6 +370,8 @@ static void invoke_padata_reorder(struct work_struct *work)
348370
pd = container_of(work, struct parallel_data, reorder_work);
349371
padata_reorder(pd);
350372
local_bh_enable();
373+
/* Pairs with putting the reorder_work in the serial_wq */
374+
padata_put_pd(pd);
351375
}
352376

353377
static void padata_serial_worker(struct work_struct *serial_work)
@@ -380,8 +404,7 @@ static void padata_serial_worker(struct work_struct *serial_work)
380404
}
381405
local_bh_enable();
382406

383-
if (refcount_sub_and_test(cnt, &pd->refcnt))
384-
padata_free_pd(pd);
407+
padata_put_pd_cnt(pd, cnt);
385408
}
386409

387410
/**
@@ -521,13 +544,6 @@ void __init padata_do_multithreaded(struct padata_mt_job *job)
521544
ps.chunk_size = max(ps.chunk_size, 1ul);
522545
ps.chunk_size = roundup(ps.chunk_size, job->align);
523546

524-
/*
525-
* chunk_size can be 0 if the caller sets min_chunk to 0. So force it
526-
* to at least 1 to prevent divide-by-0 panic in padata_mt_helper().`
527-
*/
528-
if (!ps.chunk_size)
529-
ps.chunk_size = 1U;
530-
531547
list_for_each_entry(pw, &works, pw_list)
532548
if (job->numa_aware) {
533549
int old_node = atomic_read(&last_used_nid);
@@ -688,8 +704,7 @@ static int padata_replace(struct padata_instance *pinst)
688704
synchronize_rcu();
689705

690706
list_for_each_entry_continue_reverse(ps, &pinst->pslist, list)
691-
if (refcount_dec_and_test(&ps->opd->refcnt))
692-
padata_free_pd(ps->opd);
707+
padata_put_pd(ps->opd);
693708

694709
pinst->flags &= ~PADATA_RESET;
695710

@@ -977,7 +992,7 @@ static ssize_t padata_sysfs_store(struct kobject *kobj, struct attribute *attr,
977992

978993
pinst = kobj2pinst(kobj);
979994
pentry = attr2pentry(attr);
980-
if (pentry->show)
995+
if (pentry->store)
981996
ret = pentry->store(pinst, attr, buf, count);
982997

983998
return ret;
@@ -1128,11 +1143,16 @@ void padata_free_shell(struct padata_shell *ps)
11281143
if (!ps)
11291144
return;
11301145

1146+
/*
1147+
* Wait for all _do_serial calls to finish to avoid touching
1148+
* freed pd's and ps's.
1149+
*/
1150+
synchronize_rcu();
1151+
11311152
mutex_lock(&ps->pinst->lock);
11321153
list_del(&ps->list);
11331154
pd = rcu_dereference_protected(ps->pd, 1);
1134-
if (refcount_dec_and_test(&pd->refcnt))
1135-
padata_free_pd(pd);
1155+
padata_put_pd(pd);
11361156
mutex_unlock(&ps->pinst->lock);
11371157

11381158
kfree(ps);

0 commit comments

Comments
 (0)