All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process
@ 2005-08-12 17:48 Wieland Gmeiner
  2005-08-12 17:53 ` [PATCH 2.6.13-rc6 2/2] New Syscall: set " Wieland Gmeiner
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Wieland Gmeiner @ 2005-08-12 17:48 UTC (permalink / raw)
  To: linux-kernel; +Cc: Elliot Lee, Wieland Gmeiner

Hi all!

I'm a participant in Googles Summer of Code Program, doing an entry
level kernel project suggested by Fedora Core, "Getting and Setting
Process Resource Limits out of Process Space".

Rationale: Currently resource usage limits (rlimits) can only be set 
inside a process space, or inherited from the parent process. It 
would be useful to allow adjusting resource limits for running 
processes, e.g. tuning the resource usage of daemon processes under 
changing workloads without restarting them.

Implementation: This patch provides a new syscall getprlimit() for
reading a given process resource limits for i386. Its implementation
follows closely the getrlimit syscall. It is given a pid as an
additional argument. If the given pid equals zero the current process
rlimits are read and the behaviour resembles the behaviour of
getrlimit. Otherwise some checking on the validity of the given pid is
done and if the given process is found access is granted if

- the calling process holds the CAP_SYS_RESOURCE capability or
- the calling process uid equals the uid of the process whose rlimit
  is being read or
- the calling process uid equals the suid of the process whose rlimit
  is being read or
- the calling process euid equals the uid of the process whose rlimit
  is being read or
- the calling process euid equals the suid of the process whose 
  rlimit is being read

See the followup for the writing syscall. Additionally a
/proc/pid/rlimits interface for comfortable access is under
construction.

Simple programs for testing the syscalls can be found on
http://stud4.tuwien.ac.at/~e8607062/studies/soc/patches/


Signed-off-by: Wieland Gmeiner <e8607062@student.tuwien.ac.at>


diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-vanilla/arch/i386/kernel/syscall_table.S linux-2.6.13-rc6-rlim/arch/i386/kernel/syscall_table.S
--- linux-2.6.13-rc6-vanilla/arch/i386/kernel/syscall_table.S	2005-08-09 16:03:08.000000000 +0200
+++ linux-2.6.13-rc6-rlim/arch/i386/kernel/syscall_table.S	2005-08-09 15:06:54.000000000 +0200
@@ -294,3 +294,4 @@ ENTRY(sys_call_table)
 	.long sys_inotify_init
 	.long sys_inotify_add_watch
 	.long sys_inotify_rm_watch
+        .long sys_getprlimit
diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-vanilla/include/asm-i386/unistd.h linux-2.6.13-rc6-rlim/include/asm-i386/unistd.h
--- linux-2.6.13-rc6-vanilla/include/asm-i386/unistd.h	2005-08-09 16:03:19.000000000 +0200
+++ linux-2.6.13-rc6-rlim/include/asm-i386/unistd.h	2005-08-09 15:07:46.000000000 +0200
@@ -299,8 +299,9 @@
 #define __NR_inotify_init	291
 #define __NR_inotify_add_watch	292
 #define __NR_inotify_rm_watch	293
+#define __NR_getprlimit         294
 
-#define NR_syscalls 294
+#define NR_syscalls 295
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-vanilla/kernel/sys.c linux-2.6.13-rc6-rlim/kernel/sys.c
--- linux-2.6.13-rc6-vanilla/kernel/sys.c	2005-08-09 16:03:21.000000000 +0200
+++ linux-2.6.13-rc6-rlim/kernel/sys.c	2005-08-09 15:10:32.000000000 +0200
@@ -1603,6 +1603,47 @@ asmlinkage long sys_setrlimit(unsigned i
 	return 0;
 }
 
+asmlinkage long sys_getprlimit(pid_t pid, unsigned int resource, struct rlimit __user *rlim)
+{
+        struct rlimit value;
+        task_t *p;
+        int retval = -EINVAL;
+
+        if (resource >= RLIM_NLIMITS)
+                goto out_nounlock;
+
+        if (pid < 0)
+                goto out_nounlock;
+
+        retval = -ESRCH;
+        if (pid == 0) {
+                p = current;
+        } else {
+                read_lock(&tasklist_lock);
+                p = find_task_by_pid(pid);
+        }
+        if (p) {
+                retval = -EPERM;
+                if ((current->euid ^ p->suid) && (current->euid ^ p->uid) &&
+                    (current->uid ^ p->suid) && (current->uid ^ p->uid) &&
+                    !capable(CAP_SYS_RESOURCE))
+                        goto out_unlock;
+
+                task_lock(p->group_leader);
+                value = p->signal->rlim[resource];
+                task_unlock(p->group_leader);
+                retval = copy_to_user(rlim, &value, sizeof(*rlim)) ? -EFAULT : 0;
+        }
+        if (pid == 0)
+                goto out_nounlock;
+
+out_unlock:
+        read_unlock(&tasklist_lock);
+
+out_nounlock:
+        return retval;
+}
+
 /*
  * It would make sense to put struct rusage in the task_struct,
  * except that would make the task_struct be *really big*.  After


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

* [PATCH 2.6.13-rc6 2/2] New Syscall: set rlimits of any process
  2005-08-12 17:48 [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process Wieland Gmeiner
@ 2005-08-12 17:53 ` Wieland Gmeiner
  2005-08-13 22:11 ` [PATCH 2.6.13-rc6 1/2] New Syscall: get " Greg KH
  2005-08-21  1:11 ` Andrew Morton
  2 siblings, 0 replies; 7+ messages in thread
