aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/fs/exec.c b/fs/exec.c
index 098de820abcc..882d31bb4fd3 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -110,6 +110,7 @@ bool path_noexec(const struct path *path)
return (path->mnt->mnt_flags & MNT_NOEXEC) ||
(path->mnt->mnt_sb->s_iflags & SB_I_NOEXEC);
}
+EXPORT_SYMBOL_GPL(path_noexec);
#ifdef CONFIG_USELIB
/*
@@ -454,6 +455,9 @@ static int prepare_arg_pages(struct linux_binprm *bprm,
unsigned long limit, ptr_size;
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 (bprm->argc < 0)
return bprm->argc;
@@ -482,8 +486,14 @@ static int prepare_arg_pages(struct linux_binprm *bprm,
* the stack. They aren't stored until much later when we can't
* signal to the parent that the child has run out of stack space.
* Instead, calculate it here so it's possible to fail gracefully.
+ *
+ * In the case of argc = 0, make sure there is space for adding a
+ * empty string (which will bump argc to 1), to ensure confused
+ * userspace programs don't start processing from argv[1], thinking
+ * argc can never be 0, to keep them from walking envp by accident.
+ * See do_execveat_common().
*/
- ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
+ ptr_size = (max(bprm->argc, 1) + bprm->envc) * sizeof(void *);
if (limit <= ptr_size)
return -E2BIG;
limit -= ptr_size;
@@ -827,6 +837,7 @@ int transfer_args_to_stack(struct linux_binprm *bprm,
goto out;
}
+ bprm->exec += *sp_location - MAX_ARG_PAGES * PAGE_SIZE;
*sp_location = sp;
out:
@@ -1848,6 +1859,20 @@ static int __do_execve_file(int fd, struct filename *filename,
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);
if (retval < 0)
goto out;