linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* RT scheduling and a way to make a process hang, unkillable
@ 2009-02-15  0:51 Corey Hickey
  2009-02-15 11:24 ` Peter Zijlstra
  0 siblings, 1 reply; 26+ messages in thread
From: Corey Hickey @ 2009-02-15  0:51 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2375 bytes --]

Hello,

I've encountered a bit of a problem in recent kernels that include
"Group scheduling for SCHED_RR/FIFO": it is possible for a process run
by root to hang itself and become unkillable--even by a 'kill -9'.

The following kernel options must be set:
CONFIG_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_USER_SCHED=y

The procedure is for a program to:
1. run as root
2. set SCHED_FIFO
3. change UID to a user with no realtime CPU share allocated

I'm attaching a test program that does exactly this. Run it with no
arguments or examine the print_usage() function to see detailed
information. Briefly, though, it should be run as root with the path to
a program to exec, like:
# ./hangme /bin/bash

The program hangs in a "running" state, like this:
nobody  4357  0.0  0.0    904    16 pts/1    R+   16:09   0:00 /bin/bash

The only way to kill the program is to allocate the corresponding user
some realtime CPU share:
echo 10000 > /sys/kernel/uids/65534/cpu_rt_runtime


This may or may not actually be a bug, but I think it's at least
confusing and unexpected. I had a difficult time narrowing this down
from a problem I was having with Debian's slmodemd package. I think it
would be much nicer for setuid() to return an error if the process is
realtime and the target user doesn't have any CPU share allocated (if
that's feasible).


This problem is similar in principle to a bug reported by Rafael J.
Wysocki on 2008-02-01, and which was subsequently fixed:

http://lkml.org/lkml/2008/1/31/490
http://lkml.org/lkml/2008/2/4/332

If I understand correctly, that was a case in which a program would hang
by doing the following:
1. run setuid-root
2. set SCHED_FIFO
3. change effective UID to match real UID

The difference in my case is that the program is running with root's
real UID as well as effective UID, so, at the time SCHED_FIFO is set,
there's no reason to deny realtime priority. My program changes real UID
 _after_ setting SCHED_FIFO, and that's what causes the hang.


I've run my test program, with the same results, on the following kernels:
2.6.26
2.6.28
2.6.29-rc5

Warning! Under 2.6.28 it is impossible to allocate users CPU share, and
the program will not be killable:

http://lkml.org/lkml/2009/1/14/113


I'm also attaching my kernel configuration. Please let me know if you'd
like more information or for me to test a patch.

Thank you,
Corey

[-- Attachment #2: hangme.c --]
[-- Type: text/x-csrc, Size: 2715 bytes --]

#include <stdio.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sched.h>
#include <errno.h>
#include <limits.h>

#define UID 65534

int adjust_priority() {
  struct sched_param sp;
  sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
  if (sched_setscheduler(0, SCHED_FIFO, &sp) != -1) {
    printf("running as SCHED_FIFO, priority %d\n", sp.sched_priority);
    return 1;
  } else {
    puts("could not set SCHED_FIFO");
    return 0;
  }
}

int change_uid() {
  if (setuid(UID)) {
    int err = errno;
    printf("setuid() failed: %s\n", strerror(err));
    return 0;
  }
  printf("UID set to %d\n", UID);
  return 1;
}


void print_usage() {
  printf(
"This program attempts to illustrate a way by which a process can hang and\n"
"become unkillable:\n"
"1. run as root\n"
"2. set SCHED_FIFO\n"
"3. change to a user with no realtime CPU share allocated\n"
"\n"
"The following kernel options must be set:\n"
"CONFIG_GROUP_SCHED=y\n"
"CONFIG_RT_GROUP_SCHED=y\n"
"CONFIG_USER_SCHED=y\n"
"\n"
"Warning: do not try this under Linux 2.6.28. Due to a bug, you will not be\n"
"able to write to cpu_rt_runtime:\n"
"http://lkml.org/lkml/2009/1/14/113\n"
"This appears to have been fixed in 2.6.29-rc2, but not yet in 2.6.28.5\n"
"\n"
"If you're running a 2.6.29-rc kernel, you should lower root's\n"
"cpu_rt_runtime first:\n"
"# echo 900000 > /sys/kernel/uids/0/cpu_rt_runtime\n"
"\n"
"usage: ./hangme </path/to/executable> [arg1 ...]\n"
"example: ./hangme /bin/bash\n"
"\n"
"The executable specified should take some time to run, otherwise it may\n"
"complete and exit normally within the current time slice (I assume).\n"
"Running a shell is ideal.\n"
);
}

void print_msg() {
  printf(
"\n"
"I am now going to change my UID. See if I hang.\n"
"If I do, try to kill me:\n"
"# kill -9 %d\n"
"Once you're ready to make me unhang:\n"
"# echo 10000 > /sys/kernel/uids/%d/cpu_rt_runtime\n"
"\n"
"Note: if you get an \"Invalid argument\" error with 2.6.29-rc kernels,\n"
"try lowering root's runtime like this:\n"
"# echo 900000 > /sys/kernel/uids/0/cpu_rt_runtime\n"
"...but it doesn't seem to work once this program is running!\n"
"Is that another bug or do I misunderstand?\n"
"\n"
, getpid(), UID);
}

int main(int argc, char **argv)
{
  if (argc <= 1) {
    print_usage();
    return 2;
  }
  if (getuid()) {
    printf("this test only works when run as root\n");
    return 2;
  }
  if (!adjust_priority()) {
    return 1;
  }
  print_msg();
  if (! change_uid()) {
    return 1;
  }
  ++argv;
  printf("going to exec: %s\n", argv[0]);
  execv(argv[0], argv);
  printf("exec failed\n");
  return 1;
}

[-- Attachment #3: config-2.6.29-rc5.bz2 --]
[-- Type: application/octet-stream, Size: 6606 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-15  0:51 RT scheduling and a way to make a process hang, unkillable Corey Hickey
@ 2009-02-15 11:24 ` Peter Zijlstra
  2009-02-16 10:36   ` Dhaval Giani
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-15 11:24 UTC (permalink / raw)
  To: Corey Hickey; +Cc: linux-kernel, Dhaval Giani

On Sat, 2009-02-14 at 16:51 -0800, Corey Hickey wrote:
> Hello,
> 
> I've encountered a bit of a problem in recent kernels that include
> "Group scheduling for SCHED_RR/FIFO": it is possible for a process run
> by root to hang itself and become unkillable--even by a 'kill -9'.
> 
> The following kernel options must be set:
> CONFIG_GROUP_SCHED=y
> CONFIG_RT_GROUP_SCHED=y
> CONFIG_USER_SCHED=y
> 
> The procedure is for a program to:
> 1. run as root
> 2. set SCHED_FIFO
> 3. change UID to a user with no realtime CPU share allocated

Hmm, setuid() should fail in that situation.

/me goes peek at code.

Can't find any code to make that happen, Dhaval didn't we fix that at
one point?


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-15 11:24 ` Peter Zijlstra
@ 2009-02-16 10:36   ` Dhaval Giani
  2009-02-16 11:08     ` Peter Zijlstra
  2009-02-16 20:16     ` RT scheduling and a way to make a process hang, unkillable Kyle Moffett
  0 siblings, 2 replies; 26+ messages in thread
From: Dhaval Giani @ 2009-02-16 10:36 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Sun, Feb 15, 2009 at 12:24:56PM +0100, Peter Zijlstra wrote:
> On Sat, 2009-02-14 at 16:51 -0800, Corey Hickey wrote:
> > Hello,
> > 
> > I've encountered a bit of a problem in recent kernels that include
> > "Group scheduling for SCHED_RR/FIFO": it is possible for a process run
> > by root to hang itself and become unkillable--even by a 'kill -9'.
> > 
> > The following kernel options must be set:
> > CONFIG_GROUP_SCHED=y
> > CONFIG_RT_GROUP_SCHED=y
> > CONFIG_USER_SCHED=y
> > 
> > The procedure is for a program to:
> > 1. run as root
> > 2. set SCHED_FIFO
> > 3. change UID to a user with no realtime CPU share allocated
> 
> Hmm, setuid() should fail in that situation.
> 
> /me goes peek at code.
> 
> Can't find any code to make that happen, Dhaval didn't we fix that at
> one point?

So after some searching around, I realized we did not. Does this help?
It fixes it on my system,

--
sched: Don't allow setuid to succeed if the user does not have rt bandwidth

Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.

Disclaimer: Not sure about the return values, and if setuid allows
return values other than EPERM and EAGAIN.

Not-Yet-Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>

Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -2320,9 +2320,12 @@ extern long sched_group_rt_runtime(struc
 extern int sched_group_set_rt_period(struct task_group *tg,
 				      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
 
 	return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+	/* Don't accept realtime tasks when there is no way for them to run */
+	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
 		      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-	/* Don't accept realtime tasks when there is no way for them to run */
-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+	if (sched_rt_can_attach(cgroup_tg(cgrp), tsk))
 		return -EINVAL;
 #else
 	/* We don't support RT-tasks being in separate groups */
Index: linux-2.6/kernel/user.c
===================================================================
--- linux-2.6.orig/kernel/user.c
+++ linux-2.6/kernel/user.c
@@ -216,8 +216,28 @@ static ssize_t cpu_rt_period_store(struc
 
 static struct kobj_attribute cpu_rt_period_attr =
 	__ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
+
 #endif
 
+#ifdef CONFIG_RT_GROUP_SCHED && CONFIG_USER_SCHED
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+
+int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	struct user_struct *up = find_user(uid);
+
+	return sched_rt_can_attach(up->tg, tsk);
+}
+#else
+int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	return 0;
+}
+
+#endif
 /* default attributes per uid directory */
 static struct attribute *uids_attributes[] = {
 #ifdef CONFIG_FAIR_GROUP_SCHED
Index: linux-2.6/kernel/sys.c
===================================================================
--- linux-2.6.orig/kernel/sys.c
+++ linux-2.6/kernel/sys.c
@@ -579,6 +579,15 @@ static int set_user(struct cred *new)
 		return -EAGAIN;
 	}
 
+	/*
+	 * Though rt_task_can_switch_user returns EINVAL on failure, we
+	 * return EAGAIN so as not to break semantics and because
+	 * EAGAIN implies resource not available which is the case in
+	 * this case.
+	 */
+	if (rt_task_can_switch_user(new->uid, current))
+		return -EAGAIN;
+
 	free_uid(new->user);
 	new->user = new_user;
 	return 0;

-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 10:36   ` Dhaval Giani
@ 2009-02-16 11:08     ` Peter Zijlstra
  2009-02-16 12:02       ` Dhaval Giani
  2009-02-16 20:16     ` RT scheduling and a way to make a process hang, unkillable Kyle Moffett
  1 sibling, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-16 11:08 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, 2009-02-16 at 16:06 +0530, Dhaval Giani wrote:

> sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> 
> Corey Hickey reported that on using setuid to change the uid of a
> rt process, the process would be unkillable and not be running.
> This is because there was no rt runtime for that user group. Add
> in a check to see if a user can attach an rt task to its task group.
> 
> Disclaimer: Not sure about the return values, and if setuid allows
> return values other than EPERM and EAGAIN.
> 
> Not-Yet-Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
> 
> Index: linux-2.6/include/linux/sched.h
> ===================================================================
> --- linux-2.6.orig/include/linux/sched.h
> +++ linux-2.6/include/linux/sched.h
> @@ -2320,9 +2320,12 @@ extern long sched_group_rt_runtime(struc
>  extern int sched_group_set_rt_period(struct task_group *tg,
>  				      long rt_period_us);
>  extern long sched_group_rt_period(struct task_group *tg);
> +int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
>  #endif
>  #endif
>  
> +int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk);
> +
>  #ifdef CONFIG_TASK_XACCT
>  static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
>  {
> Index: linux-2.6/kernel/sched.c
> ===================================================================
> --- linux-2.6.orig/kernel/sched.c
> +++ linux-2.6/kernel/sched.c
> @@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
>  
>  	return ret;
>  }
> +
> +int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
> +{
> +	/* Don't accept realtime tasks when there is no way for them to run */
> +	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
>  #else /* !CONFIG_RT_GROUP_SCHED */
>  static int sched_rt_global_constraints(void)
>  {
> @@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
>  		      struct task_struct *tsk)
>  {
>  #ifdef CONFIG_RT_GROUP_SCHED
> -	/* Don't accept realtime tasks when there is no way for them to run */
> -	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
> +	if (sched_rt_can_attach(cgroup_tg(cgrp), tsk))
>  		return -EINVAL;
>  #else
>  	/* We don't support RT-tasks being in separate groups */
> Index: linux-2.6/kernel/user.c
> ===================================================================
> --- linux-2.6.orig/kernel/user.c
> +++ linux-2.6/kernel/user.c
> @@ -216,8 +216,28 @@ static ssize_t cpu_rt_period_store(struc
>  
>  static struct kobj_attribute cpu_rt_period_attr =
>  	__ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
> +
>  #endif
>  
> +#ifdef CONFIG_RT_GROUP_SCHED && CONFIG_USER_SCHED
> +/*
> + * We need to check if a setuid can take place. This function should be called
> + * before successfully completing the setuid.
> + */
> +
> +int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk)
> +{
> +	struct user_struct *up = find_user(uid);
> +
> +	return sched_rt_can_attach(up->tg, tsk);
> +}

Should that not be !sched_rt_can_attach(), or preferably change
sched_rt_can_attach() to return a boolean, like the name implies.

> +#else
> +int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk)
> +{
> +	return 0;
> +}

With the below this means !RT_GROUP_SCHED || CGROUP never gets to change
uid :-)

> +#endif
>  /* default attributes per uid directory */
>  static struct attribute *uids_attributes[] = {
>  #ifdef CONFIG_FAIR_GROUP_SCHED
> Index: linux-2.6/kernel/sys.c
> ===================================================================
> --- linux-2.6.orig/kernel/sys.c
> +++ linux-2.6/kernel/sys.c
> @@ -579,6 +579,15 @@ static int set_user(struct cred *new)
>  		return -EAGAIN;
>  	}
>  
> +	/*
> +	 * Though rt_task_can_switch_user returns EINVAL on failure, we
> +	 * return EAGAIN so as not to break semantics and because
> +	 * EAGAIN implies resource not available which is the case in
> +	 * this case.
> +	 */
> +	if (rt_task_can_switch_user(new->uid, current))
> +		return -EAGAIN;
> +
>  	free_uid(new->user);
>  	new->user = new_user;
>  	return 0;
> 


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 11:08     ` Peter Zijlstra
@ 2009-02-16 12:02       ` Dhaval Giani
  2009-02-16 12:24         ` Peter Zijlstra
  0 siblings, 1 reply; 26+ messages in thread
