clock_gettime is permitted in capability mode, and it calls get_cputime if clock_id is negative. get_cputime did not check the target pid in capability mode. Reported by: llm-postcr
Details
- Reviewers
markj ojanerif_amd.com - Group Reviewers
capsicum
Diff Detail
- Lint
Lint Skipped - Unit
Tests Skipped
Event Timeline
kern_time.c doesn't include <sys/capsicum.h>, so
IN_CAPABILITY_MODE is undefined under -Werror.
Same as kern_sig.c/kern_resource.c need for the same macro.
Confirmed the fix otherwise: booted a patched kernel, clock_gettime()
with another process's CPUCLOCK id now returns ECAPMODE instead of
leaking its runtime; own pid and CLOCK_REALTIME unaffected.
Happy to add a capmode.cc case for this (own pid vs. other pid) in a
follow-up if useful.
We should at least include sys/capsicum.h.
I'm not sure if we're supposed to guard these checks with #ifdef CAPABILITY_MODE.
| sys/kern/kern_time.c | ||
|---|---|---|
| 307 | I wonder if pget() should be handling these checks, with some flag to opt out. | |
Hmm. I'm not a fan of sprinkling those #ifdefs all over, but we could just #define IN_CAPABILITY_MODE() 0 in the !CAPABILITY_MODE case I guess.
I wonder if pget() should be handling these checks, with some flag to opt out.
Yeah, there does seem to be too much copy-paste boilerplate. I'd probably want to just start by fixing the cases that have been identified and then go back to see if we can clean it up.
Confirmed IN_CAPABILITY_MODE(td) is unconditionally false when
CAPABILITY_MODE isn't configured: sys_cap_enter() returns ENOSYS in that
case and nothing else sets CRED_FLAG_CAPMODE, so there's nothing to guard
against, and the three most recent examples of this exact pattern
(kern_rtprio, kern_kill, kern_sigqueue) don't use #ifdef either. I'd skip
the ifdef here for consistency with those.
On pushing it into pget(): kern_rtprio() uses pfind() and kern_kill() uses
pfind_any(), neither goes through pget(). The only other PGET_CANSEE
callers are sysctl_kern_proc_pathname/sv_name, and neither MIB is
CTLFLAG_CAPRD/CAPWR, so they're not capmode-reachable anyway. Centralizing
in pget() would help future callers but wouldn't have caught either prior
instance of this bug class. Worth a separate revision, or do you want it
folded into this one?