Skip to content

Commit

Permalink
Merge branch 'exec-linus' of git://git.kernel.org/pub/scm/linux/kerne…
Browse files Browse the repository at this point in the history
…l/git/ebiederm/user-namespace

Pull execve updates from Eric Biederman:
 "Last cycle for the Nth time I ran into bugs and quality of
  implementation issues related to exec that could not be easily be
  fixed because of the way exec is implemented. So I have been digging
  into exec and cleanup up what I can.

  I don't think I have exec sorted out enough to fix the issues I
  started with but I have made some headway this cycle with 4 sets of
  changes.

   - promised cleanups after introducing exec_update_mutex

   - trivial cleanups for exec

   - control flow simplifications

   - remove the recomputation of bprm->cred

  The net result is code that is a bit easier to understand and work
  with and a decrease in the number of lines of code (if you don't count
  the added tests)"

* 'exec-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (24 commits)
  exec: Compute file based creds only once
  exec: Add a per bprm->file version of per_clear
  binfmt_elf_fdpic: fix execfd build regression
  selftests/exec: Add binfmt_script regression test
  exec: Remove recursion from search_binary_handler
  exec: Generic execfd support
  exec/binfmt_script: Don't modify bprm->buf and then return -ENOEXEC
  exec: Move the call of prepare_binprm into search_binary_handler
  exec: Allow load_misc_binary to call prepare_binprm unconditionally
  exec: Convert security_bprm_set_creds into security_bprm_repopulate_creds
  exec: Factor security_bprm_creds_for_exec out of security_bprm_set_creds
  exec: Teach prepare_exec_creds how exec treats uids & gids
  exec: Set the point of no return sooner
  exec: Move handling of the point of no return to the top level
  exec: Run sync_mm_rss before taking exec_update_mutex
  exec: Fix spelling of search_binary_handler in a comment
  exec: Move the comment from above de_thread to above unshare_sighand
  exec: Rename flush_old_exec begin_new_exec
  exec: Move most of setup_new_exec into flush_old_exec
  exec: In setup_new_exec cache current in the local variable me
  ...
  • Loading branch information
torvalds committed Jun 4, 2020
2 parents 9ff7258 + 3977e28 commit 15a2bc4
Show file tree
Hide file tree
Showing 27 changed files with 501 additions and 387 deletions.
2 changes: 1 addition & 1 deletion Documentation/trace/ftrace.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1524,7 +1524,7 @@ display-graph option::
=> remove_vma
=> exit_mmap
=> mmput
=> flush_old_exec
=> begin_new_exec
=> load_elf_binary
=> search_binary_handler
=> __do_execve_file.isra.32
Expand Down
11 changes: 2 additions & 9 deletions arch/alpha/kernel/binfmt_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ static int load_binary(struct linux_binprm *bprm)
if (bprm->loader)
return -ENOEXEC;

allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;

loader = bprm->vma->vm_end - sizeof(void *);

file = open_exec("/sbin/loader");
Expand All @@ -33,12 +29,9 @@ static int load_binary(struct linux_binprm *bprm)
/* Remember if the application is TASO. */
bprm->taso = eh->ah.entry < 0x100000000UL;

bprm->file = file;
bprm->interpreter = file;
bprm->loader = loader;
retval = prepare_binprm(bprm);
if (retval < 0)
return retval;
return search_binary_handler(bprm);
return 0;
}

static struct linux_binfmt loader_format = {
Expand Down
4 changes: 1 addition & 3 deletions arch/x86/ia32/ia32_aout.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ static int load_aout_binary(struct linux_binprm *bprm)
return -ENOMEM;

/* Flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
retval = begin_new_exec(bprm);
if (retval)
return retval;

Expand All @@ -156,8 +156,6 @@ static int load_aout_binary(struct linux_binprm *bprm)
if (retval < 0)
return retval;

install_exec_creds(bprm);

if (N_MAGIC(ex) == OMAGIC) {
unsigned long text_addr, map_size;

Expand Down
3 changes: 1 addition & 2 deletions fs/binfmt_aout.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static int load_aout_binary(struct linux_binprm * bprm)
return -ENOMEM;

/* Flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
retval = begin_new_exec(bprm);
if (retval)
return retval;

Expand All @@ -174,7 +174,6 @@ static int load_aout_binary(struct linux_binprm * bprm)
if (retval < 0)
return retval;

install_exec_creds(bprm);

if (N_MAGIC(ex) == OMAGIC) {
unsigned long text_addr, map_size;
Expand Down
7 changes: 3 additions & 4 deletions fs/binfmt_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
NEW_AUX_ENT(AT_BASE_PLATFORM,
(elf_addr_t)(unsigned long)u_base_platform);
}
if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
if (bprm->have_execfd) {
NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
}
#undef NEW_AUX_ENT
/* AT_NULL is zero; clear the rest too */
Expand Down Expand Up @@ -975,7 +975,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
goto out_free_dentry;

/* Flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
retval = begin_new_exec(bprm);
if (retval)
goto out_free_dentry;

Expand All @@ -989,7 +989,6 @@ static int load_elf_binary(struct linux_binprm *bprm)
current->flags |= PF_RANDOMIZE;

setup_new_exec(bprm);
install_exec_creds(bprm);

/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
Expand Down
9 changes: 4 additions & 5 deletions fs/binfmt_elf_fdpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
interp_params.flags |= ELF_FDPIC_FLAG_CONSTDISP;

/* flush all traces of the currently running executable */
retval = flush_old_exec(bprm);
retval = begin_new_exec(bprm);
if (retval)
goto error;

Expand Down Expand Up @@ -434,7 +434,6 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
current->mm->start_stack = current->mm->start_brk + stack_size;
#endif

install_exec_creds(bprm);
if (create_elf_fdpic_tables(bprm, current->mm,
&exec_params, &interp_params) < 0)
goto error;
Expand Down Expand Up @@ -589,7 +588,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
nitems = 1 + DLINFO_ITEMS + (k_platform ? 1 : 0) +
(k_base_platform ? 1 : 0) + AT_VECTOR_SIZE_ARCH;

if (bprm->interp_flags & BINPRM_FLAGS_EXECFD)
if (bprm->have_execfd)
nitems++;

csp = sp;
Expand Down Expand Up @@ -629,10 +628,10 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm,
(elf_addr_t) (unsigned long) u_base_platform);
}

