aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authormspector <mspector@google.com>2017-01-18 13:16:25 -0800
committerMister Oyster <oysterized@gmail.com>2017-04-13 12:35:12 +0200
commitde7f7305a84663cc1683972454d248cd9fe33f48 (patch)
tree9dcd138272071ed19da98973427d6d8af2e2330e /fs
parenta63710bc380142e9cd300ee1b55eeab53d7fe196 (diff)
downloadandroid_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.c107
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);