From: Dhaval Giani @ 2009-02-16 12:02 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, Feb 16, 2009 at 12:08:36PM +0100, Peter Zijlstra wrote:
> On Mon, 2009-02-16 at 16:06 +0530, Dhaval Giani wrote:
> 
> > sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> > 
> > Corey Hickey reported that on using setuid to change the uid of a
> > rt process, the process would be unkillable and not be running.
> > This is because there was no rt runtime for that user group. Add
> > in a check to see if a user can attach an rt task to its task group.
> > 
> > Disclaimer: Not sure about the return values, and if setuid allows
> > return values other than EPERM and EAGAIN.
> > 
> > Not-Yet-Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
> > 
> > Index: linux-2.6/include/linux/sched.h
> > ===================================================================
> > --- linux-2.6.orig/include/linux/sched.h
> > +++ linux-2.6/include/linux/sched.h
> > @@ -2320,9 +2320,12 @@ extern long sched_group_rt_runtime(struc
> >  extern int sched_group_set_rt_period(struct task_group *tg,
> >  				      long rt_period_us);
> >  extern long sched_group_rt_period(struct task_group *tg);
> > +int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
> >  #endif
> >  #endif
> >  
> > +int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk);
> > +
> >  #ifdef CONFIG_TASK_XACCT
> >  static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
> >  {
> > Index: linux-2.6/kernel/sched.c
> > ===================================================================
> > --- linux-2.6.orig/kernel/sched.c
> > +++ linux-2.6/kernel/sched.c
> > @@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
> >  
> >  	return ret;
> >  }
> > +
> > +int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
> > +{
> > +	/* Don't accept realtime tasks when there is no way for them to run */
> > +	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
> > +		return -EINVAL;
> > +
> > +	return 0;
> > +}
> > +
> >  #else /* !CONFIG_RT_GROUP_SCHED */
> >  static int sched_rt_global_constraints(void)
> >  {
> > @@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
> >  		      struct task_struct *tsk)
> >  {
> >  #ifdef CONFIG_RT_GROUP_SCHED
> > -	/* Don't accept realtime tasks when there is no way for them to run */
> > -	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
> > +	if (sched_rt_can_attach(cgroup_tg(cgrp), tsk))
> >  		return -EINVAL;
> >  #else
> >  	/* We don't support RT-tasks being in separate groups */
> > Index: linux-2.6/kernel/user.c
> > ===================================================================
> > --- linux-2.6.orig/kernel/user.c
> > +++ linux-2.6/kernel/user.c
> > @@ -216,8 +216,28 @@ static ssize_t cpu_rt_period_store(struc
> >  
> >  static struct kobj_attribute cpu_rt_period_attr =
> >  	__ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
> > +
> >  #endif
> >  
> > +#ifdef CONFIG_RT_GROUP_SCHED && CONFIG_USER_SCHED
> > +/*
> > + * We need to check if a setuid can take place. This function should be called
> > + * before successfully completing the setuid.
> > + */
> > +
> > +int rt_task_can_switch_user(uid_t uid, struct task_struct *tsk)
> > +{
> > +	struct user_struct *up = find_user(uid);
> > +
> > +	return sched_rt_can_attach(up->tg, tsk);
> > +}
> 
> Should that not be !sched_rt_can_attach(), or preferably change
> sched_rt_can_attach() to return a boolean, like the name implies.
> 

Yeah, made it boolean. how does the following look?

--
sched: Don't allow setuid to succeed if the user does not have rt bandwidth

Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.

Disclaimer: Not sure about the return values, and if setuid allows
return values other than EPERM and EAGAIN.

Changes from v1:
1. Peter suggested that rt_task_can_change_user should be renamed to
task_can_change_user
2. Changed sched_rt_can_attach to boolean.

Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>


Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -2320,9 +2320,12 @@ extern long sched_group_rt_runtime(struc
 extern int sched_group_set_rt_period(struct task_group *tg,
 				      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+int task_can_switch_user(uid_t uid, struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
 
 	return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+	/* Don't accept realtime tasks when there is no way for them to run */
+	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+		return 0;
+
+	return 1;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
 		      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-	/* Don't accept realtime tasks when there is no way for them to run */
-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
 		return -EINVAL;
 #else
 	/* We don't support RT-tasks being in separate groups */
Index: linux-2.6/kernel/user.c
===================================================================
--- linux-2.6.orig/kernel/user.c
+++ linux-2.6/kernel/user.c
@@ -216,8 +216,28 @@ static ssize_t cpu_rt_period_store(struc
 
 static struct kobj_attribute cpu_rt_period_attr =
 	__ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
+
 #endif
 
+#ifdef CONFIG_RT_GROUP_SCHED && CONFIG_USER_SCHED
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+
+int task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	struct user_struct *up = find_user(uid);
+
+	return sched_rt_can_attach(up->tg, tsk);
+}
+#else
+int task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	return 1;
+}
+
+#endif
 /* default attributes per uid directory */
 static struct attribute *uids_attributes[] = {
 #ifdef CONFIG_FAIR_GROUP_SCHED
Index: linux-2.6/kernel/sys.c
===================================================================
--- linux-2.6.orig/kernel/sys.c
+++ linux-2.6/kernel/sys.c
@@ -579,6 +579,9 @@ static int set_user(struct cred *new)
 		return -EAGAIN;
 	}
 
+	if (!task_can_switch_user(new->uid, current))
+		return -EAGAIN;
+
 	free_uid(new->user);
 	new->user = new_user;
 	return 0;
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 12:02       ` Dhaval Giani
@ 2009-02-16 12:24         ` Peter Zijlstra
  2009-02-16 13:14           ` Dhaval Giani
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-16 12:24 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, 2009-02-16 at 17:32 +0530, Dhaval Giani wrote:

> Yeah, made it boolean. how does the following look?

Much better, but look below.

> --
> sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> 
> Corey Hickey reported that on using setuid to change the uid of a
> rt process, the process would be unkillable and not be running.
> This is because there was no rt runtime for that user group. Add
> in a check to see if a user can attach an rt task to its task group.
> 
> Disclaimer: Not sure about the return values, and if setuid allows
> return values other than EPERM and EAGAIN.
> 
> Changes from v1:
> 1. Peter suggested that rt_task_can_change_user should be renamed to
> task_can_change_user
> 2. Changed sched_rt_can_attach to boolean.
> 
> Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
>
> Index: linux-2.6/include/linux/sched.h
> ===================================================================
> --- linux-2.6.orig/include/linux/sched.h
> +++ linux-2.6/include/linux/sched.h
> @@ -2320,9 +2320,12 @@ extern long sched_group_rt_runtime(struc
>  extern int sched_group_set_rt_period(struct task_group *tg,
>  				      long rt_period_us);
>  extern long sched_group_rt_period(struct task_group *tg);
> +int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
>  #endif
>  #endif
>  
> +int task_can_switch_user(uid_t uid, struct task_struct *tsk);
> +
>  #ifdef CONFIG_TASK_XACCT
>  static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
>  {
> Index: linux-2.6/kernel/sched.c
> ===================================================================
> --- linux-2.6.orig/kernel/sched.c
> +++ linux-2.6/kernel/sched.c
> @@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
>  
>  	return ret;
>  }
> +
> +int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
> +{
> +	/* Don't accept realtime tasks when there is no way for them to run */
> +	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
> +		return 0;
> +
> +	return 1;
> +}
> +
>  #else /* !CONFIG_RT_GROUP_SCHED */
>  static int sched_rt_global_constraints(void)
>  {
> @@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
>  		      struct task_struct *tsk)
>  {
>  #ifdef CONFIG_RT_GROUP_SCHED
> -	/* Don't accept realtime tasks when there is no way for them to run */
> -	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
> +	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
>  		return -EINVAL;
>  #else
>  	/* We don't support RT-tasks being in separate groups */
> Index: linux-2.6/kernel/user.c
> ===================================================================
> --- linux-2.6.orig/kernel/user.c
> +++ linux-2.6/kernel/user.c
> @@ -216,8 +216,28 @@ static ssize_t cpu_rt_period_store(struc
>  
>  static struct kobj_attribute cpu_rt_period_attr =
>  	__ATTR(cpu_rt_period, 0644, cpu_rt_period_show, cpu_rt_period_store);
> +
>  #endif
>  
> +#ifdef CONFIG_RT_GROUP_SCHED && CONFIG_USER_SCHED
> +/*
> + * We need to check if a setuid can take place. This function should be called
> + * before successfully completing the setuid.
> + */
> +
> +int task_can_switch_user(uid_t uid, struct task_struct *tsk)
> +{
> +	struct user_struct *up = find_user(uid);
> +
> +	return sched_rt_can_attach(up->tg, tsk);
> +}
> +#else
> +int task_can_switch_user(uid_t uid, struct task_struct *tsk)
> +{
> +	return 1;
> +}
> +
> +#endif
>  /* default attributes per uid directory */
>  static struct attribute *uids_attributes[] = {
>  #ifdef CONFIG_FAIR_GROUP_SCHED
> Index: linux-2.6/kernel/sys.c
> ===================================================================
> --- linux-2.6.orig/kernel/sys.c
> +++ linux-2.6/kernel/sys.c
> @@ -579,6 +579,9 @@ static int set_user(struct cred *new)
>  		return -EAGAIN;
>  	}
>  
> +	if (!task_can_switch_user(new->uid, current))
> +		return -EAGAIN;

you're leaking new_user here.

Best might be to place this test on top before allocating it.

>  	free_uid(new->user);
>  	new->user = new_user;
>  	return 0;


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 12:24         ` Peter Zijlstra
@ 2009-02-16 13:14           ` Dhaval Giani
  2009-02-16 13:19             ` Peter Zijlstra
  2009-02-16 13:20             ` Dhaval Giani
  0 siblings, 2 replies; 26+ messages in thread
From: Dhaval Giani @ 2009-02-16 13:14 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, Feb 16, 2009 at 01:24:42PM +0100, Peter Zijlstra wrote:
> On Mon, 2009-02-16 at 17:32 +0530, Dhaval Giani wrote:
> 
> > Yeah, made it boolean. how does the following look?
> 
> Much better, but look below.
> 

<snip>

> > Index: linux-2.6/kernel/sys.c
> > ===================================================================
> > --- linux-2.6.orig/kernel/sys.c
> > +++ linux-2.6/kernel/sys.c
> > @@ -579,6 +579,9 @@ static int set_user(struct cred *new)
> >  		return -EAGAIN;
> >  	}
> >  
> > +	if (!task_can_switch_user(new->uid, current))
> > +		return -EAGAIN;
> 
> you're leaking new_user here.
> 
> Best might be to place this test on top before allocating it.
> 

Yep, also another memory leak was there, which I fixed in this version.
What about this? (This is not a good day!)

sched: Don't allow setuid to succeed if the user does not have rt bandwidth

Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.

Disclaimer: Not sure about the return values, and if setuid allows
return values other than EPERM and EAGAIN.

Changes from v2:
1. Patch compiles for CONFIG_CGROUP_SCHED as well
2. Fix two memory leaks.

Changes from v1:
1. Peter suggested that rt_task_can_change_user should be renamed to
task_can_change_user
2. Changed sched_rt_can_attach to boolean.

Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>


Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -2320,9 +2320,12 @@ extern long sched_group_rt_runtime(struc
 extern int sched_group_set_rt_period(struct task_group *tg,
 				      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+extern int task_can_switch_user(uid_t uid, struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
 
 	return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+	/* Don't accept realtime tasks when there is no way for them to run */
+	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+		return 0;
+
+	return 1;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
 		      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-	/* Don't accept realtime tasks when there is no way for them to run */
-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
 		return -EINVAL;
 #else
 	/* We don't support RT-tasks being in separate groups */
Index: linux-2.6/kernel/user.c
===================================================================
--- linux-2.6.orig/kernel/user.c
+++ linux-2.6/kernel/user.c
@@ -362,6 +362,28 @@ static void free_user(struct user_struct
 
 #endif
 
+#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+int task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	int ret = 1;
+	struct user_struct *up = find_user(uid);
+
+	ret = sched_rt_can_attach(up->tg, tsk);
+	free_uid(up);
+
+	return ret;
+}
+#else
+int task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	return 1;
+}
+#endif
+
 /*
  * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
  * caller must undo that ref with free_uid().
Index: linux-2.6/kernel/sys.c
===================================================================
--- linux-2.6.orig/kernel/sys.c
+++ linux-2.6/kernel/sys.c
@@ -560,7 +560,7 @@ error:
 	abort_creds(new);
 	return retval;
 }
-  
+
 /*
  * change the user struct in a credentials set to match the new UID
  */
@@ -572,6 +572,9 @@ static int set_user(struct cred *new)
 	if (!new_user)
 		return -EAGAIN;
 
+	if (!task_can_switch_user(new->uid, current))
+		return -EAGAIN;
+
 	if (atomic_read(&new_user->processes) >=
 				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
 			new_user != INIT_USER) {
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 13:14           ` Dhaval Giani
@ 2009-02-16 13:19             ` Peter Zijlstra
  2009-02-16 14:23               ` Peter Zijlstra
  2009-02-16 13:20             ` Dhaval Giani
  1 sibling, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-16 13:19 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, 2009-02-16 at 18:44 +0530, Dhaval Giani wrote:
>  (This is not a good day!)

Monday strikes again ;-)

> @@ -572,6 +572,9 @@ static int set_user(struct cred *new)
>  	if (!new_user)
>  		return -EAGAIN;

So here we just allocated new_user and made sure we didn't fail that
allocation.

> +	if (!task_can_switch_user(new->uid, current))
> +		return -EAGAIN;

And here you bail, without freeing new_user. The idea was to do this
check before alloc_uid().

>  	if (atomic_read(&new_user->processes) >=
>  				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
>  			new_user != INIT_USER) {


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 13:14           ` Dhaval Giani
  2009-02-16 13:19             ` Peter Zijlstra
@ 2009-02-16 13:20             ` Dhaval Giani
  2009-02-16 19:18               ` Corey Hickey
  1 sibling, 1 reply; 26+ messages in thread
From: Dhaval Giani @ 2009-02-16 13:20 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, Feb 16, 2009 at 06:44:40PM +0530, Dhaval Giani wrote:
> On Mon, Feb 16, 2009 at 01:24:42PM +0100, Peter Zijlstra wrote:
> > On Mon, 2009-02-16 at 17:32 +0530, Dhaval Giani wrote:
> > 
> > > Yeah, made it boolean. how does the following look?
> > 
> > Much better, but look below.
> > 
> 
> <snip>
> 
> > > Index: linux-2.6/kernel/sys.c
> > > ===================================================================
> > > --- linux-2.6.orig/kernel/sys.c
> > > +++ linux-2.6/kernel/sys.c
> > > @@ -579,6 +579,9 @@ static int set_user(struct cred *new)
> > >  		return -EAGAIN;
> > >  	}
> > >  
> > > +	if (!task_can_switch_user(new->uid, current))
> > > +		return -EAGAIN;
> > 
> > you're leaking new_user here.
> > 
> > Best might be to place this test on top before allocating it.
> > 
> 
> Yep, also another memory leak was there, which I fixed in this version.
> What about this? (This is not a good day!)
> 

And it continues on! Please try this version.

sched: Don't allow setuid to succeed if the user does not have rt bandwidth

Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.

Disclaimer: Not sure about the return values, and if setuid allows
return values other than EPERM and EAGAIN.

Changes from v3:
1. Actually fix the leak.

Changes from v2:
1. Patch compiles for CONFIG_CGROUP_SCHED as well
2. Fix two memory leaks.

Changes from v1:
1. Peter suggested that rt_task_can_change_user should be renamed to
task_can_change_user
2. Changed sched_rt_can_attach to boolean.

Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>


Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -2320,9 +2320,12 @@ extern long sched_group_rt_runtime(struc
 extern int sched_group_set_rt_period(struct task_group *tg,
 				      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+extern int task_can_switch_user(uid_t uid, struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
 
 	return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+	/* Don't accept realtime tasks when there is no way for them to run */
+	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+		return 0;
+
+	return 1;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
 		      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-	/* Don't accept realtime tasks when there is no way for them to run */
-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
 		return -EINVAL;
 #else
 	/* We don't support RT-tasks being in separate groups */
Index: linux-2.6/kernel/user.c
===================================================================
--- linux-2.6.orig/kernel/user.c
+++ linux-2.6/kernel/user.c
@@ -362,6 +362,28 @@ static void free_user(struct user_struct
 
 #endif
 
+#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+int task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	int ret = 1;
+	struct user_struct *up = find_user(uid);
+
+	ret = sched_rt_can_attach(up->tg, tsk);
+	free_uid(up);
+
+	return ret;
+}
+#else
+int task_can_switch_user(uid_t uid, struct task_struct *tsk)
+{
+	return 1;
+}
+#endif
+
 /*
  * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
  * caller must undo that ref with free_uid().
Index: linux-2.6/kernel/sys.c
===================================================================
--- linux-2.6.orig/kernel/sys.c
+++ linux-2.6/kernel/sys.c
@@ -560,7 +560,7 @@ error:
 	abort_creds(new);
 	return retval;
 }
-  
+
 /*
  * change the user struct in a credentials set to match the new UID
  */
@@ -568,6 +568,9 @@ static int set_user(struct cred *new)
 {
 	struct user_struct *new_user;
 
+	if (!task_can_switch_user(new->uid, current))
+		return -EAGAIN;
+
 	new_user = alloc_uid(current_user_ns(), new->uid);
 	if (!new_user)
 		return -EAGAIN;
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 13:19             ` Peter Zijlstra
@ 2009-02-16 14:23               ` Peter Zijlstra
  0 siblings, 0 replies; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-16 14:23 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, 2009-02-16 at 14:19 +0100, Peter Zijlstra wrote:
> On Mon, 2009-02-16 at 18:44 +0530, Dhaval Giani wrote:
> >  (This is not a good day!)
> 
> Monday strikes again ;-)
> 
> > @@ -572,6 +572,9 @@ static int set_user(struct cred *new)
> >  	if (!new_user)
> >  		return -EAGAIN;
> 
> So here we just allocated new_user and made sure we didn't fail that
> allocation.
> 
> > +	if (!task_can_switch_user(new->uid, current))
> > +		return -EAGAIN;
> 
> And here you bail, without freeing new_user. The idea was to do this
> check before alloc_uid().
> 
> >  	if (atomic_read(&new_user->processes) >=
> >  				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
> >  			new_user != INIT_USER) {

Ah, I now see I send you down a hole here,.. your find_user() in
task_can_switch_user() relies on that alloc_uid(). So you have to do it
after, and just free the new_user thingy when the test fails.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 13:20             ` Dhaval Giani
@ 2009-02-16 19:18               ` Corey Hickey
  2009-02-17  5:00                 ` Dhaval Giani
  0 siblings, 1 reply; 26+ messages in thread
From: Corey Hickey @ 2009-02-16 19:18 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Peter Zijlstra, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

[-- Attachment #1: Type: text/plain, Size: 2609 bytes --]

Dhaval Giani wrote:
> And it continues on! Please try this version.
> 
> sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> 
> Corey Hickey reported that on using setuid to change the uid of a
> rt process, the process would be unkillable and not be running.
> This is because there was no rt runtime for that user group. Add
> in a check to see if a user can attach an rt task to its task group.
> 
> Disclaimer: Not sure about the return values, and if setuid allows
> return values other than EPERM and EAGAIN.
> 
> Changes from v3:
> 1. Actually fix the leak.
> 
> Changes from v2:
> 1. Patch compiles for CONFIG_CGROUP_SCHED as well
> 2. Fix two memory leaks.
> 
> Changes from v1:
> 1. Peter suggested that rt_task_can_change_user should be renamed to
> task_can_change_user
> 2. Changed sched_rt_can_attach to boolean.
> 
> Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>

Thank you, Peter and Dhaval, for looking at this. I appreciate your work.

I tested patch v4 on 2.6.29-rc5, and I get frequent kernel BUG messages.
Should I be testing your patch on a different source tree? The patch
applied to rc5 ok but with lots of offsets.

I attached the full dmesg log, and here's a sample of one of the messages:

------------------------------------------------------------------------
BUG: unable to handle kernel NULL pointer dereference at 00000034
IP: [<c011d642>] task_can_switch_user+0xe/0x28
*pde = 00000000
Oops: 0000 [#1]
last sysfs file: /sys/devices/virtual/net/lo/address
Modules linked in:

Pid: 1058, comm: vol_id Not tainted (2.6.29-rc5-fix1 #1) Satellite 5105
EIP: 0060:[<c011d642>] EFLAGS: 00010202 CPU: 0
EIP is at task_can_switch_user+0xe/0x28
EAX: 00000000 EBX: dfbe6ae0 ECX: 0000fffe EDX: c039a4a0
ESI: 00000000 EDI: 0000fffe EBP: dfbc7f88 ESP: dfbc7f80
 DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
Process vol_id (pid: 1058, ti=dfbc6000 task=dfbe6ae0 task.ti=dfbc6000)
Stack:
 fffffff4 df9a5e80 dfbc7f98 c0120c0a fffffff4 df9a5e80 dfbc7fb0 c0120da8
 df9a5180 0000fffe 00000003 bff8dec1 dfbc6000 c0102b45 0000fffe b8050ff4
 00000000 00000003 bff8dec1 bff8c918 000000d5 0000007b 0000007b c0100000
Call Trace:
 [<c0120c0a>] ? set_user+0x15/0x78
 [<c0120da8>] ? sys_setuid+0x4d/0x9d
 [<c0102b45>] ? sysenter_do_call+0x12/0x25
Code: f2 a1 90 b9 3f c0 e8 58 69 03 00 eb 02 53 9d b8 14 a9 39 c0 e8 fb
49 1b 00 5b 5e 5d c3 55 89 e5 56 53 89 d3 e8 3d fc ff ff 89 c6 <8b> 40
34 89 da e8 4b 22 ff ff 89 c3 89 f0 e8 04 ff ff ff 89 d8
EIP: [<c011d642>] task_can_switch_user+0xe/0x28 SS:ESP 0068:dfbc7f80
---[ end trace 3e1918a81c708690 ]---

Thank you,
Corey

[-- Attachment #2: dmesg.log.gz --]
[-- Type: application/gzip, Size: 6226 bytes --]

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 10:36   ` Dhaval Giani
  2009-02-16 11:08     ` Peter Zijlstra
@ 2009-02-16 20:16     ` Kyle Moffett
  2009-02-16 20:28       ` Peter Zijlstra
  2009-02-17  7:22       ` Dhaval Giani
  1 sibling, 2 replies; 26+ messages in thread
From: Kyle Moffett @ 2009-02-16 20:16 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Peter Zijlstra, Corey Hickey, linux-kernel, Bharata B Rao,
	Balbir Singh, Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, Feb 16, 2009 at 5:36 AM, Dhaval Giani <dhaval@linux.vnet.ibm.com> wrote:
> On Sun, Feb 15, 2009 at 12:24:56PM +0100, Peter Zijlstra wrote:
>> On Sat, 2009-02-14 at 16:51 -0800, Corey Hickey wrote:
>> > The procedure is for a program to:
>> > 1. run as root
>> > 2. set SCHED_FIFO
>> > 3. change UID to a user with no realtime CPU share allocated
>>
>> Hmm, setuid() should fail in that situation.
>>
>> /me goes peek at code.
>>
>> Can't find any code to make that happen, Dhaval didn't we fix that at
>> one point?
>
> So after some searching around, I realized we did not. Does this help?
> It fixes it on my system,
>
> --
> sched: Don't allow setuid to succeed if the user does not have rt bandwidth

Erm, hrm, this reminds me of the old sendmail capabilities bug.  There
are an awful lot of buggy binaries out there who assume that if they
have uid 0 and they call setuid() that it cannot fail.  They then do
all sorts of insecure operations, assuming that they have dropped to
an unprivileged UID.  This one is especially bad because it could bite
*any* program using setuid() which an admin happens to run with chrt.

Specifically, I personally think that:
  *  Process is stuck and unkillable

is a much better result than:
  *  Process runs arbitrary untrusted code with full-root privs in RT mode.

Cheers,
Kyle Moffett

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 20:16     ` RT scheduling and a way to make a process hang, unkillable Kyle Moffett
@ 2009-02-16 20:28       ` Peter Zijlstra
  2009-02-17  7:22       ` Dhaval Giani
  1 sibling, 0 replies; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-16 20:28 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: Dhaval Giani, Corey Hickey, linux-kernel, Bharata B Rao,
	Balbir Singh, Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, 2009-02-16 at 15:16 -0500, Kyle Moffett wrote:
> On Mon, Feb 16, 2009 at 5:36 AM, Dhaval Giani <dhaval@linux.vnet.ibm.com> wrote:
> > On Sun, Feb 15, 2009 at 12:24:56PM +0100, Peter Zijlstra wrote:
> >> On Sat, 2009-02-14 at 16:51 -0800, Corey Hickey wrote:
> >> > The procedure is for a program to:
> >> > 1. run as root
> >> > 2. set SCHED_FIFO
> >> > 3. change UID to a user with no realtime CPU share allocated
> >>
> >> Hmm, setuid() should fail in that situation.
> >>
> >> /me goes peek at code.
> >>
> >> Can't find any code to make that happen, Dhaval didn't we fix that at
> >> one point?
> >
> > So after some searching around, I realized we did not. Does this help?
> > It fixes it on my system,
> >
> > --
> > sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> 
> Erm, hrm, this reminds me of the old sendmail capabilities bug.  There
> are an awful lot of buggy binaries out there who assume that if they
> have uid 0 and they call setuid() that it cannot fail.  They then do
> all sorts of insecure operations, assuming that they have dropped to
> an unprivileged UID.  This one is especially bad because it could bite
> *any* program using setuid() which an admin happens to run with chrt.
> 
> Specifically, I personally think that:
>   *  Process is stuck and unkillable
> 
> is a much better result than:
>   *  Process runs arbitrary untrusted code with full-root privs in RT mode.

You have a point, however there are plenty of ways to fail setuid(), one
of them is severe memory pressure, another is exceeding rlimits, also
the security_*() hooks can do pretty much whatever.

So while security is important, its IMHO not a good enough reason to
preserve broken stuff.

[ dhaval, michael, it appears setuid() already returns errors outside
those specified by POSIX, so I'd rather fail with -ENOTIME, or similar,
rather than with -EAGAIN ]


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 19:18               ` Corey Hickey
@ 2009-02-17  5:00                 ` Dhaval Giani
  2009-02-17 10:15                   ` Dhaval Giani
  0 siblings, 1 reply; 26+ messages in thread
From: Dhaval Giani @ 2009-02-17  5:00 UTC (permalink / raw)
  To: Corey Hickey
  Cc: Peter Zijlstra, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, Feb 16, 2009 at 11:18:36AM -0800, Corey Hickey wrote:
> Dhaval Giani wrote:
> > And it continues on! Please try this version.
> > 
> > sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> > 
> > Corey Hickey reported that on using setuid to change the uid of a
> > rt process, the process would be unkillable and not be running.
> > This is because there was no rt runtime for that user group. Add
> > in a check to see if a user can attach an rt task to its task group.
> > 
> > Disclaimer: Not sure about the return values, and if setuid allows
> > return values other than EPERM and EAGAIN.
> > 
> > Changes from v3:
> > 1. Actually fix the leak.
> > 
> > Changes from v2:
> > 1. Patch compiles for CONFIG_CGROUP_SCHED as well
> > 2. Fix two memory leaks.
> > 
> > Changes from v1:
> > 1. Peter suggested that rt_task_can_change_user should be renamed to
> > task_can_change_user
> > 2. Changed sched_rt_can_attach to boolean.
> > 
> > Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
> 
> Thank you, Peter and Dhaval, for looking at this. I appreciate your work.
> 
> I tested patch v4 on 2.6.29-rc5, and I get frequent kernel BUG messages.
> Should I be testing your patch on a different source tree? The patch
> applied to rc5 ok but with lots of offsets.
> 

This was on top of tip I think. But yeah, that would be expected.
Yesterday was really not working out, I figured out this one, and had
fixed this in the next version. I have a better patch arond here.

thanks,
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-16 20:16     ` RT scheduling and a way to make a process hang, unkillable Kyle Moffett
  2009-02-16 20:28       ` Peter Zijlstra
@ 2009-02-17  7:22       ` Dhaval Giani
  1 sibling, 0 replies; 26+ messages in thread
From: Dhaval Giani @ 2009-02-17  7:22 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: Peter Zijlstra, Corey Hickey, linux-kernel, Bharata B Rao,
	Balbir Singh, Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

On Mon, Feb 16, 2009 at 03:16:25PM -0500, Kyle Moffett wrote:
> On Mon, Feb 16, 2009 at 5:36 AM, Dhaval Giani <dhaval@linux.vnet.ibm.com> wrote:
> > On Sun, Feb 15, 2009 at 12:24:56PM +0100, Peter Zijlstra wrote:
> >> On Sat, 2009-02-14 at 16:51 -0800, Corey Hickey wrote:
> >> > The procedure is for a program to:
> >> > 1. run as root
> >> > 2. set SCHED_FIFO
> >> > 3. change UID to a user with no realtime CPU share allocated
> >>
> >> Hmm, setuid() should fail in that situation.
> >>
> >> /me goes peek at code.
> >>
> >> Can't find any code to make that happen, Dhaval didn't we fix that at
> >> one point?
> >
> > So after some searching around, I realized we did not. Does this help?
> > It fixes it on my system,
> >
> > --
> > sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> 
> Erm, hrm, this reminds me of the old sendmail capabilities bug.  There
> are an awful lot of buggy binaries out there who assume that if they
> have uid 0 and they call setuid() that it cannot fail.  They then do
> all sorts of insecure operations, assuming that they have dropped to
> an unprivileged UID.  This one is especially bad because it could bite
> *any* program using setuid() which an admin happens to run with chrt.
> 

Would that not be a bug in the application itself and fixed there
itself? As Peter mentions there are other ways setuid can fail as well.

> Specifically, I personally think that:
>   *  Process is stuck and unkillable
> 
> is a much better result than:
>   *  Process runs arbitrary untrusted code with full-root privs in RT mode.
> 

thanks,
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-17  5:00                 ` Dhaval Giani
@ 2009-02-17 10:15                   ` Dhaval Giani
  2009-02-17 11:15                     ` Peter Zijlstra
  0 siblings, 1 reply; 26+ messages in thread
From: Dhaval Giani @ 2009-02-17 10:15 UTC (permalink / raw)
  To: Corey Hickey
  Cc: Peter Zijlstra, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages

> This was on top of tip I think. But yeah, that would be expected.
> Yesterday was really not working out, I figured out this one, and had
> fixed this in the next version. I have a better patch arond here.
> 

This is on top of tip, and should have everything fixed up.

/me has his fingers crossed :)


sched: Don't allow setuid to succeed if the user does not have rt bandwidth

Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.

Changes from v5:
1. free up the user struct on failure
2. Use the user struct obtained in set_user
3. Change the return value to ENOSPC, since this makes more sense, we do
not have RT runtime available to us.

Changes from v4:
1. Check if find_user returns a valid user struct.

Changes from v3:
1. Actually fix the leak.

Changes from v2:
1. Patch compiles for CONFIG_CGROUP_SCHED as well
2. Fix two memory leaks.

Changes from v1:
1. Peter suggested that rt_task_can_change_user should be renamed to
task_can_change_user
2. Changed sched_rt_can_attach to boolean.

Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>


Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -2320,9 +2320,13 @@ extern long sched_group_rt_runtime(struc
 extern int sched_group_set_rt_period(struct task_group *tg,
 				      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+extern int task_can_switch_user(struct user_struct *up,
+					struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
 
 	return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+	/* Don't accept realtime tasks when there is no way for them to run */
+	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+		return 0;
+
+	return 1;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
 		      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-	/* Don't accept realtime tasks when there is no way for them to run */
-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
 		return -EINVAL;
 #else
 	/* We don't support RT-tasks being in separate groups */
Index: linux-2.6/kernel/user.c
===================================================================
--- linux-2.6.orig/kernel/user.c
+++ linux-2.6/kernel/user.c
@@ -362,6 +362,24 @@ static void free_user(struct user_struct
 
 #endif
 
+#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+
+	return sched_rt_can_attach(up->tg, tsk);
+
+}
+#else
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+	return 1;
+}
+#endif
+
 /*
  * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
  * caller must undo that ref with free_uid().
Index: linux-2.6/kernel/sys.c
===================================================================
--- linux-2.6.orig/kernel/sys.c
+++ linux-2.6/kernel/sys.c
@@ -560,7 +560,7 @@ error:
 	abort_creds(new);
 	return retval;
 }
-  
+
 /*
  * change the user struct in a credentials set to match the new UID
  */
@@ -572,6 +572,11 @@ static int set_user(struct cred *new)
 	if (!new_user)
 		return -EAGAIN;
 
+	if (!task_can_switch_user(new_user, current)) {
+		free_uid(new_user);
+		return -ENOSPC;
+	}
+
 	if (atomic_read(&new_user->processes) >=
 				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
 			new_user != INIT_USER) {
@@ -632,10 +637,11 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, u
 			goto error;
 	}
 
-	retval = -EAGAIN;
-	if (new->uid != old->uid && set_user(new) < 0)
-		goto error;
-
+	if (new->uid != old->uid) {
+		retval = set_user(new);
+		if (retval < 0)
+			goto error;
+	}
 	if (ruid != (uid_t) -1 ||
 	    (euid != (uid_t) -1 && euid != old->uid))
 		new->suid = new->euid;
@@ -681,9 +687,10 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
 	retval = -EPERM;
 	if (capable(CAP_SETUID)) {
 		new->suid = new->uid = uid;
-		if (uid != old->uid && set_user(new) < 0) {
-			retval = -EAGAIN;
-			goto error;
+		if (uid != old->uid) {
+			retval = set_user(new);
+			if (retval < 0)
+				goto error;
 		}
 	} else if (uid != old->uid && uid != new->suid) {
 		goto error;
@@ -735,11 +742,13 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, 
 			goto error;
 	}
 
-	retval = -EAGAIN;
 	if (ruid != (uid_t) -1) {
 		new->uid = ruid;
-		if (ruid != old->uid && set_user(new) < 0)
-			goto error;
+		if (ruid != old->uid) {
+			retval = set_user(new);
+			if (retval < 0)
+				goto error;
+		}
 	}
 	if (euid != (uid_t) -1)
 		new->euid = euid;
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-17 10:15                   ` Dhaval Giani
@ 2009-02-17 11:15                     ` Peter Zijlstra
  2009-02-18  0:09                       ` Corey Hickey
  2009-02-23 11:45                       ` Dhaval Giani
  0 siblings, 2 replies; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-17 11:15 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages, Alan Cox

On Tue, 2009-02-17 at 15:45 +0530, Dhaval Giani wrote:

> sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> 
> Corey Hickey reported that on using setuid to change the uid of a
> rt process, the process would be unkillable and not be running.
> This is because there was no rt runtime for that user group. Add
> in a check to see if a user can attach an rt task to its task group.

This looks good to me.

Does anybody object to the -ENOSPC return value? Should we introduce
-ENOTIME for that?

Michael, Alan?

> Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>

Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>

Ingo, I'll send you the patch once the error issue is settled.

> Index: linux-2.6/include/linux/sched.h
> ===================================================================
> --- linux-2.6.orig/include/linux/sched.h
> +++ linux-2.6/include/linux/sched.h
> @@ -2320,9 +2320,13 @@ extern long sched_group_rt_runtime(struc
>  extern int sched_group_set_rt_period(struct task_group *tg,
>  				      long rt_period_us);
>  extern long sched_group_rt_period(struct task_group *tg);
> +extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
>  #endif
>  #endif
>  
> +extern int task_can_switch_user(struct user_struct *up,
> +					struct task_struct *tsk);
> +
>  #ifdef CONFIG_TASK_XACCT
>  static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
>  {
> Index: linux-2.6/kernel/sched.c
> ===================================================================
> --- linux-2.6.orig/kernel/sched.c
> +++ linux-2.6/kernel/sched.c
> @@ -9466,6 +9466,16 @@ static int sched_rt_global_constraints(v
>  
>  	return ret;
>  }
> +
> +int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
> +{
> +	/* Don't accept realtime tasks when there is no way for them to run */
> +	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
> +		return 0;
> +
> +	return 1;
> +}
> +
>  #else /* !CONFIG_RT_GROUP_SCHED */
>  static int sched_rt_global_constraints(void)
>  {
> @@ -9559,8 +9569,7 @@ cpu_cgroup_can_attach(struct cgroup_subs
>  		      struct task_struct *tsk)
>  {
>  #ifdef CONFIG_RT_GROUP_SCHED
> -	/* Don't accept realtime tasks when there is no way for them to run */
> -	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
> +	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
>  		return -EINVAL;
>  #else
>  	/* We don't support RT-tasks being in separate groups */
> Index: linux-2.6/kernel/user.c
> ===================================================================
> --- linux-2.6.orig/kernel/user.c
> +++ linux-2.6/kernel/user.c
> @@ -362,6 +362,24 @@ static void free_user(struct user_struct
>  
>  #endif
>  
> +#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
> +/*
> + * We need to check if a setuid can take place. This function should be called
> + * before successfully completing the setuid.
> + */
> +int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
> +{
> +
> +	return sched_rt_can_attach(up->tg, tsk);
> +
> +}
> +#else
> +int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
> +{
> +	return 1;
> +}
> +#endif
> +
>  /*
>   * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
>   * caller must undo that ref with free_uid().
> Index: linux-2.6/kernel/sys.c
> ===================================================================
> --- linux-2.6.orig/kernel/sys.c
> +++ linux-2.6/kernel/sys.c
> @@ -560,7 +560,7 @@ error:
>  	abort_creds(new);
>  	return retval;
>  }
> -  
> +
>  /*
>   * change the user struct in a credentials set to match the new UID
>   */
> @@ -572,6 +572,11 @@ static int set_user(struct cred *new)
>  	if (!new_user)
>  		return -EAGAIN;
>  
> +	if (!task_can_switch_user(new_user, current)) {
> +		free_uid(new_user);
> +		return -ENOSPC;
> +	}
> +
>  	if (atomic_read(&new_user->processes) >=
>  				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
>  			new_user != INIT_USER) {
> @@ -632,10 +637,11 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, u
>  			goto error;
>  	}
>  
> -	retval = -EAGAIN;
> -	if (new->uid != old->uid && set_user(new) < 0)
> -		goto error;
> -
> +	if (new->uid != old->uid) {
> +		retval = set_user(new);
> +		if (retval < 0)
> +			goto error;
> +	}
>  	if (ruid != (uid_t) -1 ||
>  	    (euid != (uid_t) -1 && euid != old->uid))
>  		new->suid = new->euid;
> @@ -681,9 +687,10 @@ SYSCALL_DEFINE1(setuid, uid_t, uid)
>  	retval = -EPERM;
>  	if (capable(CAP_SETUID)) {
>  		new->suid = new->uid = uid;
> -		if (uid != old->uid && set_user(new) < 0) {
> -			retval = -EAGAIN;
> -			goto error;
> +		if (uid != old->uid) {
> +			retval = set_user(new);
> +			if (retval < 0)
> +				goto error;
>  		}
>  	} else if (uid != old->uid && uid != new->suid) {
>  		goto error;
> @@ -735,11 +742,13 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, 
>  			goto error;
>  	}
>  
> -	retval = -EAGAIN;
>  	if (ruid != (uid_t) -1) {
>  		new->uid = ruid;
> -		if (ruid != old->uid && set_user(new) < 0)
> -			goto error;
> +		if (ruid != old->uid) {
> +			retval = set_user(new);
> +			if (retval < 0)
> +				goto error;
> +		}
>  	}
>  	if (euid != (uid_t) -1)
>  		new->euid = euid;


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-17 11:15                     ` Peter Zijlstra
@ 2009-02-18  0:09                       ` Corey Hickey
  2009-02-23 11:45                       ` Dhaval Giani
  1 sibling, 0 replies; 26+ messages in thread
From: Corey Hickey @ 2009-02-18  0:09 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Dhaval Giani, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages, Alan Cox

Peter Zijlstra wrote:
> On Tue, 2009-02-17 at 15:45 +0530, Dhaval Giani wrote:
> 
>> sched: Don't allow setuid to succeed if the user does not have rt bandwidth
>>
>> Corey Hickey reported that on using setuid to change the uid of a
>> rt process, the process would be unkillable and not be running.
>> This is because there was no rt runtime for that user group. Add
>> in a check to see if a user can attach an rt task to its task group.
> 
> This looks good to me.
> 
> Does anybody object to the -ENOSPC return value? Should we introduce
> -ENOTIME for that?

setuid() failed: No space left on device

For what it's worth, a message like that would be confusing to me if I
didn't already know the context. It's not a big problem in my opinion,
though; I'm just happy there's an error at all, now. :)

I just tested patch v6 and it works nicely for me. Again, thanks a bunch
for the attention to this issue.

-Corey

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-17 11:15                     ` Peter Zijlstra
  2009-02-18  0:09                       ` Corey Hickey
@ 2009-02-23 11:45                       ` Dhaval Giani
  2009-02-23 11:59                         ` Peter Zijlstra
  1 sibling, 1 reply; 26+ messages in thread
From: Dhaval Giani @ 2009-02-23 11:45 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages, Alan Cox

On Tue, Feb 17, 2009 at 12:15:39PM +0100, Peter Zijlstra wrote:
> On Tue, 2009-02-17 at 15:45 +0530, Dhaval Giani wrote:
> 
> > sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> > 
> > Corey Hickey reported that on using setuid to change the uid of a
> > rt process, the process would be unkillable and not be running.
> > This is because there was no rt runtime for that user group. Add
> > in a check to see if a user can attach an rt task to its task group.
> 
> This looks good to me.
> 
> Does anybody object to the -ENOSPC return value? Should we introduce
> -ENOTIME for that?
> 
> Michael, Alan?
> 

Hi,

Any comments on which return value to return? Should we introduce
-ENOTIME?

Corey mentioned he found ENOSPC confusing.

Thanks,
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-23 11:45                       ` Dhaval Giani
@ 2009-02-23 11:59                         ` Peter Zijlstra
  2009-02-24  9:18                           ` Dhaval Giani
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-23 11:59 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages, Alan Cox

On Mon, 2009-02-23 at 17:15 +0530, Dhaval Giani wrote:
> On Tue, Feb 17, 2009 at 12:15:39PM +0100, Peter Zijlstra wrote:
> > On Tue, 2009-02-17 at 15:45 +0530, Dhaval Giani wrote:
> > 
> > > sched: Don't allow setuid to succeed if the user does not have rt bandwidth
> > > 
> > > Corey Hickey reported that on using setuid to change the uid of a
> > > rt process, the process would be unkillable and not be running.
> > > This is because there was no rt runtime for that user group. Add
> > > in a check to see if a user can attach an rt task to its task group.
> > 
> > This looks good to me.
> > 
> > Does anybody object to the -ENOSPC return value? Should we introduce
> > -ENOTIME for that?
> > 
> > Michael, Alan?
> > 
> 
> Hi,
> 
> Any comments on which return value to return? Should we introduce
> -ENOTIME?
> 
> Corey mentioned he found ENOSPC confusing.

I'd say go for the ENOTIME thing.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-23 11:59                         ` Peter Zijlstra
@ 2009-02-24  9:18                           ` Dhaval Giani
  2009-02-24 15:58                             ` Andi Kleen
  0 siblings, 1 reply; 26+ messages in thread
From: Dhaval Giani @ 2009-02-24  9:18 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Corey Hickey, linux-kernel, Bharata B Rao, Balbir Singh,
	Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages, Alan Cox

> 
> I'd say go for the ENOTIME thing.

OK, how does the following do?
--
sched: Don't allow setuid to succeed if the user does not have rt bandwidth

Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.

Returns a new error ENOTIME

Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>

---
 include/asm-generic/errno.h |    2 ++
 include/linux/sched.h       |    4 ++++
 kernel/sched.c              |   13 +++++++++++--
 kernel/sys.c                |   31 ++++++++++++++++++++-----------
 kernel/user.c               |   18 ++++++++++++++++++
 5 files changed, 55 insertions(+), 13 deletions(-)

Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -2320,9 +2320,13 @@
 extern int sched_group_set_rt_period(struct task_group *tg,
 				      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+extern int task_can_switch_user(struct user_struct *up,
+					struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -9466,6 +9466,16 @@
 
 	return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+	/* Don't accept realtime tasks when there is no way for them to run */
+	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+		return 0;
+
+	return 1;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9559,8 +9569,7 @@
 		      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-	/* Don't accept realtime tasks when there is no way for them to run */
-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
 		return -EINVAL;
 #else
 	/* We don't support RT-tasks being in separate groups */
Index: linux-2.6/kernel/user.c
===================================================================
--- linux-2.6.orig/kernel/user.c
+++ linux-2.6/kernel/user.c
@@ -362,6 +362,24 @@
 
 #endif
 
+#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+
+	return sched_rt_can_attach(up->tg, tsk);
+
+}
+#else
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+	return 1;
+}
+#endif
+
 /*
  * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
  * caller must undo that ref with free_uid().
Index: linux-2.6/kernel/sys.c
===================================================================
--- linux-2.6.orig/kernel/sys.c
+++ linux-2.6/kernel/sys.c
@@ -560,7 +560,7 @@
 	abort_creds(new);
 	return retval;
 }
-  
+
 /*
  * change the user struct in a credentials set to match the new UID
  */
@@ -572,6 +572,11 @@
 	if (!new_user)
 		return -EAGAIN;
 
+	if (!task_can_switch_user(new_user, current)) {
+		free_uid(new_user);
+		return -ENOTIME;
+	}
+
 	if (atomic_read(&new_user->processes) >=
 				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
 			new_user != INIT_USER) {
@@ -632,10 +637,11 @@
 			goto error;
 	}
 
-	retval = -EAGAIN;
-	if (new->uid != old->uid && set_user(new) < 0)
-		goto error;
-
+	if (new->uid != old->uid) {
+		retval = set_user(new);
+		if (retval < 0)
+			goto error;
+	}
 	if (ruid != (uid_t) -1 ||
 	    (euid != (uid_t) -1 && euid != old->uid))
 		new->suid = new->euid;
@@ -681,9 +687,10 @@
 	retval = -EPERM;
 	if (capable(CAP_SETUID)) {
 		new->suid = new->uid = uid;
-		if (uid != old->uid && set_user(new) < 0) {
-			retval = -EAGAIN;
-			goto error;
+		if (uid != old->uid) {
+			retval = set_user(new);
+			if (retval < 0)
+				goto error;
 		}
 	} else if (uid != old->uid && uid != new->suid) {
 		goto error;
@@ -735,11 +742,13 @@
 			goto error;
 	}
 
-	retval = -EAGAIN;
 	if (ruid != (uid_t) -1) {
 		new->uid = ruid;
-		if (ruid != old->uid && set_user(new) < 0)
-			goto error;
+		if (ruid != old->uid) {
+			retval = set_user(new);
+			if (retval < 0)
+				goto error;
+		}
 	}
 	if (euid != (uid_t) -1)
 		new->euid = euid;
Index: linux-2.6/include/asm-generic/errno.h
===================================================================
--- linux-2.6.orig/include/asm-generic/errno.h
+++ linux-2.6/include/asm-generic/errno.h
@@ -106,4 +106,6 @@
 #define	EOWNERDEAD	130	/* Owner died */
 #define	ENOTRECOVERABLE	131	/* State not recoverable */
 
+#define ENOTIME		132	/* No time available to run process */
+
 #endif

-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-24  9:18                           ` Dhaval Giani
@ 2009-02-24 15:58                             ` Andi Kleen
  2009-02-24 16:36                               ` Peter Zijlstra
  0 siblings, 1 reply; 26+ messages in thread
From: Andi Kleen @ 2009-02-24 15:58 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Peter Zijlstra, Corey Hickey, linux-kernel, Bharata B Rao,
	Balbir Singh, Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages,
	Alan Cox

Dhaval Giani <dhaval@linux.vnet.ibm.com> writes:
>  		new->euid = euid;
> Index: linux-2.6/include/asm-generic/errno.h
> ===================================================================
> --- linux-2.6.orig/include/asm-generic/errno.h
> +++ linux-2.6/include/asm-generic/errno.h
> @@ -106,4 +106,6 @@
>  #define	EOWNERDEAD	130	/* Owner died */
>  #define	ENOTRECOVERABLE	131	/* State not recoverable */
>  
> +#define ENOTIME		132	/* No time available to run process */

It's normally not a good idea to add new errnos, because old glibc's
strerror()s won't know about it.

There are also so many around that you surely will find an existing
one which sounds appropiate.
-Andi

-- 
ak@linux.intel.com -- Speaking for myself only.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-24 15:58                             ` Andi Kleen
@ 2009-02-24 16:36                               ` Peter Zijlstra
  2009-02-24 19:29                                 ` Chris Friesen
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2009-02-24 16:36 UTC (permalink / raw)
  To: Andi Kleen
  Cc: Dhaval Giani, Corey Hickey, linux-kernel, Bharata B Rao,
	Balbir Singh, Srivatsa Vaddagiri, Ingo Molnar, mtk.manpages,
	Alan Cox

On Tue, 2009-02-24 at 16:58 +0100, Andi Kleen wrote:
> Dhaval Giani <dhaval@linux.vnet.ibm.com> writes:
> >  		new->euid = euid;
> > Index: linux-2.6/include/asm-generic/errno.h
> > ===================================================================
> > --- linux-2.6.orig/include/asm-generic/errno.h
> > +++ linux-2.6/include/asm-generic/errno.h
> > @@ -106,4 +106,6 @@
> >  #define	EOWNERDEAD	130	/* Owner died */
> >  #define	ENOTRECOVERABLE	131	/* State not recoverable */
> >  
> > +#define ENOTIME		132	/* No time available to run process */
> 
> It's normally not a good idea to add new errnos, because old glibc's
> strerror()s won't know about it.
> 
> There are also so many around that you surely will find an existing
> one which sounds appropiate.

Feel free to suggest one, I've read over all these error thingies
several times and non really stood out.

We tried ENOSPC, but people thought that weird too.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: RT scheduling and a way to make a process hang, unkillable
  2009-02-24 16:36                               ` Peter Zijlstra
@ 2009-02-24 19:29                                 ` Chris Friesen
  2009-02-27  9:43                                   ` [PATCH] sched: Don't allow setuid to succeed if the user does not have rt bandwidth Dhaval Giani
  0 siblings, 1 reply; 26+ messages in thread
From: Chris Friesen @ 2009-02-24 19:29 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Andi Kleen, Dhaval Giani, Corey Hickey, linux-kernel,
	Bharata B Rao, Balbir Singh, Srivatsa Vaddagiri, Ingo Molnar,
	mtk.manpages, Alan Cox

Peter Zijlstra wrote:
> On Tue, 2009-02-24 at 16:58 +0100, Andi Kleen wrote:
>> Dhaval Giani <dhaval@linux.vnet.ibm.com> writes:
>>>  		new->euid = euid;
>>> Index: linux-2.6/include/asm-generic/errno.h
>>> ===================================================================
>>> --- linux-2.6.orig/include/asm-generic/errno.h
>>> +++ linux-2.6/include/asm-generic/errno.h
>>> @@ -106,4 +106,6 @@
>>>  #define	EOWNERDEAD	130	/* Owner died */
>>>  #define	ENOTRECOVERABLE	131	/* State not recoverable */
>>>  
>>> +#define ENOTIME		132	/* No time available to run process */
>> It's normally not a good idea to add new errnos, because old glibc's
>> strerror()s won't know about it.
>>
>> There are also so many around that you surely will find an existing
>> one which sounds appropiate.
> 
> Feel free to suggest one, I've read over all these error thingies
> several times and non really stood out.
> 
> We tried ENOSPC, but people thought that weird too.

What about EDQUOT, as in "the user you're trying to become has no quota".

Chris

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH] sched: Don't allow setuid to succeed if the user does not have rt bandwidth
  2009-02-24 19:29                                 ` Chris Friesen
@ 2009-02-27  9:43                                   ` Dhaval Giani
  2009-02-27 10:25                                     ` Ingo Molnar
  0 siblings, 1 reply; 26+ messages in thread
From: Dhaval Giani @ 2009-02-27  9:43 UTC (permalink / raw)
  To: Chris Friesen, mingo
  Cc: Peter Zijlstra, Andi Kleen, Corey Hickey, linux-kernel,
	Bharata B Rao, Balbir Singh, Srivatsa Vaddagiri, mtk.manpages,
	Alan Cox


Corey Hickey reported that on using setuid to change the uid of a
rt process, the process would be unkillable and not be running.
This is because there was no rt runtime for that user group. Add
in a check to see if a user can attach an rt task to its task group.
On failure, return EINVAL, which is also returned in
CONFIG_CGROUP_SCHED.

Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
---
 include/linux/sched.h |    4 ++++
 kernel/sched.c        |   13 +++++++++++--
 kernel/sys.c          |   31 ++++++++++++++++++++-----------
 kernel/user.c         |   18 ++++++++++++++++++
 4 files changed, 53 insertions(+), 13 deletions(-)

Index: linux-2.6/include/linux/sched.h
===================================================================
--- linux-2.6.orig/include/linux/sched.h
+++ linux-2.6/include/linux/sched.h
@@ -2330,9 +2330,13 @@
 extern int sched_group_set_rt_period(struct task_group *tg,
 				      long rt_period_us);
 extern long sched_group_rt_period(struct task_group *tg);
+extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk);
 #endif
 #endif
 
+extern int task_can_switch_user(struct user_struct *up,
+					struct task_struct *tsk);
+
 #ifdef CONFIG_TASK_XACCT
 static inline void add_rchar(struct task_struct *tsk, ssize_t amt)
 {
Index: linux-2.6/kernel/sched.c
===================================================================
--- linux-2.6.orig/kernel/sched.c
+++ linux-2.6/kernel/sched.c
@@ -9466,6 +9466,16 @@
 
 	return ret;
 }
+
+int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk)
+{
+	/* Don't accept realtime tasks when there is no way for them to run */
+	if (rt_task(tsk) && tg->rt_bandwidth.rt_runtime == 0)
+		return 0;
+
+	return 1;
+}
+
 #else /* !CONFIG_RT_GROUP_SCHED */
 static int sched_rt_global_constraints(void)
 {
@@ -9559,8 +9569,7 @@
 		      struct task_struct *tsk)
 {
 #ifdef CONFIG_RT_GROUP_SCHED
-	/* Don't accept realtime tasks when there is no way for them to run */
-	if (rt_task(tsk) && cgroup_tg(cgrp)->rt_bandwidth.rt_runtime == 0)
+	if (!sched_rt_can_attach(cgroup_tg(cgrp), tsk))
 		return -EINVAL;
 #else
 	/* We don't support RT-tasks being in separate groups */
Index: linux-2.6/kernel/user.c
===================================================================
--- linux-2.6.orig/kernel/user.c
+++ linux-2.6/kernel/user.c
@@ -362,6 +362,24 @@
 
 #endif
 
+#if defined(CONFIG_RT_GROUP_SCHED) && defined(CONFIG_USER_SCHED)
+/*
+ * We need to check if a setuid can take place. This function should be called
+ * before successfully completing the setuid.
+ */
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+
+	return sched_rt_can_attach(up->tg, tsk);
+
+}
+#else
+int task_can_switch_user(struct user_struct *up, struct task_struct *tsk)
+{
+	return 1;
+}
+#endif
+
 /*
  * Locate the user_struct for the passed UID.  If found, take a ref on it.  The
  * caller must undo that ref with free_uid().
Index: linux-2.6/kernel/sys.c
===================================================================
--- linux-2.6.orig/kernel/sys.c
+++ linux-2.6/kernel/sys.c
@@ -560,7 +560,7 @@
 	abort_creds(new);
 	return retval;
 }
-  
+
 /*
  * change the user struct in a credentials set to match the new UID
  */
@@ -572,6 +572,11 @@
 	if (!new_user)
 		return -EAGAIN;
 
+	if (!task_can_switch_user(new_user, current)) {
+		free_uid(new_user);
+		return -EINVAL;
+	}
+
 	if (atomic_read(&new_user->processes) >=
 				current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
 			new_user != INIT_USER) {
@@ -632,10 +637,11 @@
 			goto error;
 	}
 
-	retval = -EAGAIN;
-	if (new->uid != old->uid && set_user(new) < 0)
-		goto error;
-
+	if (new->uid != old->uid) {
+		retval = set_user(new);
+		if (retval < 0)
+			goto error;
+	}
 	if (ruid != (uid_t) -1 ||
 	    (euid != (uid_t) -1 && euid != old->uid))
 		new->suid = new->euid;
@@ -681,9 +687,10 @@
 	retval = -EPERM;
 	if (capable(CAP_SETUID)) {
 		new->suid = new->uid = uid;
-		if (uid != old->uid && set_user(new) < 0) {
-			retval = -EAGAIN;
-			goto error;
+		if (uid != old->uid) {
+			retval = set_user(new);
+			if (retval < 0)
+				goto error;
 		}
 	} else if (uid != old->uid && uid != new->suid) {
 		goto error;
@@ -735,11 +742,13 @@
 			goto error;
 	}
 
-	retval = -EAGAIN;
 	if (ruid != (uid_t) -1) {
 		new->uid = ruid;
-		if (ruid != old->uid && set_user(new) < 0)
-			goto error;
+		if (ruid != old->uid) {
+			retval = set_user(new);
+			if (retval < 0)
+				goto error;
+		}
 	}
 	if (euid != (uid_t) -1)
 		new->euid = euid;
-- 
regards,
Dhaval

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] sched: Don't allow setuid to succeed if the user does not have rt bandwidth
  2009-02-27  9:43                                   ` [PATCH] sched: Don't allow setuid to succeed if the user does not have rt bandwidth Dhaval Giani
@ 2009-02-27 10:25                                     ` Ingo Molnar
  0 siblings, 0 replies; 26+ messages in thread
From: Ingo Molnar @ 2009-02-27 10:25 UTC (permalink / raw)
  To: Dhaval Giani
  Cc: Chris Friesen, mingo, Peter Zijlstra, Andi Kleen, Corey Hickey,
	linux-kernel, Bharata B Rao, Balbir Singh, Srivatsa Vaddagiri,
	mtk.manpages, Alan Cox


* Dhaval Giani <dhaval@linux.vnet.ibm.com> wrote:

> 
> Corey Hickey reported that on using setuid to change the uid of a
> rt process, the process would be unkillable and not be running.
> This is because there was no rt runtime for that user group. Add
> in a check to see if a user can attach an rt task to its task group.
> On failure, return EINVAL, which is also returned in
> CONFIG_CGROUP_SCHED.
> 
> Signed-off-by: Dhaval Giani <dhaval@linux.vnet.ibm.com>
> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
> ---
>  include/linux/sched.h |    4 ++++
>  kernel/sched.c        |   13 +++++++++++--
>  kernel/sys.c          |   31 ++++++++++++++++++++-----------
>  kernel/user.c         |   18 ++++++++++++++++++
>  4 files changed, 53 insertions(+), 13 deletions(-)

Applied to tip:sched/urgent, thanks Dhaval!

	Ingo

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2009-02-27 10:25 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-02-15  0:51 RT scheduling and a way to make a process hang, unkillable Corey Hickey
2009-02-15 11:24 ` Peter Zijlstra
2009-02-16 10:36   ` Dhaval Giani
2009-02-16 11:08     ` Peter Zijlstra
2009-02-16 12:02       ` Dhaval Giani
2009-02-16 12:24         ` Peter Zijlstra
2009-02-16 13:14           ` Dhaval Giani
2009-02-16 13:19             ` Peter Zijlstra
2009-02-16 14:23               ` Peter Zijlstra
2009-02-16 13:20             ` Dhaval Giani
2009-02-16 19:18               ` Corey Hickey
2009-02-17  5:00                 ` Dhaval Giani
2009-02-17 10:15                   ` Dhaval Giani
2009-02-17 11:15                     ` Peter Zijlstra
2009-02-18  0:09                       ` Corey Hickey
2009-02-23 11:45                       ` Dhaval Giani
2009-02-23 11:59                         ` Peter Zijlstra
2009-02-24  9:18                           ` Dhaval Giani
2009-02-24 15:58                             ` Andi Kleen
2009-02-24 16:36                               ` Peter Zijlstra
2009-02-24 19:29                                 ` Chris Friesen
2009-02-27  9:43                                   ` [PATCH] sched: Don't allow setuid to succeed if the user does not have rt bandwidth Dhaval Giani
2009-02-27 10:25                                     ` Ingo Molnar
2009-02-16 20:16     ` RT scheduling and a way to make a process hang, unkillable Kyle Moffett
2009-02-16 20:28       ` Peter Zijlstra
2009-02-17  7:22       ` Dhaval Giani

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).