if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) {
if (bprm->have_execfd) {
nr = 0;
csp -= 2 * sizeof(unsigned long);
NEW_AUX_ENT(AT_EXECFD, bprm->interp_data);
NEW_AUX_ENT(AT_EXECFD, bprm->execfd);
}

nr = 0;
Expand Down
13 changes: 2 additions & 11 deletions fs/binfmt_em86.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ static int load_em86(struct linux_binprm *bprm)
if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
return -ENOENT;

allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;

/* Unlike in the script case, we don't have to do any hairy
* parsing to find our interpreter... it's hardcoded!
*/
Expand Down Expand Up @@ -89,13 +85,8 @@ static int load_em86(struct linux_binprm *bprm)
if (IS_ERR(file))
return PTR_ERR(file);

bprm->file = file;

retval = prepare_binprm(bprm);
if (retval < 0)
return retval;

return search_binary_handler(bprm);
bprm->interpreter = file;
return 0;
}

static struct linux_binfmt em86_format = {
Expand Down
4 changes: 1 addition & 3 deletions fs/binfmt_flat.c
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ static int load_flat_file(struct linux_binprm *bprm,

/* Flush all traces of the currently running executable */
if (id == 0) {
ret = flush_old_exec(bprm);
ret = begin_new_exec(bprm);
if (ret)
goto err;

Expand Down Expand Up @@ -963,8 +963,6 @@ static int load_flat_binary(struct linux_binprm *bprm)
}
}

install_exec_creds(bprm);

set_binfmt(&flat_format);

#ifdef CONFIG_MMU
Expand Down
69 changes: 10 additions & 59 deletions fs/binfmt_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ static int load_misc_binary(struct linux_binprm *bprm)
Node *fmt;
struct file *interp_file = NULL;
int retval;
int fd_binary = -1;

retval = -ENOEXEC;
if (!enabled)
Expand All @@ -160,51 +159,25 @@ static int load_misc_binary(struct linux_binprm *bprm)
goto ret;
}

if (fmt->flags & MISC_FMT_OPEN_BINARY) {
if (fmt->flags & MISC_FMT_OPEN_BINARY)
bprm->have_execfd = 1;

/* if the binary should be opened on behalf of the
* interpreter than keep it open and assign descriptor
* to it
*/
fd_binary = get_unused_fd_flags(0);
if (fd_binary < 0) {
retval = fd_binary;
goto ret;
}
fd_install(fd_binary, bprm->file);

/* if the binary is not readable than enforce mm->dumpable=0
regardless of the interpreter's permissions */
would_dump(bprm, bprm->file);

allow_write_access(bprm->file);
bprm->file = NULL;

/* mark the bprm that fd should be passed to interp */
bprm->interp_flags |= BINPRM_FLAGS_EXECFD;
bprm->interp_data = fd_binary;

} else {
allow_write_access(bprm->file);
fput(bprm->file);
bprm->file = NULL;
}
/* make argv[1] be the path to the binary */
retval = copy_strings_kernel(1, &bprm->interp, bprm);
if (retval < 0)
goto error;
goto ret;
bprm->argc++;

/* add the interp as argv[0] */
retval = copy_strings_kernel(1, &fmt->interpreter, bprm);
if (retval < 0)
goto error;
goto ret;
bprm->argc++;

/* Update interp in case binfmt_script needs it. */
retval = bprm_change_interp(fmt->interpreter, bprm);
if (retval < 0)
goto error;
goto ret;

if (fmt->flags & MISC_FMT_OPEN_FILE) {
interp_file = file_clone_open(fmt->interp_file);
Expand All @@ -215,38 +188,16 @@ static int load_misc_binary(struct linux_binprm *bprm)
}
retval = PTR_ERR(interp_file);
if (IS_ERR(interp_file))
goto error;

bprm->file = interp_file;
if (fmt->flags & MISC_FMT_CREDENTIALS) {
loff_t pos = 0;

/*
* No need to call prepare_binprm(), it's already been
* done. bprm->buf is stale, update from interp_file.
*/
memset(bprm->buf, 0, BINPRM_BUF_SIZE);
retval = kernel_read(bprm->file, bprm->buf, BINPRM_BUF_SIZE,
&pos);
} else
retval = prepare_binprm(bprm);

if (retval < 0)
goto error;
goto ret;

retval = search_binary_handler(bprm);
if (retval < 0)
goto error;
bprm->interpreter = interp_file;
if (fmt->flags & MISC_FMT_CREDENTIALS)
bprm->execfd_creds = 1;

retval = 0;
ret:
dput(fmt->dentry);
return retval;
error:
if (fd_binary > 0)
ksys_close(fd_binary);
bprm->interp_flags = 0;
bprm->interp_data = 0;
goto ret;
}

/* Command parsers */
Expand Down
Loading

0 comments on commit 15a2bc4

Please sign in to comment.