67 lines
2.0 KiB
Diff
67 lines
2.0 KiB
Diff
From 60aa0fa94c00942cc2c9f67f05d4a0d9e15349c7 Mon Sep 17 00:00:00 2001
|
|
From: Oleg Nesterov <oleg@redhat.com>
|
|
Date: Thu, 3 Sep 2009 19:21:45 +0200
|
|
Subject: [PATCH] sys_setrlimit: make sure ->rlim_max never grows
|
|
References: FATE#305733
|
|
Patch-mainline: no (later)
|
|
|
|
Mostly preparation for Jiri's changes, but probably makes sense anyway.
|
|
|
|
sys_setrlimit() checks new_rlim.rlim_max <= old_rlim->rlim_max, but when
|
|
it takes task_lock() old_rlim->rlim_max can be already lowered. Move this
|
|
check under task_lock().
|
|
|
|
Currently this is not important, we can only race with our sub-thread,
|
|
this means the application is stupid. But when we change the code to allow
|
|
the update of !current task's limits, it becomes important to make sure
|
|
->rlim_max can be lowered "reliably" even if we race with the application
|
|
doing sys_setrlimit().
|
|
|
|
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
|
|
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
---
|
|
kernel/sys.c | 15 ++++++++-------
|
|
1 file changed, 8 insertions(+), 7 deletions(-)
|
|
|
|
--- a/kernel/sys.c
|
|
+++ b/kernel/sys.c
|
|
@@ -1313,10 +1313,6 @@ SYSCALL_DEFINE2(setrlimit, unsigned int,
|
|
return -EFAULT;
|
|
if (new_rlim.rlim_cur > new_rlim.rlim_max)
|
|
return -EINVAL;
|
|
- old_rlim = current->signal->rlim + resource;
|
|
- if ((new_rlim.rlim_max > old_rlim->rlim_max) &&
|
|
- !capable(CAP_SYS_RESOURCE))
|
|
- return -EPERM;
|
|
if (resource == RLIMIT_NOFILE && new_rlim.rlim_max > sysctl_nr_open)
|
|
return -EPERM;
|
|
|
|
@@ -1334,11 +1330,16 @@ SYSCALL_DEFINE2(setrlimit, unsigned int,
|
|
new_rlim.rlim_cur = 1;
|
|
}
|
|
|
|
+ old_rlim = current->signal->rlim + resource;
|
|
task_lock(current->group_leader);
|
|
- *old_rlim = new_rlim;
|
|
+ if ((new_rlim.rlim_max <= old_rlim->rlim_max) ||
|
|
+ capable(CAP_SYS_RESOURCE))
|
|
+ *old_rlim = new_rlim;
|
|
+ else
|
|
+ retval = -EPERM;
|
|
task_unlock(current->group_leader);
|
|
|
|
- if (resource != RLIMIT_CPU)
|
|
+ if (retval || resource != RLIMIT_CPU)
|
|
goto out;
|
|
|
|
/*
|
|
@@ -1352,7 +1353,7 @@ SYSCALL_DEFINE2(setrlimit, unsigned int,
|
|
|
|
update_rlimit_cpu(current, new_rlim.rlim_cur);
|
|
out:
|
|
- return 0;
|
|
+ return retval;
|
|
}
|
|
|
|
/*
|