113 lines
3.5 KiB
Diff
113 lines
3.5 KiB
Diff
From 282b6f3a2d1c95ed2443ad974e354883b66cd7c9 Mon Sep 17 00:00:00 2001
|
|
From: Jiri Slaby <jirislaby@gmail.com>
|
|
Date: Wed, 26 Aug 2009 23:45:34 +0200
|
|
Subject: [PATCH] core: split sys_setrlimit
|
|
References: FATE#305733
|
|
Patch-mainline: no (later)
|
|
|
|
Create do_setrlimit from sys_setrlimit and declare do_setrlimit
|
|
in the resource header. This is to allow rlimits to be changed
|
|
not only by syscall, but later from proc and syscall code too.
|
|
|
|
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
---
|
|
include/linux/resource.h | 2 ++
|
|
kernel/sys.c | 40 ++++++++++++++++++++++++----------------
|
|
2 files changed, 26 insertions(+), 16 deletions(-)
|
|
|
|
--- a/include/linux/resource.h
|
|
+++ b/include/linux/resource.h
|
|
@@ -73,6 +73,8 @@ struct rlimit {
|
|
struct task_struct;
|
|
|
|
int getrusage(struct task_struct *p, int who, struct rusage __user *ru);
|
|
+int do_setrlimit(struct task_struct *tsk, unsigned int resource,
|
|
+ struct rlimit *new_rlim);
|
|
|
|
#endif /* __KERNEL__ */
|
|
|
|
--- a/kernel/sys.c
|
|
+++ b/kernel/sys.c
|
|
@@ -1302,42 +1302,41 @@ SYSCALL_DEFINE2(old_getrlimit, unsigned
|
|
|
|
#endif
|
|
|
|
-SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
|
|
+int do_setrlimit(struct task_struct *tsk, unsigned int resource,
|
|
+ struct rlimit *new_rlim)
|
|
{
|
|
- struct rlimit new_rlim, *old_rlim;
|
|
+ struct rlimit *old_rlim;
|
|
int retval;
|
|
|
|
if (resource >= RLIM_NLIMITS)
|
|
return -EINVAL;
|
|
- if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
|
|
- return -EFAULT;
|
|
- if (new_rlim.rlim_cur > new_rlim.rlim_max)
|
|
+ if (new_rlim->rlim_cur > new_rlim->rlim_max)
|
|
return -EINVAL;
|
|
- if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
|
|
+ if (resource == RLIMIT_NOFILE && new_rlim->rlim_max > sysctl_nr_open)
|
|
return -EPERM;
|
|
|
|
- retval = security_task_setrlimit(current, resource, &new_rlim);
|
|
+ retval = security_task_setrlimit(tsk, resource, new_rlim);
|
|
if (retval)
|
|
return retval;
|
|
|
|
- if (resource == RLIMIT_CPU && new_rlim.rlim_cur == 0) {
|
|
+ if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
|
|
/*
|
|
* The caller is asking for an immediate RLIMIT_CPU
|
|
* expiry. But we use the zero value to mean "it was
|
|
* never set". So let's cheat and make it one second
|
|
* instead
|
|
*/
|
|
- new_rlim.rlim_cur = 1;
|
|
+ new_rlim->rlim_cur = 1;
|
|
}
|
|
|
|
- old_rlim = current->signal->rlim + resource;
|
|
- task_lock(current->group_leader);
|
|
- if ((new_rlim.rlim_max <= old_rlim->rlim_max) ||
|
|
+ old_rlim = tsk->signal->rlim + resource;
|
|
+ task_lock(tsk->group_leader);
|
|
+ if ((new_rlim->rlim_max <= old_rlim->rlim_max) ||
|
|
capable(CAP_SYS_RESOURCE))
|
|
- *old_rlim = new_rlim;
|
|
+ *old_rlim = *new_rlim;
|
|
else
|
|
retval = -EPERM;
|
|
- task_unlock(current->group_leader);
|
|
+ task_unlock(tsk->group_leader);
|
|
|
|
if (retval || resource != RLIMIT_CPU)
|
|
goto out;
|
|
@@ -1348,14 +1347,23 @@ SYSCALL_DEFINE2(setrlimit, unsigned int,
|
|
* very long-standing error, and fixing it now risks breakage of
|
|
* applications, so we live with it
|
|
*/
|
|
- if (new_rlim.rlim_cur == RLIM_INFINITY)
|
|
+ if (new_rlim->rlim_cur == RLIM_INFINITY)
|
|
goto out;
|
|
|
|
- update_rlimit_cpu(current, new_rlim.rlim_cur);
|
|
+ update_rlimit_cpu(tsk, new_rlim->rlim_cur);
|
|
out:
|
|
return retval;
|
|
}
|
|
|
|
+SYSCALL_DEFINE2(setrlimit, unsigned int, resource, struct rlimit __user *, rlim)
|
|
+{
|
|
+ struct rlimit new_rlim;
|
|
+
|
|
+ if (copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
|
|
+ return -EFAULT;
|
|
+ return do_setrlimit(current, resource, &new_rlim);
|
|
+}
|
|
+
|
|
/*
|
|
* It would make sense to put struct rusage in the task_struct,
|
|
* except that would make the task_struct be *really big*. After
|