--- kernel-2.6.28-jaunty/fs/binfmt_elf.c.orig 2009-06-10 07:05:27.000000000 +0400 +++ kernel-2.6.28/fs/binfmt_elf.c 2009-09-29 14:46:39.008238197 +0400 @@ -571,6 +571,7 @@ static int load_elf_binary(struct linux_ unsigned long elf_bss, elf_brk; int retval, i; unsigned int size; + unsigned int offset; unsigned long elf_entry; unsigned long interp_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; @@ -588,6 +589,8 @@ static int load_elf_binary(struct linux_ goto out_ret; } + offset = 0; +retry_elf: /* Get the exec-header */ loc->elf_ex = *((struct elfhdr *)bprm->buf); @@ -598,8 +601,27 @@ static int load_elf_binary(struct linux_ if (loc->elf_ex.e_type != ET_EXEC && loc->elf_ex.e_type != ET_DYN) goto out; - if (!elf_check_arch(&loc->elf_ex)) +#if (defined(__x86_64__) || defined(__powerpc64__) || defined(__s390x__)) \ + && ELF_CLASS == ELFCLASS64 + if (personality(current->personality) == PER_LINUX32) goto out; +#endif + if (!elf_check_arch(&loc->elf_ex)) { + offset = loc->elf_ex.e_ident[0xc] + | loc->elf_ex.e_ident[0xd] << 8 + | loc->elf_ex.e_ident[0xe] << 16 + | loc->elf_ex.e_ident[0xf] << 24; + if (offset != 0) { + memset(bprm->buf, 0, BINPRM_BUF_SIZE); + retval = kernel_read(bprm->file, offset, bprm->buf, BINPRM_BUF_SIZE); + if (retval != BINPRM_BUF_SIZE) { + retval = -ENOEXEC; + goto out; + } + goto retry_elf; + } + goto out; + } if (!bprm->file->f_op||!bprm->file->f_op->mmap) goto out; @@ -723,13 +745,30 @@ static int load_elf_binary(struct linux_ /* Some simple consistency checks for the interpreter */ if (elf_interpreter) { + offset = 0; +retry_interp: retval = -ELIBBAD; + loc->interp_elf_ex = *((struct elfhdr *)bprm->buf); /* Not an ELF interpreter */ if (memcmp(loc->interp_elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out_free_dentry; /* Verify the interpreter has a valid arch */ - if (!elf_check_arch(&loc->interp_elf_ex)) + if (!elf_check_arch(&loc->interp_elf_ex)) { + offset = loc->interp_elf_ex.e_ident[0xc] + | loc->interp_elf_ex.e_ident[0xd] << 8 + | loc->interp_elf_ex.e_ident[0xe] << 16 + | loc->interp_elf_ex.e_ident[0xf] << 24; + if (offset != 0) { + memset(bprm->buf, 0, BINPRM_BUF_SIZE); + retval = kernel_read(bprm->file, offset, bprm->buf, BINPRM_BUF_SIZE); + if (retval != BINPRM_BUF_SIZE) { + retval = -ELIBBAD; + goto out; + } + goto retry_interp; + } goto out_free_dentry; + } } else { /* Executables without an interpreter also need a personality */ SET_PERSONALITY(loc->elf_ex); @@ -1026,18 +1065,42 @@ static int load_elf_library(struct file unsigned long elf_bss, bss, len; int retval, error, i, j; struct elfhdr elf_ex; + unsigned int offset; error = -ENOEXEC; retval = kernel_read(file, 0, (char *)&elf_ex, sizeof(elf_ex)); if (retval != sizeof(elf_ex)) goto out; + offset = 0; +retry_lib: if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0) goto out; /* First of all, some simple consistency checks */ - if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || - !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap) + if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2) + goto out; +#if (defined(__x86_64__) || defined(__powerpc64__) || defined(__s390x__)) \ + && ELF_CLASS == ELFCLASS64 + if (personality(current->personality) == PER_LINUX32) + goto out; +#endif + if (!elf_check_arch(&elf_ex)) { + offset = elf_ex.e_ident[0xc] + | elf_ex.e_ident[0xd] << 8 + | elf_ex.e_ident[0xe] << 16 + | elf_ex.e_ident[0xf] << 24; + if (offset != 0) { + retval = kernel_read(file, offset, (char *)&elf_ex, sizeof(elf_ex)); + if (retval != sizeof(elf_ex)) { + retval = -ENOEXEC; + goto out; + } + goto retry_lib; + } + goto out; + } + if (!file->f_op || !file->f_op->mmap) goto out; /* Now read in all of the header information */