From: Wieland Gmeiner @ 2005-08-12 17:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: Elliot Lee, Wieland Gmeiner


Implementation: This patch provides a new syscall setprlimit() for
writing a given process resource limits for i386. Its implementation
follows closely the setrlimit syscall. It is given a pid as an
additional argument. If the given pid equals zero the current process
rlimits are written and the behaviour resembles the behaviour of
setrlimit. Otherwise some checking on the validity of the given pid is
done and if the given process is found write access is granted if

- the calling process holds the CAP_SYS_RESOURCE capability
  or
- the calling process uid equals the uid of the process whose rlimit
  is being written and
  the calling process uid equals the euid of the process whose rlimit
  is being written
  or
- the calling process euid equals the suid of the process whose 
  rlimit is being written

Signed-off-by: Wieland Gmeiner <e8607062@student.tuwien.ac.at>



diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-rlim/arch/i386/kernel/syscall_table.S linux-2.6.13-rc6-get_set_rlim/arch/i386/kernel/syscall_table.S
--- linux-2.6.13-rc6-rlim/arch/i386/kernel/syscall_table.S	2005-08-09 16:30:51.000000000 +0200
+++ linux-2.6.13-rc6-get_set_rlim/arch/i386/kernel/syscall_table.S	2005-08-09 16:34:54.000000000 +0200
@@ -295,3 +295,4 @@ ENTRY(sys_call_table)
 	.long sys_inotify_add_watch
 	.long sys_inotify_rm_watch
         .long sys_getprlimit
+        .long sys_setprlimit            /* 295 */
diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-rlim/include/asm-i386/unistd.h linux-2.6.13-rc6-get_set_rlim/include/asm-i386/unistd.h
--- linux-2.6.13-rc6-rlim/include/asm-i386/unistd.h	2005-08-09 16:30:51.000000000 +0200
+++ linux-2.6.13-rc6-get_set_rlim/include/asm-i386/unistd.h	2005-08-09 16:34:54.000000000 +0200
@@ -300,8 +300,9 @@
 #define __NR_inotify_add_watch	292
 #define __NR_inotify_rm_watch	293
 #define __NR_getprlimit         294
+#define __NR_setprlimit         295
 
