Skip to content

Commit 219f170

Browse files
committed
Merge branch 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'sched-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: sched: don't allow setuid to succeed if the user does not have rt bandwidth sched_rt: don't start timer when rt bandwidth disabled
2 parents 3024e4a + 54e9912 commit 219f170

File tree

4 files changed

+54
-14
lines changed

4 files changed

+54
-14
lines changed

include/linux/sched.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,9 +2291,13 @@ extern long sched_group_rt_runtime(struct task_group *tg);
22912291
extern int sched_group_set_rt_period(struct task_group *tg,
22922292
long rt_period_us);
22932293
extern long sched_group_rt_period(struct task_group *tg);
2294+
extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
22942295
#endif
22952296
#endif
22962297

2298+
extern int task_can_switch_user(struct user_struct *up,
2299+
struct task_struct *tsk);
2300+
22972301
#ifdef CONFIG_TASK_XACCT
22982302
static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
22992303
{

kernel/sched.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ static void start_rt_bandwidth(struct rt_bandwidth *rt_b)
223223
{
224224
ktime_t now;
225225

226-
if (rt_bandwidth_enabled() && rt_b->rt_runtime == RUNTIME_INF)
226+
if (!rt_bandwidth_enabled() || rt_b->rt_runtime == RUNTIME_INF)
227227
return;
228228

229229
if (hrtimer_active(&rt_b->rt_period_timer))
@@ -9224,6 +9224,16 @@ static int sched_rt_global_constraints(void)
92249224

92259225
return ret;
92269226
}
9227+
9228+
int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
9229+
{
9230+
/* Don't accept realtime tasks when there is no way for them to run */
9231+
if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
9232+
return 0;
9233+
9234+
return 1;
9235+
}
9236+
92279237
#else /* !CONFIG_RT_GROUP_SCHED */
92289238
static int sched_rt_global_constraints(void)
92299239
{
@@ -9317,8 +9327,7 @@ cpu_cgroup_can_attach(struct cgroup_subsys *ss, struct cgroup *cgrp,
93179327
struct task_struct *tsk)
93189328
{
93199329
#ifdef CONFIG_RT_GROUP_SCHED
9320-
/* Don't accept realtime tasks when there is no way for them to run */
9321-
if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
9330+
if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
93229331
return -EINVAL;
93239332
#else
93249333
/* We don't support RT-tasks being in separate groups */

kernel/sys.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ SYSCALL_DEFINE1(setgid, gid_t, gid)
559559
abort_creds(new);
560560
return retval;
561561
}
562-
562+
563563
/*
564564
* change the user struct in a credentials set to match the new UID
565565
*/
@@ -571,6 +571,11 @@ static int set_user(struct cred *new)
571571
if (!new_user)
572572
return -EAGAIN;
573573

574+
if (!task_can_switch_user(new_user, current)) {
575+
free_uid(new_user);
576+
return -EINVAL;
577+
}
578+
574579
if (atomic_read(&new_user->processes) >=
575580
current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
576581
new_user != INIT_USER) {
@@ -631,10 +636,11 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
631636
goto error;
632637
}
633638

634-
retval = -EAGAIN;
635-
if (new->uid != old->uid && set_user(new) < 0)
636-
goto error;
637-
639+
if (new->uid != old->uid) {
640+
retval = set_user(new);
641+
if (retval < 0)
642+
goto error;
643+
}
638644
if (ruid != (uid_t) -1 ||
639645
(euid != (uid_t) -1 && euid != old->uid))
640646
new->suid = new->euid;
@@ -680,9 +686,10 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
680686
retval = -EPERM;
681687
if (capable(CAP_SETUID)) {
682688
new->suid = new->uid = uid;
683-
if (uid != old->uid && set_user(new) < 0) {
684-
retval = -EAGAIN;
685-
goto error;
689+
if (uid != old->uid) {
690+
retval = set_user(new);
691+
if (retval < 0)
692+
goto error;
686693
}
687694
} else if (uid != old->uid && uid != new->suid) {
688695
goto error;
@@ -734,11 +741,13 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
734741
goto error;
735742
}
736743

737-
retval = -EAGAIN;
738744
if (ruid != (uid_t) -1) {
739745
new->uid = ruid;
740-
if (ruid != old->uid && set_user(new) < 0)
741-
goto error;
746+
if (ruid != old->uid) {
747+
retval = set_user(new);
748+
if (retval < 0)
749+
goto error;
750+
}
742751
}
743752
if (euid != (uid_t) -1)
744753
new->euid = euid;

kernel/user.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,24 @@ static void free_user(struct user_struct *up, unsigned long flags)
362362

363363
#endif
364364

365+
#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
366+
/*
367+
* We need to check if a setuid can take place. This function should be called
368+
* before successfully completing the setuid.
369+
*/
370+
int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
371+
{
372+
373+
return sched_rt_can_attach(up->tg, tsk);
374+
375+
}
376+
#else
377+
int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
378+
{
379+
return 1;
380+
}
381+
#endif
382+
365383
/*
366384
* Locate the user_struct for the passed UID. If found, take a ref on it. The
367385
* caller must undo that ref with free_uid().

0 commit comments

Comments
 (0)