diff options
author | Jiri Slaby <jslaby@suse.cz> | 2009-11-14 17:37:04 +0100 |
---|---|---|
committer | Jiri Slaby <jirislaby@gmail.com> | 2010-07-16 09:48:47 +0200 |
commit | 86f162f4c75ceb6daf43165469eeeca1bc3d4639 (patch) | |
tree | bca0e9d28d636fbaefb1846bdb85d9b57708df11 /kernel/sys.c | |
parent | 1c1e618ddd15f69fd87ccea596769f78c8065504 (diff) | |
download | lwn-86f162f4c75ceb6daf43165469eeeca1bc3d4639.tar.gz lwn-86f162f4c75ceb6daf43165469eeeca1bc3d4639.zip |
rlimits: do security check under task_lock
Do security_task_setrlimit under task_lock. Other tasks may change
limits under our hands while we are checking limits inside the
function. From now on, they can't.
Note that all the security work is done under a spinlock here now.
Security hooks count with that, they are called from interrupt context
(like security_task_kill) and with spinlocks already held (e.g.
capable->security_capable).
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Acked-by: James Morris <jmorris@namei.org>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'kernel/sys.c')
-rw-r--r-- | kernel/sys.c | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/kernel/sys.c b/kernel/sys.c index 9dbcbbcce153..c762eebdebf7 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1277,7 +1277,7 @@ int do_setrlimit(struct task_struct *tsk, unsigned int resource, struct rlimit *new_rlim) { struct rlimit *old_rlim; - int retval; + int retval = 0; if (resource >= RLIM_NLIMITS) return -EINVAL; @@ -1293,9 +1293,14 @@ int do_setrlimit(struct task_struct *tsk, unsigned int resource, goto out; } - retval = security_task_setrlimit(tsk->group_leader, resource, new_rlim); - if (retval) - goto out; + old_rlim = tsk->signal->rlim + resource; + task_lock(tsk->group_leader); + if (new_rlim->rlim_max > old_rlim->rlim_max && + !capable(CAP_SYS_RESOURCE)) + retval = -EPERM; + if (!retval) + retval = security_task_setrlimit(tsk->group_leader, resource, + new_rlim); if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) { /* @@ -1307,12 +1312,7 @@ int do_setrlimit(struct task_struct *tsk, unsigned int resource, new_rlim->rlim_cur = 1; } - old_rlim = tsk->signal->rlim + resource; - task_lock(tsk->group_leader); - if (new_rlim->rlim_max > old_rlim->rlim_max && - !capable(CAP_SYS_RESOURCE)) - retval = -EPERM; - else + if (!retval) *old_rlim = *new_rlim; task_unlock(tsk->group_leader); |