Skip to content

Commit a16b335

Browse files
committed
exec: Allow load_misc_binary to call prepare_binprm unconditionally
Add a flag preserve_creds that binfmt_misc can set to prevent credentials from being updated. This allows binfmt_misc to always call prepare_binprm. Allowing the credential computation logic to be consolidated. Not replacing the credentials with the interpreters credentials is safe because because an open file descriptor to the executable is passed to the interpreter. As the interpreter does not need to reopen the executable it is guaranteed to see the same file that exec sees. Ref: c407c03 ("[PATCH] binfmt_misc: improve calculation of interpreter's credentials") Link: https://lkml.kernel.org/r/[email protected] Acked-by: Linus Torvalds <[email protected]> Reviewed-by: Kees Cook <[email protected]> Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 112b714 commit a16b335

File tree

3 files changed

+17
-19
lines changed

3 files changed

+17
-19
lines changed

fs/binfmt_misc.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,19 +218,10 @@ static int load_misc_binary(struct linux_binprm *bprm)
218218
goto error;
219219

220220
bprm->file = interp_file;
221-
if (fmt->flags & MISC_FMT_CREDENTIALS) {
222-
loff_t pos = 0;
223-
224-
/*
225-
* No need to call prepare_binprm(), it's already been
226-
* done. bprm->buf is stale, update from interp_file.
227-
*/
228-
memset(bprm->buf, 0, BINPRM_BUF_SIZE);
229-
retval = kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE,
230-
&pos);
231-
} else
232-
retval = prepare_binprm(bprm);
221+
if (fmt->flags & MISC_FMT_CREDENTIALS)
222+
bprm->preserve_creds = 1;
233223

224+
retval = prepare_binprm(bprm);
234225
if (retval < 0)
235226
goto error;
236227

fs/exec.c

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,15 +1631,20 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
16311631
*/
16321632
int prepare_binprm(struct linux_binprm *bprm)
16331633
{
1634-
int retval;
16351634
loff_t pos = 0;
16361635

1637-
/* Recompute parts of bprm->cred based on bprm->file */
1638-
bprm->active_secureexec = 0;
1639-
bprm_fill_uid(bprm);
1640-
retval = security_bprm_repopulate_creds(bprm);
1641-
if (retval)
1642-
return retval;
1636+
/* Can the interpreter get to the executable without races? */
1637+
if (!bprm->preserve_creds) {
1638+
int retval;
1639+
1640+
/* Recompute parts of bprm->cred based on bprm->file */
1641+
bprm->active_secureexec = 0;
1642+
bprm_fill_uid(bprm);
1643+
retval = security_bprm_repopulate_creds(bprm);
1644+
if (retval)
1645+
return retval;
1646+
}
1647+
bprm->preserve_creds = 0;
16431648

16441649
memset(bprm->buf, 0, BINPRM_BUF_SIZE);
16451650
return kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE, &pos);

include/linux/binfmts.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ struct linux_binprm {
2626
unsigned long p; /* current top of mem */
2727
unsigned long argmin; /* rlimit marker for copy_strings() */
2828
unsigned int
29+
/* It is safe to use the creds of a script (see binfmt_misc) */
30+
preserve_creds:1,
2931
/*
3032
* True if most recent call to security_bprm_set_creds
3133
* resulted in elevated privileges.

0 commit comments

Comments
 (0)