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 <cgzones@xxxxxxxxxxxxxx> --- 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