aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/kernel/sched.c b/kernel/sched.c
index b946209d9c15..f9b3c6a414f1 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -4080,6 +4080,8 @@ static void __setscheduler(struct task_struct *p, int policy, int prio)
4080 * @p: the task in question. 4080 * @p: the task in question.
4081 * @policy: new policy. 4081 * @policy: new policy.
4082 * @param: structure containing the new RT priority. 4082 * @param: structure containing the new RT priority.
4083 *
4084 * NOTE: the task may be already dead
4083 */ 4085 */
4084int sched_setscheduler(struct task_struct *p, int policy, 4086int sched_setscheduler(struct task_struct *p, int policy,
4085 struct sched_param *param) 4087 struct sched_param *param)
@@ -4115,19 +4117,26 @@ recheck:
4115 * Allow unprivileged RT tasks to decrease priority: 4117 * Allow unprivileged RT tasks to decrease priority:
4116 */ 4118 */
4117 if (!capable(CAP_SYS_NICE)) { 4119 if (!capable(CAP_SYS_NICE)) {
4120 unsigned long rlim_rtprio;
4121 unsigned long flags;
4122
4123 if (!lock_task_sighand(p, &flags))
4124 return -ESRCH;
4125 rlim_rtprio = p->signal->rlim[RLIMIT_RTPRIO].rlim_cur;
4126 unlock_task_sighand(p, &flags);
4127
4118 /* 4128 /*
4119 * can't change policy, except between SCHED_NORMAL 4129 * can't change policy, except between SCHED_NORMAL
4120 * and SCHED_BATCH: 4130 * and SCHED_BATCH:
4121 */ 4131 */
4122 if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) && 4132 if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) &&
4123 (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) && 4133 (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) &&
4124 !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) 4134 !rlim_rtprio)
4125 return -EPERM; 4135 return -EPERM;
4126 /* can't increase priority */ 4136 /* can't increase priority */
4127 if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) && 4137 if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) &&
4128 param->sched_priority > p->rt_priority && 4138 param->sched_priority > p->rt_priority &&
4129 param->sched_priority > 4139 param->sched_priority > rlim_rtprio)
4130 p->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
4131 return -EPERM; 4140 return -EPERM;
4132 /* can't change other user's priorities */ 4141 /* can't change other user's priorities */
4133 if ((current->euid != p->euid) && 4142 if ((current->euid != p->euid) &&
@@ -4193,14 +4202,13 @@ do_sched_setscheduler(pid_t pid, int policy, struct sched_param __user *param)
4193 return -EINVAL; 4202 return -EINVAL;
4194 if (copy_from_user(&lparam, param, sizeof(struct sched_param))) 4203 if (copy_from_user(&lparam, param, sizeof(struct sched_param)))
4195 return -EFAULT; 4204 return -EFAULT;
4196 read_lock_irq(&tasklist_lock); 4205
4206 rcu_read_lock();
4207 retval = -ESRCH;
4197 p = find_process_by_pid(pid); 4208 p = find_process_by_pid(pid);
4198 if (!p) { 4209 if (p != NULL)
4199 read_unlock_irq(&tasklist_lock); 4210 retval = sched_setscheduler(p, policy, &lparam);
4200 return -ESRCH; 4211 rcu_read_unlock();
4201 }
4202 retval = sched_setscheduler(p, policy, &lparam);
4203 read_unlock_irq(&tasklist_lock);
4204 4212
4205 return retval; 4213 return retval;
4206} 4214}