Skip to content

Commit b519f2e

Browse files
oleg-nesterovgregkh
authored andcommitted
exec: fix the racy usage of fs_struct->in_exec
commit af7bb0d upstream. check_unsafe_exec() sets fs->in_exec under cred_guard_mutex, then execve() paths clear fs->in_exec lockless. This is fine if exec succeeds, but if it fails we have the following race: T1 sets fs->in_exec = 1, fails, drops cred_guard_mutex T2 sets fs->in_exec = 1 T1 clears fs->in_exec T2 continues with fs->in_exec == 0 Change fs/exec.c to clear fs->in_exec with cred_guard_mutex held. Reported-by: syzbot+1c486d0b62032c82a968@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/67dc67f0.050a0220.25ae54.001f.GAE@google.com/ Cc: stable@vger.kernel.org Signed-off-by: Oleg Nesterov <oleg@redhat.com> Link: https://lore.kernel.org/r/20250324160003.GA8878@redhat.com Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 717d9c3 commit b519f2e

1 file changed

Lines changed: 9 additions & 6 deletions

File tree

fs/exec.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,13 +1229,12 @@ int begin_new_exec(struct linux_binprm * bprm)
12291229
*/
12301230
bprm->point_of_no_return = true;
12311231

1232-
/*
1233-
* Make this the only thread in the thread group.
1234-
*/
1232+
/* Make this the only thread in the thread group */
12351233
retval = de_thread(me);
12361234
if (retval)
12371235
goto out;
1238-
1236+
/* see the comment in check_unsafe_exec() */
1237+
current->fs->in_exec = 0;
12391238
/*
12401239
* Cancel any io_uring activity across execve
12411240
*/
@@ -1497,6 +1496,8 @@ static void free_bprm(struct linux_binprm *bprm)
14971496
}
14981497
free_arg_pages(bprm);
14991498
if (bprm->cred) {
1499+
/* in case exec fails before de_thread() succeeds */
1500+
current->fs->in_exec = 0;
15001501
mutex_unlock(&current->signal->cred_guard_mutex);
15011502
abort_creds(bprm->cred);
15021503
}
@@ -1618,6 +1619,10 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
16181619
* suid exec because the differently privileged task
16191620
* will be able to manipulate the current directory, etc.
16201621
* It would be nice to force an unshare instead...
1622+
*
1623+
* Otherwise we set fs->in_exec = 1 to deny clone(CLONE_FS)
1624+
* from another sub-thread until de_thread() succeeds, this
1625+
* state is protected by cred_guard_mutex we hold.
16211626
*/
16221627
n_fs = 1;
16231628
spin_lock(&p->fs->lock);
@@ -1862,7 +1867,6 @@ static int bprm_execve(struct linux_binprm *bprm)
18621867

18631868
sched_mm_cid_after_execve(current);
18641869
/* execve succeeded */
1865-
current->fs->in_exec = 0;
18661870
current->in_execve = 0;
18671871
rseq_execve(current);
18681872
user_events_execve(current);
@@ -1881,7 +1885,6 @@ static int bprm_execve(struct linux_binprm *bprm)
18811885
force_fatal_sig(SIGSEGV);
18821886

18831887
sched_mm_cid_after_execve(current);
1884-
current->fs->in_exec = 0;
18851888
current->in_execve = 0;
18861889

18871890
return retval;

0 commit comments

Comments
 (0)