-#define NR_syscalls 295
+#define NR_syscalls 296
 
 /*
  * user-visible error numbers are in the range -1 - -128: see
diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-rlim/include/linux/security.h linux-2.6.13-rc6-get_set_rlim/include/linux/security.h
--- linux-2.6.13-rc6-rlim/include/linux/security.h	2005-06-17 21:48:29.000000000 +0200
+++ linux-2.6.13-rc6-get_set_rlim/include/linux/security.h	2005-08-09 16:34:55.000000000 +0200
@@ -591,7 +591,16 @@ struct swap_info_struct;
  *	@resource contains the resource whose limit is being set.
  *	@new_rlim contains the new limits for @resource.
  *	Return 0 if permission is granted.
- * @task_setscheduler:
+ * @task_setprlimit:
+ *	Check permission before setting the resource limits of process @p
+ *	for @resource to @new_rlim.  The old resource limit values can
+ *	be examined by dereferencing (p->signal->rlim + resource).
+ *	@p contains the task struct of the process whose resource limit is
+ *	being set.
+ *	@resource contains the resource whose limit is being set.
+ *	@new_rlim contains the new limits for @resource.
+ *	Return 0 if permission is granted.
+  @task_setscheduler:
  *	Check permission before setting scheduling policy and/or parameters of
  *	process @p based on @policy and @lp.
  *	@p contains the task_struct for process.
@@ -1157,6 +1166,8 @@ struct security_operations {
 	int (*task_setgroups) (struct group_info *group_info);
 	int (*task_setnice) (struct task_struct * p, int nice);
 	int (*task_setrlimit) (unsigned int resource, struct rlimit * new_rlim);
+	int (*task_setprlimit) (struct task_struct * p, unsigned int resource, 
+                                struct rlimit * new_rlim);
 	int (*task_setscheduler) (struct task_struct * p, int policy,
 				  struct sched_param * lp);
 	int (*task_getscheduler) (struct task_struct * p);
@@ -1804,6 +1815,13 @@ static inline int security_task_setrlimi
 	return security_ops->task_setrlimit (resource, new_rlim);
 }
 
+static inline int security_task_setprlimit (struct task_struct *p,
+                                            unsigned int resource,
+					    struct rlimit *new_rlim)
+{
+	return security_ops->task_setprlimit (p, resource, new_rlim);
+}
+
 static inline int security_task_setscheduler (struct task_struct *p,
 					      int policy,
 					      struct sched_param *lp)
diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-rlim/kernel/sys.c linux-2.6.13-rc6-get_set_rlim/kernel/sys.c
--- linux-2.6.13-rc6-rlim/kernel/sys.c	2005-08-09 16:30:51.000000000 +0200
+++ linux-2.6.13-rc6-get_set_rlim/kernel/sys.c	2005-08-09 16:34:56.000000000 +0200
@@ -1644,6 +1644,72 @@ out_nounlock:
         return retval;
 }
 
+asmlinkage long sys_setprlimit(pid_t pid, unsigned int resource, struct rlimit __user *rlim)
+{
+	struct rlimit new_rlim, *old_rlim;
+	int retval;
+        task_t *p;
+
+	if (resource >= RLIM_NLIMITS)
+		return -EINVAL;
+        if (pid < 0)
+                return -EINVAL;
+	if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
+		return -EFAULT;
+        if (new_rlim.rlim_cur > new_rlim.rlim_max)
+                return -EINVAL;
+        
+        retval = -ESRCH;
+        if (pid == 0) {
+                p = current;
+        } else {
+                read_lock(&tasklist_lock);
+                p = find_task_by_pid(pid);
+        }
+        if (p) {
+                retval = -EPERM;
+                if ((current->euid ^ p->suid) &&
+                    ((current->uid ^ p->euid) || (current->uid ^ p->uid)) &&
+                    !capable(CAP_SYS_RESOURCE))
+                        goto out_unlock;
+ 
+                old_rlim = p->signal->rlim + resource;
+                if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
+                                !capable(CAP_SYS_RESOURCE))
+                        goto out_unlock;
+                if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > NR_OPEN)
+                        goto out_unlock;
+
+                retval = security_task_setprlimit(p, resource, &new_rlim);
+                if (retval)
+                        goto out_unlock;
+
+                task_lock(p->group_leader);
+	        *old_rlim = new_rlim;
+                task_unlock(p->group_leader);
+                retval = 0;
+
+        	if (resource == RLIMIT_CPU && new_rlim.rlim_cur != RLIM_INFINITY &&
+	            (cputime_eq(p->signal->it_prof_expires, cputime_zero) ||
+	             new_rlim.rlim_cur <= cputime_to_secs(
+		                p->signal->it_prof_expires))) {
+		        cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur);
+		        spin_lock_irq(&p->sighand->siglock);
+		        set_process_cpu_timer(p, CPUCLOCK_PROF,
+			        	      &cputime, NULL);
+		        spin_unlock_irq(&p->sighand->siglock);
+	        }
+        }
+        if (pid == 0)
+                goto out_nounlock;
+
+out_unlock:
+        read_unlock(&tasklist_lock);
+
+out_nounlock:
+        return retval;
+}
+
 /*
  * It would make sense to put struct rusage in the task_struct,
  * except that would make the task_struct be *really big*.  After
diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-rlim/security/dummy.c linux-2.6.13-rc6-get_set_rlim/security/dummy.c
--- linux-2.6.13-rc6-rlim/security/dummy.c	2005-08-09 16:30:38.000000000 +0200
+++ linux-2.6.13-rc6-get_set_rlim/security/dummy.c	2005-08-09 16:34:56.000000000 +0200
@@ -548,6 +548,12 @@ static int dummy_task_setrlimit (unsigne
 	return 0;
 }
 
+static int dummy_task_setprlimit (struct task_struct *p, unsigned int resource,
+                                  struct rlimit *new_rlim)
+{
+	return 0;
+}
+
 static int dummy_task_setscheduler (struct task_struct *p, int policy,
 				    struct sched_param *lp)
 {
@@ -937,6 +943,7 @@ void security_fixup_ops (struct security
 	set_to_dummy_if_null(ops, task_setgroups);
 	set_to_dummy_if_null(ops, task_setnice);
 	set_to_dummy_if_null(ops, task_setrlimit);
+	set_to_dummy_if_null(ops, task_setprlimit);
 	set_to_dummy_if_null(ops, task_setscheduler);
 	set_to_dummy_if_null(ops, task_getscheduler);
 	set_to_dummy_if_null(ops, task_wait);
diff -uprN -X linux-2.6.13-rc6-vanilla/Documentation/dontdiff linux-2.6.13-rc6-rlim/security/selinux/hooks.c linux-2.6.13-rc6-get_set_rlim/security/selinux/hooks.c
--- linux-2.6.13-rc6-rlim/security/selinux/hooks.c	2005-08-09 16:30:38.000000000 +0200
+++ linux-2.6.13-rc6-get_set_rlim/security/selinux/hooks.c	2005-08-09 16:34:57.000000000 +0200
@@ -2722,6 +2722,26 @@ static int selinux_task_setrlimit(unsign
 	return 0;
 }
 
+static int selinux_task_setprlimit(struct task_struct *p, unsigned int resource,
+                                  struct rlimit *new_rlim)
+{
+	struct rlimit *old_rlim = p->signal->rlim + resource;
+	int rc;
+
+	rc = secondary_ops->task_setprlimit(p, resource, new_rlim);
+	if (rc)
+		return rc;
+
+	/* Control the ability to change the hard limit (whether
+	   lowering or raising it), so that the hard limit can
+	   later be used as a safe reset point for the soft limit
+	   upon context transitions. See selinux_bprm_apply_creds. */
+	if (old_rlim->rlim_max != new_rlim->rlim_max)
+		return task_has_perm(current, p, PROCESS__SETRLIMIT);
+
+	return 0;
+}
+
 static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
 {
 	return task_has_perm(current, p, PROCESS__SETSCHED);


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

* Re: [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process
  2005-08-12 17:48 [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process Wieland Gmeiner
  2005-08-12 17:53 ` [PATCH 2.6.13-rc6 2/2] New Syscall: set " Wieland Gmeiner
@ 2005-08-13 22:11 ` Greg KH
  2005-08-16 17:34   ` Wieland Gmeiner
  2005-08-21  1:11 ` Andrew Morton
  2 siblings, 1 reply; 7+ messages in thread
From: Greg KH @ 2005-08-13 22:11 UTC (permalink / raw)
  To: Wieland Gmeiner; +Cc: linux-kernel, Elliot Lee

On Fri, Aug 12, 2005 at 07:48:22PM +0200, Wieland Gmeiner wrote:
> @@ -294,3 +294,4 @@ ENTRY(sys_call_table)
>  	.long sys_inotify_init
>  	.long sys_inotify_add_watch
>  	.long sys_inotify_rm_watch
> +        .long sys_getprlimit

Please follow the proper kernel coding style when writing new kernel
code...

thanks,

greg k-h

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

* Re: [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process
  2005-08-13 22:11 ` [PATCH 2.6.13-rc6 1/2] New Syscall: get " Greg KH
@ 2005-08-16 17:34   ` Wieland Gmeiner
  2005-08-16 17:50     ` Greg KH
  2005-08-16 17:55     ` Kyle Moffett
  0 siblings, 2 replies; 7+ messages in thread
From: Wieland Gmeiner @ 2005-08-16 17:34 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, Elliot Lee

On Sat, 2005-08-13 at 15:11 -0700, Greg KH wrote:
> On Fri, Aug 12, 2005 at 07:48:22PM +0200, Wieland Gmeiner wrote:
> > @@ -294,3 +294,4 @@ ENTRY(sys_call_table)
> >  	.long sys_inotify_init
> >  	.long sys_inotify_add_watch
> >  	.long sys_inotify_rm_watch
> > +        .long sys_getprlimit
> 
> Please follow the proper kernel coding style when writing new kernel
> code...

Hm, Documentation/CodingStyle suggests using descriptive names, so
something like getrlimit(...)/getrlimit_per_process(pid_t pid, ...)
would be more appropriate?

I thought getrlimit(...)/getprlimit(pid_t pid, ...) would be a good
choice as getgid(void)/getpgid(pid_t pid) already exists in Linux which
have the same naming scheme.

Or would something like
getrlimit/getrlimitpid (like wait(void)/waitpid(pid)) or
getrlimit/getrlimit2 (like getpgrp(void)/getpgrp2(pid) in HP-UX)
be preferred?

What would you suggest?

Thanks,
Wieland


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

* Re: [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process
  2005-08-16 17:34   ` Wieland Gmeiner
@ 2005-08-16 17:50     ` Greg KH
  2005-08-16 17:55     ` Kyle Moffett
  1 sibling, 0 replies; 7+ messages in thread
From: Greg KH @ 2005-08-16 17:50 UTC (permalink / raw)
  To: Wieland Gmeiner; +Cc: linux-kernel, Elliot Lee

On Tue, Aug 16, 2005 at 07:34:34PM +0200, Wieland Gmeiner wrote:
> On Sat, 2005-08-13 at 15:11 -0700, Greg KH wrote:
> > On Fri, Aug 12, 2005 at 07:48:22PM +0200, Wieland Gmeiner wrote:
> > > @@ -294,3 +294,4 @@ ENTRY(sys_call_table)
> > >  	.long sys_inotify_init
> > >  	.long sys_inotify_add_watch
> > >  	.long sys_inotify_rm_watch
> > > +        .long sys_getprlimit
> > 
> > Please follow the proper kernel coding style when writing new kernel
> > code...
> 
> Hm, Documentation/CodingStyle suggests using descriptive names, so
> something like getrlimit(...)/getrlimit_per_process(pid_t pid, ...)
> would be more appropriate?
> 
> I thought getrlimit(...)/getprlimit(pid_t pid, ...) would be a good
> choice as getgid(void)/getpgid(pid_t pid) already exists in Linux which
> have the same naming scheme.
> 
> Or would something like
> getrlimit/getrlimitpid (like wait(void)/waitpid(pid)) or
> getrlimit/getrlimit2 (like getpgrp(void)/getpgrp2(pid) in HP-UX)
> be preferred?
> 
> What would you suggest?

You use tabs instead of spaces :)

thanks,

greg k-h

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

* Re: [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process
  2005-08-16 17:34   ` Wieland Gmeiner
  2005-08-16 17:50     ` Greg KH
@ 2005-08-16 17:55     ` Kyle Moffett
  1 sibling, 0 replies; 7+ messages in thread
From: Kyle Moffett @ 2005-08-16 17:55 UTC (permalink / raw)
  To: e8607062; +Cc: Greg KH, linux-kernel, Elliot Lee

On Aug 16, 2005, at 13:34:34, Wieland Gmeiner wrote:
> On Sat, 2005-08-13 at 15:11 -0700, Greg KH wrote:
>> On Fri, Aug 12, 2005 at 07:48:22PM +0200, Wieland Gmeiner wrote:
>>
>>> @@ -294,3 +294,4 @@ ENTRY(sys_call_table)
>>>      .long sys_inotify_init
>>>      .long sys_inotify_add_watch
>>>      .long sys_inotify_rm_watch
>>> +        .long sys_getprlimit
>>>
>>
>> Please follow the proper kernel coding style when writing new kernel
>> code...
>
> Hm, Documentation/CodingStyle suggests using descriptive names, so
> something like getrlimit(...)/getrlimit_per_process(pid_t pid, ...)
> would be more appropriate?

I think he was commenting more on the code indentation and braces  
placement
than any naming issue.  There was also a good guide to kernel whitespace
posted to the LKML a week or so ago, please check the archives and  
review
that as well.

I have one small comment on something you stated in your original mail:
> Otherwise some checking on the validity of the given pid is
> done and if the given process is found access is granted if
>
> - the calling process holds the CAP_SYS_RESOURCE capability or
> - the calling process uid equals the uid of the process whose rlimit
>   is being read or
> - the calling process uid equals the suid of the process whose rlimit
>   is being read or
> - the calling process euid equals the uid of the process whose rlimit
>   is being read or
> - the calling process euid equals the suid of the process whose
>   rlimit is being read

I suggest that you revise this list to the following:
> If the calling process can ptrace the target process, then allow  
> rlimits to be
> read and written such that the hard limits may not be raised unless  
> one of the
> two processes possesses the CAP_SYS_RESOURCE capability

ptrace implies the ability to execute arbitrary code in the given  
process, which
means that even without this new function the calling process  
theoretically
could obtain and set rlimits for that process anyways, subject to its  
own
CAP_SYS_RESOURCE capability.  Such a situation would guarantee that  
there are
no new security holes, and would limit the number of inter-process  
access rules
which kernel developers need to understand.  I believe some simple  
Googling and
grepping through the kernel code should reveal the necessary ptrace- 
related
process checks.

Cheers,
Kyle Moffett

--
There are two ways of constructing a software design. One way is to  
make it so
simple that there are obviously no deficiencies. And the other way is  
to make
it so complicated that there are no obvious deficiencies.  The first  
method is
far more difficult.
   -- C.A.R. Hoare



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

* Re: [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process
  2005-08-12 17:48 [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process Wieland Gmeiner
  2005-08-12 17:53 ` [PATCH 2.6.13-rc6 2/2] New Syscall: set " Wieland Gmeiner
  2005-08-13 22:11 ` [PATCH 2.6.13-rc6 1/2] New Syscall: get " Greg KH
@ 2005-08-21  1:11 ` Andrew Morton
  2 siblings, 0 replies; 7+ messages in thread
From: Andrew Morton @ 2005-08-21  1:11 UTC (permalink / raw)
  To: e8607062; +Cc: linux-kernel, sopwith

Wieland Gmeiner <e8607062@student.tuwien.ac.at> wrote:
>
> +asmlinkage long sys_getprlimit(pid_t pid, unsigned int resource, struct rlimit __user *rlim)
>  +{
>  +        struct rlimit value;
>  +        task_t *p;
>  +        int retval = -EINVAL;
>  +
>  +        if (resource >= RLIM_NLIMITS)
>  +                goto out_nounlock;
>  +
>  +        if (pid < 0)
>  +                goto out_nounlock;
>  +
>  +        retval = -ESRCH;
>  +        if (pid == 0) {
>  +                p = current;
>  +        } else {
>  +                read_lock(&tasklist_lock);
>  +                p = find_task_by_pid(pid);
>  +        }
>  +        if (p) {
>  +                retval = -EPERM;
>  +                if ((current->euid ^ p->suid) && (current->euid ^ p->uid) &&
>  +                    (current->uid ^ p->suid) && (current->uid ^ p->uid) &&
>  +                    !capable(CAP_SYS_RESOURCE))
>  +                        goto out_unlock;
>  +
>  +                task_lock(p->group_leader);
>  +                value = p->signal->rlim[resource];
>  +                task_unlock(p->group_leader);

There isn't much point in taking task_lock() here.  The value can change
after the lock has been dropped anyway.

>  +                retval = copy_to_user(rlim, &value, sizeof(*rlim)) ? -EFAULT : 0;

It's not legal to perform copy_*_user() (which sleeps) inside read_lock(),
write_lock(), spin_lock(), preempt_diable() or, really,
local_irq_disable().

>  +        }
>  +        if (pid == 0)
>  +                goto out_nounlock;
>  +
>  +out_unlock:
>  +        read_unlock(&tasklist_lock);

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

end of thread, other threads:[~2005-08-21  1:12 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-08-12 17:48 [PATCH 2.6.13-rc6 1/2] New Syscall: get rlimits of any process Wieland Gmeiner
2005-08-12 17:53 ` [PATCH 2.6.13-rc6 2/2] New Syscall: set " Wieland Gmeiner
2005-08-13 22:11 ` [PATCH 2.6.13-rc6 1/2] New Syscall: get " Greg KH
2005-08-16 17:34   ` Wieland Gmeiner
2005-08-16 17:50     ` Greg KH
2005-08-16 17:55     ` Kyle Moffett
2005-08-21  1:11 ` Andrew Morton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.