diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2006-09-29 05:00:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-29 12:18:17 -0400 |
commit | 8dc3e9099e01dfdd53f27f329c268eced03dfef6 (patch) | |
tree | c4a88aeabd5726185bf65c75cc52145d9dc33e43 | |
parent | 57a6f51c4281aa3119975473c70dce0480d322bd (diff) |
[PATCH] sched_setscheduler: fix? policy checks
I am not sure this patch is correct: I can't understand what the current
code does, and I don't know what it was supposed to do.
The comment says:
* can't change policy, except between SCHED_NORMAL
* and SCHED_BATCH:
The code:
if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) &&
(policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) &&
But this is equivalent to:
if ( (is_rt_policy(policy) && has_rt_policy(p)) &&
which means something different. We can't _decrease_ the current
->rt_priority with such a check (if rlim[RLIMIT_RTPRIO] == 0).
Probably, it was supposed to be:
if ( !(policy == SCHED_NORMAL && p->policy == SCHED_BATCH) &&
!(policy == SCHED_BATCH && p->policy == SCHED_NORMAL)
this matches the comment, but strange: it doesn't allow to _drop_ the
realtime priority when rlim[RLIMIT_RTPRIO] == 0.
I think the right check would be:
/* can't set/change rt policy */
if (is_rt_policy(policy) &&
policy != p->policy &&
!rlim_rtprio)
return -EPERM;
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | kernel/sched.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index c3c718aea618..155a33da7aa7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -4116,27 +4116,25 @@ recheck: | |||
4116 | * Allow unprivileged RT tasks to decrease priority: | 4116 | * Allow unprivileged RT tasks to decrease priority: |
4117 | */ | 4117 | */ |
4118 | if (!capable(CAP_SYS_NICE)) { | 4118 | if (!capable(CAP_SYS_NICE)) { |
4119 | unsigned long rlim_rtprio; | 4119 | if (is_rt_policy(policy)) { |
4120 | unsigned long flags; | 4120 | unsigned long rlim_rtprio; |
4121 | 4121 | unsigned long flags; | |
4122 | if (!lock_task_sighand(p, &flags)) | 4122 | |
4123 | return -ESRCH; | 4123 | if (!lock_task_sighand(p, &flags)) |
4124 | rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur; | 4124 | return -ESRCH; |
4125 | unlock_task_sighand(p, &flags); | 4125 | rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur; |
4126 | unlock_task_sighand(p, &flags); | ||
4127 | |||
4128 | /* can't set/change the rt policy */ | ||
4129 | if (policy != p->policy && !rlim_rtprio) | ||
4130 | return -EPERM; | ||
4131 | |||
4132 | /* can't increase priority */ | ||
4133 | if (param->sched_priority > p->rt_priority && | ||
4134 | param->sched_priority > rlim_rtprio) | ||
4135 | return -EPERM; | ||
4136 | } | ||
4126 | 4137 | ||
4127 | /* | ||
4128 | * can't change policy, except between SCHED_NORMAL | ||
4129 | * and SCHED_BATCH: | ||
4130 | */ | ||
4131 | if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) && | ||
4132 | (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) && | ||
4133 | !rlim_rtprio) | ||
4134 | return -EPERM; | ||
4135 | /* can't increase priority */ | ||
4136 | if (is_rt_policy(policy) && | ||
4137 | param->sched_priority > p->rt_priority && | ||
4138 | param->sched_priority > rlim_rtprio) | ||
4139 | return -EPERM; | ||
4140 | /* can't change other user's priorities */ | 4138 | /* can't change other user's priorities */ |
4141 | if ((current->euid != p->euid) && | 4139 | if ((current->euid != p->euid) && |
4142 | (current->euid != p->uid)) | 4140 | (current->euid != p->uid)) |