[PATCH 00/13] cred: gather the "same uid" checks between tasks in one place
Josef Bacik
josef at toxicpanda.com
Sun Oct 18 17:31:42 UTC 2026
Hello,
We have a dozen places in the kernel that let one task mess with another
because they belong to the same user: kill(), SIGIO, the scheduler
syscalls, setpriority(), ioprio_set(), prlimit(), ptrace, moving a task
around in cgroup v1 and resctrl, and KEYCTL_SESSION_TO_PARENT. Every
one of them open codes a handful of uid_eq() calls on the two creds.
They come in six flavors that differ in which of the real, effective and
saved ids they look at, and in whether euid 0 gets a pass, and there is
nothing that tells you whether two of them differ on purpose or by
accident.
I tripped over this working on something else that needs to change what
"the same user" means. I kept finding another copy I had missed, and
for this kind of check a copy you missed is a hole. So this pulls all
of them into kernel/cred.c, side by side, with a table that says which
rule looks at what, and converts the callers one at a time.
Nothing is supposed to change. What each of these means by "the same
user" is ABI at this point, so every rule is kept exactly as it was,
warts and all, I have not tried to unify them. The capability checks
and the LSM hooks stay with the callers.
The one patch that isn't a straight substitution is the fcntl one.
F_SETOWN copies the uid and euid of the caller into the fown_struct, and
the helpers take creds, so it holds a reference on the cred instead, the
same way struct file does for the opener. That means the cred sticks
around until the owner is set again or the file goes away.
For testing, patch 2 is a KUnit test that holds each helper against the
expression it replaces, verbatim, over every combination of a few ids. I
also ran kill, setpriority, ioprio_set, sched_setaffinity,
sched_setscheduler, prlimit, a cgroup v1 move, SIGIO and PTRACE_SEIZE
for all 64 combinations of real, effective and saved uid of the two
tasks, on a kernel with and without the series under KASAN and lockdep.
All 576 results are the same on both, and they match what the table
says. The resctrl and usbdevfs (kill_pid_usb_asyncio) callers I have no
way to exercise, and the MIPS patch is compile tested only.
This is based on vfs.all only because that's what the other work sits
on. Thanks,
Josef
Signed-off-by: Josef Bacik <josef at toxicpanda.com>
---
Josef Bacik (13):
cred: gather the rules for acting on a task by uid
cred: add KUnit tests for the id rules
signal: use cred_ids_allow_signal()
fcntl: use cred_ids_allow_sigio()
sched: use cred_ids_allow_sched()
MIPS: use cred_ids_allow_sched()
sys: use cred_ids_allow_sched() for setpriority()
sys: use cred_ids_allow_control() for prlimit()
block: use cred_ids_allow_ioprio()
cgroup/v1: use cred_ids_allow_move()
fs/resctrl: use cred_ids_allow_move()
ptrace: use cred_ids_allow_control()
keys: use cred_ids_allow_control()
Documentation/security/credentials.rst | 19 +++
MAINTAINERS | 1 +
arch/mips/kernel/mips-mt-fpaff.c | 3 +-
block/blk-ioc.c | 3 +-
fs/fcntl.c | 19 +--
fs/resctrl/rdtgroup.c | 4 +-
include/linux/cred.h | 20 +++
include/linux/fs.h | 4 +-
kernel/Makefile | 1 +
kernel/cgroup/cgroup-v1.c | 4 +-
kernel/cred.c | 160 ++++++++++++++++++++++++
kernel/cred_kunit.c | 218 +++++++++++++++++++++++++++++++++
kernel/ptrace.c | 16 +--
kernel/sched/syscalls.c | 3 +-
kernel/signal.c | 10 +-
kernel/sys.c | 10 +-
lib/Kconfig.debug | 13 ++
security/keys/keyctl.c | 7 +-
security/landlock/fs.h | 3 +-
19 files changed, 459 insertions(+), 59 deletions(-)
---
base-commit: ac311bf4f20e614d8e94cae4c62f075f2e5ef16c
change-id: 20261018-b4-cred-ids-eb01b2b38524
More information about the Linux-security-module-archive
mailing list