@@ -697,7 +697,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
retval = -ENOEXEC;
/* First of all, some simple consistency checks */
- if (memcmp(loc->elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+ if (!elf_check_linux_magic(&loc->elf_ex))
goto out;
if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN)
@@ -800,7 +800,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
if (elf_interpreter) {
retval = -ELIBBAD;
/* Not an ELF interpreter */
- if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+ if (!elf_check_linux_magic(&loc->interp_elf_ex))
goto out_free_dentry;
/* Verify the interpreter has a valid arch */
if (!elf_check_arch(&loc->interp_elf_ex))
@@ -1122,7 +1122,7 @@ static int load_elf_library(struct file *file)
if (retval != sizeof(elf_ex))
goto out;
- if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+ if (!elf_check_linux_magic(&elf_ex))
goto out;
/* First of all, some simple consistency checks */
@@ -106,7 +106,7 @@ module_exit(exit_elf_fdpic_binfmt);
static int is_elf(struct elfhdr *hdr, struct file *file)
{
- if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0)
+ if (!elf_check_linux_magic(hdr))
return 0;
if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN)
return 0;
@@ -32,7 +32,7 @@ static int load_em86(struct linux_binprm *bprm)
/* Make sure this is a Linux/Intel ELF executable... */
elf_ex = *((struct elfhdr *)bprm->buf);
- if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
+ if (!elf_check_linux_magic(&elf_ex))
return -ENOEXEC;
/* First of all, some simple consistency checks */
@@ -46,6 +46,15 @@ extern Elf64_Dyn _DYNAMIC [];
struct file;
struct coredump_params;
+/*
+ * Returns true if the ELF header corresponds with a valid ELF file that
+ * is supposed to be used on Linux.
+ */
+#define elf_check_linux_magic(hdr) \
+ (memcmp((hdr)->e_ident, ELFMAG, SELFMAG) == 0 && \
+ ((hdr)->e_ident[EI_OSABI] == ELFOSABI_NONE || \
+ (hdr)->e_ident[EI_OSABI] == ELFOSABI_LINUX))
+
#ifndef ARCH_HAVE_EXTRA_ELF_NOTES
static inline int elf_coredump_extra_notes_size(void) { return 0; }
static inline int elf_coredump_extra_notes_write(struct coredump_params *cprm) { return 0; }
While implementing an alternative binfmt for a pure capability-based runtime environment[1], I noticed that our current binfmts don't test against the OSABI field. This can for example be observed by trying to execute a (statically linked) FreeBSD binary on Linux: $ ./sbin/init zsh: segmentation fault (core dumped) ./sbin/init Introduce a new macro called elf_check_linux_magic() that we can use to validate that an ELF header is suitable for use on Linux, similar to how the existing elf_check_arch() macro validates that an ELF header is suitable for the current architecture. Let this macro match both ELFOSABI_NONE and ELFOSABI_LINUX, as the former is actually used more commonly. This allows people to experiment with custom ELF binfmts without having the standard binfmt taking preference. If we now try to execute our FreeBSD binary we get an error message instead, as no matching binfmt exists: $ ./sbin/init zsh: exec format error: ./sbin/init [1] CloudABI: https://www.youtube.com/watch?v=62cYMmSY2Dc Signed-off-by: Ed Schouten <ed@nuxi.nl> --- fs/binfmt_elf.c | 6 +++--- fs/binfmt_elf_fdpic.c | 2 +- fs/binfmt_em86.c | 2 +- include/linux/elf.h | 9 +++++++++ 4 files changed, 14 insertions(+), 5 deletions(-)