Move the common userspace argv and envp counting and stack setup code into do_execveat_common_bprm(). Keep do_execveat_common() responsible for the existing RLIMIT_NPROC check, bprm allocation, and error path. This is a mechanical refactor for later opened-file exec users. It does not change execve or execveat behavior.
Signed-off-by: Li Chen <[email protected]> --- fs/exec.c | 53 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 2889b7cf808d7..53f7b18d2b1ea 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1775,31 +1775,12 @@ static int bprm_execve(struct linux_binprm *bprm) return retval; } -static int do_execveat_common(int fd, struct filename *filename, - struct user_arg_ptr argv, - struct user_arg_ptr envp, - int flags) +static int do_execveat_common_bprm(struct linux_binprm *bprm, + struct user_arg_ptr argv, + struct user_arg_ptr envp) { int retval; - /* - * We move the actual failure in case of RLIMIT_NPROC excess from - * set*uid() to execve() because too many poorly written programs - * don't check setuid() return code. Here we additionally recheck - * whether NPROC limit is still exceeded. - */ - if ((current->flags & PF_NPROC_EXCEEDED) && - is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) - return -EAGAIN; - - /* We're below the limit (still or again), so we don't want to make - * further execve() calls fail. */ - current->flags &= ~PF_NPROC_EXCEEDED; - - CLASS(bprm, bprm)(fd, filename, flags); - if (IS_ERR(bprm)) - return PTR_ERR(bprm); - retval = count(argv, MAX_ARG_STRINGS); if (retval < 0) return retval; @@ -1846,6 +1827,34 @@ static int do_execveat_common(int fd, struct filename *filename, return bprm_execve(bprm); } +static int do_execveat_common(int fd, struct filename *filename, + struct user_arg_ptr argv, + struct user_arg_ptr envp, + int flags) +{ + /* + * We move the actual failure in case of RLIMIT_NPROC excess from + * set*uid() to execve() because too many poorly written programs + * don't check setuid() return code. Here we additionally recheck + * whether NPROC limit is still exceeded. + */ + if ((current->flags & PF_NPROC_EXCEEDED) && + is_rlimit_overlimit(current_ucounts(), UCOUNT_RLIMIT_NPROC, rlimit(RLIMIT_NPROC))) + return -EAGAIN; + + /* + * We're below the limit (still or again), so we don't want to make + * further execve() calls fail. + */ + current->flags &= ~PF_NPROC_EXCEEDED; + + CLASS(bprm, bprm)(fd, filename, flags); + if (IS_ERR(bprm)) + return PTR_ERR(bprm); + + return do_execveat_common_bprm(bprm, argv, envp); +} + int kernel_execve(const char *kernel_filename, const char *const *argv, const char *const *envp) { -- 2.52.0

