|
@@ -440,6 +440,74 @@ out:
|
|
|
return elf_phdata;
|
|
|
}
|
|
|
|
|
|
+#ifndef CONFIG_ARCH_BINFMT_ELF_STATE
|
|
|
+
|
|
|
+/**
|
|
|
+ * struct arch_elf_state - arch-specific ELF loading state
|
|
|
+ *
|
|
|
+ * This structure is used to preserve architecture specific data during
|
|
|
+ * the loading of an ELF file, throughout the checking of architecture
|
|
|
+ * specific ELF headers & through to the point where the ELF load is
|
|
|
+ * known to be proceeding (ie. SET_PERSONALITY).
|
|
|
+ *
|
|
|
+ * This implementation is a dummy for architectures which require no
|
|
|
+ * specific state.
|
|
|
+ */
|
|
|
+struct arch_elf_state {
|
|
|
+};
|
|
|
+
|
|
|
+#define INIT_ARCH_ELF_STATE {}
|
|
|
+
|
|
|
+/**
|
|
|
+ * arch_elf_pt_proc() - check a PT_LOPROC..PT_HIPROC ELF program header
|
|
|
+ * @ehdr: The main ELF header
|
|
|
+ * @phdr: The program header to check
|
|
|
+ * @elf: The open ELF file
|
|
|
+ * @is_interp: True if the phdr is from the interpreter of the ELF being
|
|
|
+ * loaded, else false.
|
|
|
+ * @state: Architecture-specific state preserved throughout the process
|
|
|
+ * of loading the ELF.
|
|
|
+ *
|
|
|
+ * Inspects the program header phdr to validate its correctness and/or
|
|
|
+ * suitability for the system. Called once per ELF program header in the
|
|
|
+ * range PT_LOPROC to PT_HIPROC, for both the ELF being loaded and its
|
|
|
+ * interpreter.
|
|
|
+ *
|
|
|
+ * Return: Zero to proceed with the ELF load, non-zero to fail the ELF load
|
|
|
+ * with that return code.
|
|
|
+ */
|
|
|
+static inline int arch_elf_pt_proc(struct elfhdr *ehdr,
|
|
|
+ struct elf_phdr *phdr,
|
|
|
+ struct file *elf, bool is_interp,
|
|
|
+ struct arch_elf_state *state)
|
|
|
+{
|
|
|
+ /* Dummy implementation, always proceed */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * arch_check_elf() - check a PT_LOPROC..PT_HIPROC ELF program header
|
|
|
+ * @ehdr: The main ELF header
|
|
|
+ * @has_interp: True if the ELF has an interpreter, else false.
|
|
|
+ * @state: Architecture-specific state preserved throughout the process
|
|
|
+ * of loading the ELF.
|
|
|
+ *
|
|
|
+ * Provides a final opportunity for architecture code to reject the loading
|
|
|
+ * of the ELF & cause an exec syscall to return an error. This is called after
|
|
|
+ * all program headers to be checked by arch_elf_pt_proc have been.
|
|
|
+ *
|
|
|
+ * Return: Zero to proceed with the ELF load, non-zero to fail the ELF load
|
|
|
+ * with that return code.
|
|
|
+ */
|
|
|
+static inline int arch_check_elf(struct elfhdr *ehdr, bool has_interp,
|
|
|
+ struct arch_elf_state *state)
|
|
|
+{
|
|
|
+ /* Dummy implementation, always proceed */
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+#endif /* !CONFIG_ARCH_BINFMT_ELF_STATE */
|
|
|
+
|
|
|
/* This is much more generalized than the library routine read function,
|
|
|
so we keep this separate. Technically the library read function
|
|
|
is only provided so that we can read a.out libraries that have
|
|
@@ -611,6 +679,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|
|
struct elfhdr elf_ex;
|
|
|
struct elfhdr interp_elf_ex;
|
|
|
} *loc;
|
|
|
+ struct arch_elf_state arch_state = INIT_ARCH_ELF_STATE;
|
|
|
|
|
|
loc = kmalloc(sizeof(*loc), GFP_KERNEL);
|
|
|
if (!loc) {
|
|
@@ -705,12 +774,21 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|
|
|
|
|
elf_ppnt = elf_phdata;
|
|
|
for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
|
|
|
- if (elf_ppnt->p_type == PT_GNU_STACK) {
|
|
|
+ switch (elf_ppnt->p_type) {
|
|
|
+ case PT_GNU_STACK:
|
|
|
if (elf_ppnt->p_flags & PF_X)
|
|
|
executable_stack = EXSTACK_ENABLE_X;
|
|
|
else
|
|
|
executable_stack = EXSTACK_DISABLE_X;
|
|
|
break;
|
|
|
+
|
|
|
+ case PT_LOPROC ... PT_HIPROC:
|
|
|
+ retval = arch_elf_pt_proc(&loc->elf_ex, elf_ppnt,
|
|
|
+ bprm->file, false,
|
|
|
+ &arch_state);
|
|
|
+ if (retval)
|
|
|
+ goto out_free_dentry;
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
/* Some simple consistency checks for the interpreter */
|
|
@@ -728,8 +806,30 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|
|
interpreter);
|
|
|
if (!interp_elf_phdata)
|
|
|
goto out_free_dentry;
|
|
|
+
|
|
|
+ /* Pass PT_LOPROC..PT_HIPROC headers to arch code */
|
|
|
+ elf_ppnt = interp_elf_phdata;
|
|
|
+ for (i = 0; i < loc->interp_elf_ex.e_phnum; i++, elf_ppnt++)
|
|
|
+ switch (elf_ppnt->p_type) {
|
|
|
+ case PT_LOPROC ... PT_HIPROC:
|
|
|
+ retval = arch_elf_pt_proc(&loc->interp_elf_ex,
|
|
|
+ elf_ppnt, interpreter,
|
|
|
+ true, &arch_state);
|
|
|
+ if (retval)
|
|
|
+ goto out_free_dentry;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Allow arch code to reject the ELF at this point, whilst it's
|
|
|
+ * still possible to return an error to the code that invoked
|
|
|
+ * the exec syscall.
|
|
|
+ */
|
|
|
+ retval = arch_check_elf(&loc->elf_ex, !!interpreter, &arch_state);
|
|
|
+ if (retval)
|
|
|
+ goto out_free_dentry;
|
|
|
+
|
|
|
/* Flush all traces of the currently running executable */
|
|
|
retval = flush_old_exec(bprm);
|
|
|
if (retval)
|
|
@@ -737,7 +837,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|
|
|
|
|
/* Do this immediately, since STACK_TOP as used in setup_arg_pages
|
|
|
may depend on the personality. */
|
|
|
- SET_PERSONALITY(loc->elf_ex);
|
|
|
+ SET_PERSONALITY2(loc->elf_ex, &arch_state);
|
|
|
if (elf_read_implies_exec(loc->elf_ex, executable_stack))
|
|
|
current->personality |= READ_IMPLIES_EXEC;
|
|
|
|
|
@@ -929,6 +1029,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ kfree(interp_elf_phdata);
|
|
|
kfree(elf_phdata);
|
|
|
|
|
|
set_binfmt(&elf_format);
|