From 518acbdb88c6fb53f7ba8d768c9ab07fd0f07f1c Mon Sep 17 00:00:00 2001 From: Park Ju Hyung Date: Wed, 18 Mar 2020 19:15:04 +0900 Subject: [PATCH] exec: use bprm from the stack space struct linux_binprm isn't big and is safe to use from the stack space Signed-off-by: Park Ju Hyung [@0ctobot: Adapted for 4.19] Signed-off-by: Adam W. Willis --- fs/exec.c | 74 +++++++++++++++++++------------------------------------ 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 82d943489c44..9259024f8ac1 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1445,7 +1445,6 @@ static void free_bprm(struct linux_binprm *bprm) /* If a binfmt changed the interp, free it. */ if (bprm->interp != bprm->filename) kfree(bprm->interp); - kfree(bprm); } int bprm_change_interp(const char *interp, struct linux_binprm *bprm) @@ -1731,7 +1730,7 @@ static int __do_execve_file(int fd, struct filename *filename, int flags, struct file *file) { char *pathbuf = NULL; - struct linux_binprm *bprm; + struct linux_binprm bprm; struct files_struct *displaced; int retval; @@ -1758,16 +1757,13 @@ static int __do_execve_file(int fd, struct filename *filename, if (retval) goto out_ret; - retval = -ENOMEM; - bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); - if (!bprm) - goto out_files; + memset(&bprm, 0, sizeof(bprm)); - retval = prepare_bprm_creds(bprm); + retval = prepare_bprm_creds(&bprm); if (retval) goto out_free; - check_unsafe_exec(bprm); + check_unsafe_exec(&bprm); current->in_execve = 1; if (!file) @@ -1778,11 +1774,11 @@ static int __do_execve_file(int fd, struct filename *filename, sched_exec(); - bprm->file = file; + bprm.file = file; if (!filename) { - bprm->filename = "none"; + bprm.filename = "none"; } else if (fd == AT_FDCWD || filename->name[0] == '/') { - bprm->filename = filename->name; + bprm.filename = filename->name; } else { if (filename->name[0] == '\0') pathbuf = kasprintf(GFP_KERNEL, "/dev/fd/%d", fd); @@ -1799,58 +1795,41 @@ static int __do_execve_file(int fd, struct filename *filename, * current->files (due to unshare_files above). */ if (close_on_exec(fd, rcu_dereference_raw(current->files->fdt))) - bprm->interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; - bprm->filename = pathbuf; + bprm.interp_flags |= BINPRM_FLAGS_PATH_INACCESSIBLE; + bprm.filename = pathbuf; } - bprm->interp = bprm->filename; + bprm.interp = bprm.filename; - retval = bprm_mm_init(bprm); + retval = bprm_mm_init(&bprm); if (retval) goto out_unmark; - bprm->argc = count(argv, MAX_ARG_STRINGS); - if (bprm->argc == 0) - pr_warn_once("process '%s' launched '%s' with NULL argv: empty string added\n", - current->comm, bprm->filename); - if ((retval = bprm->argc) < 0) + bprm.argc = count(argv, MAX_ARG_STRINGS); + if ((retval = bprm.argc) < 0) goto out; - bprm->envc = count(envp, MAX_ARG_STRINGS); - if ((retval = bprm->envc) < 0) + bprm.envc = count(envp, MAX_ARG_STRINGS); + if ((retval = bprm.envc) < 0) goto out; - retval = prepare_binprm(bprm); + retval = prepare_binprm(&bprm); if (retval < 0) goto out; - retval = copy_strings_kernel(1, &bprm->filename, bprm); + retval = copy_strings_kernel(1, &bprm.filename, &bprm); if (retval < 0) goto out; - bprm->exec = bprm->p; - retval = copy_strings(bprm->envc, envp, bprm); + bprm.exec = bprm.p; + retval = copy_strings(bprm.envc, envp, &bprm); if (retval < 0) goto out; - retval = copy_strings(bprm->argc, argv, bprm); + retval = copy_strings(bprm.argc, argv, &bprm); if (retval < 0) goto out; - /* - * When argv is empty, add an empty string ("") as argv[0] to - * ensure confused userspace programs that start processing - * from argv[1] won't end up walking envp. See also - * bprm_stack_limits(). - */ - if (bprm->argc == 0) { - const char *argv[] = { "", NULL }; - retval = copy_strings_kernel(1, argv, bprm); - if (retval < 0) - goto out; - bprm->argc = 1; - } - - retval = exec_binprm(bprm); + retval = exec_binprm(&bprm); if (retval < 0) goto out; @@ -1870,7 +1849,7 @@ static int __do_execve_file(int fd, struct filename *filename, rseq_execve(current); acct_update_integrals(current); task_numa_free(current, false); - free_bprm(bprm); + free_bprm(&bprm); kfree(pathbuf); if (filename) putname(filename); @@ -1879,9 +1858,9 @@ static int __do_execve_file(int fd, struct filename *filename, return retval; out: - if (bprm->mm) { - acct_arg_size(bprm, 0); - mmput(bprm->mm); + if (bprm.mm) { + acct_arg_size(&bprm, 0); + mmput(bprm.mm); } out_unmark: @@ -1889,10 +1868,9 @@ out_unmark: current->in_execve = 0; out_free: - free_bprm(bprm); + free_bprm(&bprm); kfree(pathbuf); -out_files: if (displaced) reset_files_struct(displaced); out_ret: