qubes-linux-kernel/patches.suse/rlim-0018-core-split-sys_setrlimit.patch
2010-07-07 13:12:45 +02:00

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