[RFC PATCH] sched: only issue an audit on privileged operation
From: Christian Göttsche <hidden>
Date: 2020-09-04 16:01:25
sched_setattr(2) does via kernel/sched/core.c:__sched_setscheduler() issue a CAP_SYS_NICE audit event unconditionally, even when the requested operation does not require that capability / is un-privileged. Perform privilged/unprivileged catigorization first and perform a capable test only if needed. Signed-off-by: Christian Göttsche <redacted> --- kernel/sched/core.c | 65 ++++++++++++++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 18 deletions(-)
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 8471a0f7eb32..954f968d2466 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c@@ -5249,13 +5249,19 @@ static int __sched_setscheduler(struct task_struct *p, return -EINVAL; /* - * Allow unprivileged RT tasks to decrease priority: + * Allow unprivileged RT tasks to decrease priority. + * Only issue a capable test if needed to avoid audit + * event on non-privileged operations: */ - if (user && !capable(CAP_SYS_NICE)) { + if (user) { if (fair_policy(policy)) { if (attr->sched_nice < task_nice(p) && - !can_nice(p, attr->sched_nice)) - return -EPERM; + !can_nice(p, attr->sched_nice)) { + if (capable(CAP_SYS_NICE)) + goto sys_nice_capable; + else + return -EPERM; + } } if (rt_policy(policy)) {
@@ -5263,13 +5269,21 @@ static int __sched_setscheduler(struct task_struct *p, task_rlimit(p, RLIMIT_RTPRIO); /* Can't set/change the rt policy: */ - if (policy != p->policy && !rlim_rtprio) - return -EPERM; + if (policy != p->policy && !rlim_rtprio) { + if (capable(CAP_SYS_NICE)) + goto sys_nice_capable; + else + return -EPERM; + } /* Can't increase priority: */ if (attr->sched_priority > p->rt_priority && - attr->sched_priority > rlim_rtprio) - return -EPERM; + attr->sched_priority > rlim_rtprio) { + if (capable(CAP_SYS_NICE)) + goto sys_nice_capable; + else + return -EPERM; + } } /*
@@ -5278,28 +5292,43 @@ static int __sched_setscheduler(struct task_struct *p, * unprivileged DL tasks to increase their relative deadline * or reduce their runtime (both ways reducing utilization) */ - if (dl_policy(policy)) - return -EPERM; + if (dl_policy(policy)) { + if (capable(CAP_SYS_NICE)) + goto sys_nice_capable; + else + return -EPERM; + } /* * Treat SCHED_IDLE as nice 20. Only allow a switch to * SCHED_NORMAL if the RLIMIT_NICE would normally permit it. */ if (task_has_idle_policy(p) && !idle_policy(policy)) { - if (!can_nice(p, task_nice(p))) - return -EPERM; + if (!can_nice(p, task_nice(p))) { + if (capable(CAP_SYS_NICE)) + goto sys_nice_capable; + else + return -EPERM; + } } /* Can't change other user's priorities: */ - if (!check_same_owner(p)) - return -EPERM; + if (!check_same_owner(p)) { + if (capable(CAP_SYS_NICE)) + goto sys_nice_capable; + else + return -EPERM; + } /* Normal users shall not reset the sched_reset_on_fork flag: */ - if (p->sched_reset_on_fork && !reset_on_fork) - return -EPERM; - } + if (p->sched_reset_on_fork && !reset_on_fork) { + if (capable(CAP_SYS_NICE)) + goto sys_nice_capable; + else + return -EPERM; + } - if (user) { +sys_nice_capable: if (attr->sched_flags & SCHED_FLAG_SUGOV) return -EINVAL;
--
2.28.0