summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/binfmt_elf.c4
-rw-r--r--fs/binfmt_elf_fdpic.c4
-rw-r--r--fs/binfmt_misc.c40
-rw-r--r--fs/exec.c15
-rw-r--r--include/linux/binfmts.h10
5 files changed, 32 insertions, 41 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 396d5c2e6b5e..441c85f04dfd 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -273,8 +273,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 */
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 896e3ca9bf85..2d5e9eb12075 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -628,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;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 50a73afdf9b7..ad2866f28f0c 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -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)
@@ -161,29 +160,12 @@ static int load_misc_binary(struct linux_binprm *bprm)
}
if (fmt->flags & MISC_FMT_OPEN_BINARY) {
-
- /* 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);
+ /* Pass the open binary to the interpreter */
+ bprm->have_execfd = 1;
+ bprm->executable = 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);
@@ -192,19 +174,19 @@ static int load_misc_binary(struct linux_binprm *bprm)
/* 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);
@@ -215,7 +197,7 @@ static int load_misc_binary(struct linux_binprm *bprm)
}
retval = PTR_ERR(interp_file);
if (IS_ERR(interp_file))
- goto error;
+ goto ret;
bprm->file = interp_file;
if (fmt->flags & MISC_FMT_CREDENTIALS)
@@ -223,17 +205,11 @@ static int load_misc_binary(struct linux_binprm *bprm)
retval = search_binary_handler(bprm);
if (retval < 0)
- goto error;
+ goto ret;
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 */
diff --git a/fs/exec.c b/fs/exec.c
index 5fc458460e44..117ad8fc012b 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1323,7 +1323,10 @@ int begin_new_exec(struct linux_binprm * bprm)
*/
set_mm_exe_file(bprm->mm, bprm->file);
+ /* If the binary is not readable then enforce mm->dumpable=0 */
would_dump(bprm, bprm->file);
+ if (bprm->have_execfd)
+ would_dump(bprm, bprm->executable);
/*
* Release all of the old mmap stuff
@@ -1427,6 +1430,16 @@ int begin_new_exec(struct linux_binprm * bprm)
* credentials; any time after this it may be unlocked.
*/
security_bprm_committed_creds(bprm);
+
+ /* Pass the opened binary to the interpreter. */
+ if (bprm->have_execfd) {
+ retval = get_unused_fd_flags(0);
+ if (retval < 0)
+ goto out_unlock;
+ fd_install(retval, bprm->executable);
+ bprm->executable = NULL;
+ bprm->execfd = retval;
+ }
return 0;
out_unlock:
@@ -1516,6 +1529,8 @@ static void free_bprm(struct linux_binprm *bprm)
allow_write_access(bprm->file);
fput(bprm->file);
}
+ if (bprm->executable)
+ fput(bprm->executable);
/* If a binfmt changed the interp, free it. */
if (bprm->interp != bprm->filename)
kfree(bprm->interp);
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 8c7779d6bf19..653508b25815 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -26,6 +26,9 @@ struct linux_binprm {
unsigned long p; /* current top of mem */
unsigned long argmin; /* rlimit marker for copy_strings() */
unsigned int
+ /* Should an execfd be passed to userspace? */
+ have_execfd:1,
+
/* It is safe to use the creds of a script (see binfmt_misc) */
preserve_creds:1,
/*
@@ -48,6 +51,7 @@ struct linux_binprm {
unsigned int taso:1;
#endif
unsigned int recursion_depth; /* only for search_binary_handler() */
+ struct file * executable; /* Executable to pass to the interpreter */
struct file * file;
struct cred *cred; /* new credentials */
int unsafe; /* how unsafe this exec is (mask of LSM_UNSAFE_*) */
@@ -58,7 +62,7 @@ struct linux_binprm {
of the time same as filename, but could be
different for binfmt_{misc,script} */
unsigned interp_flags;
- unsigned interp_data;
+ int execfd; /* File descriptor of the executable */
unsigned long loader, exec;
struct rlimit rlim_stack; /* Saved RLIMIT_STACK used during exec. */
@@ -69,10 +73,6 @@ struct linux_binprm {
#define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
#define BINPRM_FLAGS_ENFORCE_NONDUMP (1 << BINPRM_FLAGS_ENFORCE_NONDUMP_BIT)
-/* fd of the binary should be passed to the interpreter */
-#define BINPRM_FLAGS_EXECFD_BIT 1
-#define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT)
-
/* filename of the binary will be inaccessible after exec */
#define BINPRM_FLAGS_PATH_INACCESSIBLE_BIT 2
#define BINPRM_FLAGS_PATH_INACCESSIBLE (1 << BINPRM_FLAGS_PATH_INACCESSIBLE_BIT)