diff options
| author | mspector <mspector@google.com> | 2017-01-18 13:16:25 -0800 |
|---|---|---|
| committer | Mister Oyster <oysterized@gmail.com> | 2017-04-13 12:35:12 +0200 |
| commit | de7f7305a84663cc1683972454d248cd9fe33f48 (patch) | |
| tree | 9dcd138272071ed19da98973427d6d8af2e2330e /fs | |
| parent | a63710bc380142e9cd300ee1b55eeab53d7fe196 (diff) | |
| download | android_kernel_m2note-de7f7305a84663cc1683972454d248cd9fe33f48.tar.gz | |
ANDROID: Support to disable arm32 Kuser_Helpers
This patch adds support to disable kuser_helpers from being mapped into
32 bit processes on arm64. It also adds an ELF note that tells the
kernel to map the page in for the specific process.
Signed-off-by: mspector <mspector@google.com>
Bug: 33689037
Change-Id: I8d6d75cc8e1b2280f2436fd3334ff3779ae3539a
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/binfmt_elf.c | 107 |
1 files changed, 102 insertions, 5 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index c38dfe2c8..f10ffa577 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -567,6 +567,92 @@ static unsigned long randomize_stack_top(unsigned long stack_top) #endif } +#define ANDROID_NOTE_OWNER "Android" +#define ANDROID_KUSER_HELPER_TYPE 0x3L +#define ANDROID_KUSER_HELPER_ON 0x1L + +static int should_call_arch_setup_additional_pages(struct linux_binprm *bprm, + struct elfhdr *elf_ex, + struct elf_phdr *elf_ppnt) +{ + Elf64_Half i; + + /* We want to allow vdso, but not kuser_helpers */ + if (elf_ex->e_ident[EI_CLASS] == ELFCLASS64) + return true; + + for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) { + int retval; + void *elf_pnotes; + struct elf32_note *next_elf_notep; + Elf64_Xword left_to_read; + + if (elf_ppnt->p_type != PT_NOTE) + continue; + + /* + * This code is seeing if we have a special note. + * The note tells us that this binary still needs + * arch_setup_additional_pages to be called. + */ + if (elf_ppnt->p_filesz < sizeof(struct elf32_note)) + break; + + elf_pnotes = kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); + if (!elf_pnotes) + return -ENOMEM; + + retval = kernel_read(bprm->file, elf_ppnt->p_offset, + (char *)elf_pnotes, elf_ppnt->p_filesz); + if ((retval < 0) || + ((Elf64_Xword) retval != elf_ppnt->p_filesz)) { + kfree(elf_pnotes); + return retval; + } + + /* + * Now that we have read in all the notes and find ours + */ + next_elf_notep = (struct elf32_note *)elf_pnotes; + left_to_read = elf_ppnt->p_filesz; + while (left_to_read >= sizeof(struct elf32_note)) { + char *note_namep; + + left_to_read -= sizeof(struct elf32_note); + + /* Sanity check on the name and desc length*/ + if (((Elf64_Xword) next_elf_notep->n_namesz + + (Elf64_Xword) next_elf_notep->n_descsz) > + left_to_read) + break; + + note_namep = (char *)next_elf_notep + + sizeof(struct elf32_note); + left_to_read -= next_elf_notep->n_namesz; + left_to_read -= next_elf_notep->n_descsz; + + if ((sizeof(ANDROID_NOTE_OWNER) == + next_elf_notep->n_namesz) && + (next_elf_notep->n_type == + ANDROID_KUSER_HELPER_TYPE) && + strncmp(note_namep, ANDROID_NOTE_OWNER, + next_elf_notep->n_namesz) == 0) { + kfree(elf_pnotes); + return true; + } + + next_elf_notep = (struct elf32_note *) + (note_namep + + next_elf_notep->n_namesz + + next_elf_notep->n_descsz); + } + + kfree(elf_pnotes); + } + + return false; +} + static int load_elf_binary(struct linux_binprm *bprm) { struct file *interpreter = NULL; /* to shut gcc up */ @@ -940,18 +1026,29 @@ static int load_elf_binary(struct linux_binprm *bprm) } } - kfree(elf_phdata); - set_binfmt(&elf_format); #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES - retval = arch_setup_additional_pages(bprm, !!elf_interpreter); - if (retval < 0) { - send_sig(SIGKILL, current, 0); +#ifdef CONFIG_ARM64 + retval = should_call_arch_setup_additional_pages(bprm, &loc->elf_ex, + elf_phdata); + if (retval < 0) goto out; + + if (retval) { +#endif + retval = arch_setup_additional_pages(bprm, !!elf_interpreter); + if (retval < 0) { + send_sig(SIGKILL, current, 0); + goto out; + } +#ifdef CONFIG_ARM64 } +#endif #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ + kfree(elf_phdata); + install_exec_creds(bprm); retval = create_elf_tables(bprm, &loc->elf_ex, load_addr, interp_load_addr); |
