Skip to content

Commit a15f37a

Browse files
oleg-nesterovakpm00
authored andcommitted
kernel/sys.c: fix the racy usage of task_lock(tsk->group_leader) in sys_prlimit64() paths
The usage of task_lock(tsk->group_leader) in sys_prlimit64()->do_prlimit() path is very broken. sys_prlimit64() does get_task_struct(tsk) but this only protects task_struct itself. If tsk != current and tsk is not a leader, this process can exit/exec and task_lock(tsk->group_leader) may use the already freed task_struct. Another problem is that sys_prlimit64() can race with mt-exec which changes ->group_leader. In this case do_prlimit() may take the wrong lock, or (worse) ->group_leader may change between task_lock() and task_unlock(). Change sys_prlimit64() to take tasklist_lock when necessary. This is not nice, but I don't see a better fix for -stable. Link: https://lkml.kernel.org/r/[email protected] Fixes: 18c91bb ("prlimit: do not grab the tasklist_lock") Signed-off-by: Oleg Nesterov <[email protected]> Cc: Christian Brauner <[email protected]> Cc: Jiri Slaby <[email protected]> Cc: Mateusz Guzik <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 39f17c7 commit a15f37a

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

kernel/sys.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1734,6 +1734,7 @@ SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource,
17341734
struct rlimit old, new;
17351735
struct task_struct *tsk;
17361736
unsigned int checkflags = 0;
1737+
bool need_tasklist;
17371738
int ret;
17381739

17391740
if (old_rlim)
@@ -1760,8 +1761,25 @@ SYSCALL_DEFINE4(prlimit64, pid_t, pid, unsigned int, resource,
17601761
get_task_struct(tsk);
17611762
rcu_read_unlock();
17621763

1763-
ret = do_prlimit(tsk, resource, new_rlim ? &new : NULL,
1764-
old_rlim ? &old : NULL);
1764+
need_tasklist = !same_thread_group(tsk, current);
1765+
if (need_tasklist) {
1766+
/*
1767+
* Ensure we can't race with group exit or de_thread(),
1768+
* so tsk->group_leader can't be freed or changed until
1769+
* read_unlock(tasklist_lock) below.
1770+
*/
1771+
read_lock(&tasklist_lock);
1772+
if (!pid_alive(tsk))
1773+
ret = -ESRCH;
1774+
}
1775+
1776+
if (!ret) {
1777+
ret = do_prlimit(tsk, resource, new_rlim ? &new : NULL,
1778+
old_rlim ? &old : NULL);
1779+
}
1780+
1781+
if (need_tasklist)
1782+
read_unlock(&tasklist_lock);
17651783

17661784
if (!ret && old_rlim) {
17671785
rlim_to_rlim64(&old, &old64);

0 commit comments

Comments
 (0)