CVE-2026-97938: reboot: fix cad_pid use-after-free race

Published Sep 25, 2026
·
Updated

In the Linux kernel, the following vulnerability has been resolved:

reboot: fix cadpid use-after-free race

cadpid is a single kernel-wide struct pid pointer. procdocadpid() reads it and passes it to pidvnr() without protecting the lifetime of the referenced struct pid. A concurrent writer can replace cadpid and drop the final reference to the old struct pid after the reader has loaded the pointer but before pidvnr() has finished dereferencing it, causing a use-after-free.

killcadpid() has the same lifetime race when it passes cadpid to killpid().

At the time this issue was reported, an unprivileged user could reach the sysctl through user and PID namespaces because cadpid was registered in pidtable[]. Moving cadpid back to the global reboot sysctl table corrected that namespace and permission mismatch, but did not fix the underlying lifetime race.

Fix this by treating cadpid as an RCU-protected pointer at both read sites and by waiting for a grace period before dropping the old reference on the write side.

callrcu(&oldpid->rcu, ...) cannot be used here because freepid() also queues pid->rcu; queueing the same rcuhead twice can corrupt the RCU callback list.

Original KASAN crash stack: kernel/pid.c:545 pidnrns() # reads freed pid->level kernel/pid.c:556 pidvnr() # calls pidnrns() kernel/pid.c:775 procdocadpid() # calls pidvnr(cadpid)

Affected Software

1 affected component
Linux Linux kernel

Event History

Sep 25, 2026
CVE Published
via MITRE·10:22 AM
Data Sourced
via MITRE·10:22 AM
Description
Data Sourced
via NVD·11:17 AM
Description

Frequently Asked Questions

1

Who could trigger the vulnerable code path?

At the time the issue was reported, an unprivileged user could reach the cad_pid sysctl through user and PID namespaces because it was registered in pid_table[]. The affected operations also require concurrency between access to cad_pid and a writer replacing it.

2

Is namespace access alone sufficient to cause the use-after-free?

No. The race occurs when a reader loads cad_pid and dereferences it through pid_vnr(), or passes it to kill_pid(), while a concurrent writer replaces the pointer and drops the final reference to the old struct pid.

3

How was exposure through namespaces addressed?

cad_pid was moved back to the global reboot sysctl table, correcting the namespace and permission mismatch that had made it reachable through user and PID namespaces. That change alone did not resolve the underlying pointer-lifetime race.

4

What is the implemented mitigation for the lifetime race?

The fix treats cad_pid as an RCU-protected pointer at both read sites and waits for an RCU grace period before dropping the replaced pid reference. It avoids queueing the pid RCU head twice, since free_pid() also uses pid->rcu.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203