Skip to content

Commit 0a8f36e

Browse files
committed
exec: Factor out alloc_bprm
Currently it is necessary for the usermode helper code and the code that launches init to use set_fs so that pages coming from the kernel look like they are coming from userspace. To allow that usage of set_fs to be removed cleanly the argument copying from userspace needs to happen earlier. Move the allocation of the bprm into it's own function (alloc_bprm) and move the call of alloc_bprm before unshare_files so that bprm can ultimately be allocated, the arguments can be placed on the new stack, and then the bprm can be passed into the core of exec. Neither the allocation of struct binprm nor the unsharing depend upon each other so swapping the order in which they are called is trivially safe. To keep things consistent the order of cleanup at the end of do_execve_common swapped to match the order of initialization. Reviewed-by: Kees Cook <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: "Eric W. Biederman" <[email protected]>
1 parent 9746c9b commit 0a8f36e

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

fs/exec.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,14 @@ static void free_bprm(struct linux_binprm *bprm)
15601560
kfree(bprm);
15611561
}
15621562

1563+
static struct linux_binprm *alloc_bprm(void)
1564+
{
1565+
struct linux_binprm *bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1566+
if (!bprm)
1567+
return ERR_PTR(-ENOMEM);
1568+
return bprm;
1569+
}
1570+
15631571
int bprm_change_interp(const char *interp, struct linux_binprm *bprm)
15641572
{
15651573
/* If a binfmt changed the interp, free it first. */
@@ -1848,18 +1856,19 @@ static int do_execveat_common(int fd, struct filename *filename,
18481856
* further execve() calls fail. */
18491857
current->flags &= ~PF_NPROC_EXCEEDED;
18501858

1851-
retval = unshare_files(&displaced);
1852-
if (retval)
1859+
bprm = alloc_bprm();
1860+
if (IS_ERR(bprm)) {
1861+
retval = PTR_ERR(bprm);
18531862
goto out_ret;
1863+
}
18541864

1855-
retval = -ENOMEM;
1856-
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
1857-
if (!bprm)
1858-
goto out_files;
1865+
retval = unshare_files(&displaced);
1866+
if (retval)
1867+
goto out_free;
18591868

18601869
retval = prepare_bprm_creds(bprm);
18611870
if (retval)
1862-
goto out_free;
1871+
goto out_files;
18631872

18641873
check_unsafe_exec(bprm);
18651874
current->in_execve = 1;
@@ -1956,13 +1965,13 @@ static int do_execveat_common(int fd, struct filename *filename,
19561965
current->fs->in_exec = 0;
19571966
current->in_execve = 0;
19581967

1968+
out_files:
1969+
if (displaced)
1970+
reset_files_struct(displaced);
19591971
out_free:
19601972
free_bprm(bprm);
19611973
kfree(pathbuf);
19621974

1963-
out_files:
1964-
if (displaced)
1965-
reset_files_struct(displaced);
19661975
out_ret:
19671976
putname(filename);
19681977
return retval;

0 commit comments

Comments
 (0)