From cefb93f253f423a66dbad74725b297cb05e95603 Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Fri, 23 Nov 2018 23:33:55 +0000 Subject: [PATCH] Parse FreeBSD Feature Control note on the ELF image activation. Sponsored by: The FreeBSD Foundation MFC after: 2 weeks --- sys/kern/imgact_elf.c | 59 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 4fb327539ec0..60722e55cf8c 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -88,7 +88,7 @@ __FBSDID("$FreeBSD$"); static int __elfN(check_header)(const Elf_Ehdr *hdr); static Elf_Brandinfo *__elfN(get_brandinfo)(struct image_params *imgp, - const char *interp, int interp_name_len, int32_t *osrel); + const char *interp, int interp_name_len, int32_t *osrel, uint32_t *fctl0); static int __elfN(load_file)(struct proc *p, const char *file, u_long *addr, u_long *entry, size_t pagesize); static int __elfN(load_section)(struct image_params *imgp, vm_ooffset_t offset, @@ -99,7 +99,7 @@ static bool __elfN(freebsd_trans_osrel)(const Elf_Note *note, int32_t *osrel); static bool kfreebsd_trans_osrel(const Elf_Note *note, int32_t *osrel); static boolean_t __elfN(check_note)(struct image_params *imgp, - Elf_Brandnote *checknote, int32_t *osrel); + Elf_Brandnote *checknote, int32_t *osrel, uint32_t *fctl0); static vm_prot_t __elfN(trans_prot)(Elf_Word); static Elf_Word __elfN(untrans_prot)(vm_prot_t); @@ -256,7 +256,7 @@ __elfN(brand_inuse)(Elf_Brandinfo *entry) static Elf_Brandinfo * __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, - int interp_name_len, int32_t *osrel) + int interp_name_len, int32_t *osrel, uint32_t *fctl0) { const Elf_Ehdr *hdr = (const Elf_Ehdr *)imgp->image_header; Elf_Brandinfo *bi, *bi_m; @@ -280,7 +280,8 @@ __elfN(get_brandinfo)(struct image_params *imgp, const char *interp, continue; if (hdr->e_machine == bi->machine && (bi->flags & (BI_BRAND_NOTE|BI_BRAND_NOTE_MANDATORY)) != 0) { - ret = __elfN(check_note)(imgp, bi->brand_note, osrel); + ret = __elfN(check_note)(imgp, bi->brand_note, osrel, + fctl0); /* Give brand a chance to veto check_note's guess */ if (ret && bi->header_supported) ret = bi->header_supported(imgp); @@ -789,6 +790,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) vm_prot_t prot; u_long text_size, data_size, total_size, text_addr, data_addr; u_long seg_size, seg_addr, addr, baddr, et_dyn_addr, entry, proghdr; + uint32_t fctl0; int32_t osrel; int error, i, n, interp_name_len, have_interp; @@ -824,6 +826,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) n = error = 0; baddr = 0; osrel = 0; + fctl0 = 0; text_size = data_size = total_size = text_addr = data_addr = 0; entry = proghdr = 0; interp_name_len = 0; @@ -889,7 +892,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) } brand_info = __elfN(get_brandinfo)(imgp, interp, interp_name_len, - &osrel); + &osrel, &fctl0); if (brand_info == NULL) { uprintf("ELF binary type \"%u\" not known.\n", hdr->e_ident[EI_OSABI]); @@ -1092,6 +1095,7 @@ __CONCAT(exec_, __elfN(imgact))(struct image_params *imgp) imgp->interpreted = 0; imgp->reloc_base = addr; imgp->proc->p_osrel = osrel; + imgp->proc->p_fctl0 = fctl0; imgp->proc->p_elf_machine = hdr->e_machine; imgp->proc->p_elf_flags = hdr->e_flags; @@ -2428,29 +2432,64 @@ brandnote_cb(const Elf_Note *note, void *arg0, boolean_t *res) return (TRUE); } +static Elf_Note fctl_note = { + .n_namesz = sizeof(FREEBSD_ABI_VENDOR), + .n_descsz = sizeof(uint32_t), + .n_type = NT_FREEBSD_FEATURE_CTL, +}; + +struct fctl_cb_arg { + uint32_t *fctl0; +}; + +static boolean_t +note_fctl_cb(const Elf_Note *note, void *arg0, boolean_t *res) +{ + struct fctl_cb_arg *arg; + const Elf32_Word *desc; + uintptr_t p; + + arg = arg0; + p = (uintptr_t)(note + 1); + p += roundup2(note->n_namesz, ELF_NOTE_ROUNDSIZE); + desc = (const Elf32_Word *)p; + *arg->fctl0 = desc[0]; + return (TRUE); +} + /* - * Try to find the appropriate ABI-note section for checknote, - * fetch the osreldate for binary from the ELF OSABI-note. Only the - * first page of the image is searched, the same as for headers. + * Try to find the appropriate ABI-note section for checknote, fetch + * the osreldate and feature control flags for binary from the ELF + * OSABI-note. Only the first page of the image is searched, the same + * as for headers. */ static boolean_t __elfN(check_note)(struct image_params *imgp, Elf_Brandnote *brandnote, - int32_t *osrel) + int32_t *osrel, uint32_t *fctl0) { const Elf_Phdr *phdr; const Elf_Ehdr *hdr; struct brandnote_cb_arg b_arg; - int i; + struct fctl_cb_arg f_arg; + int i, j; hdr = (const Elf_Ehdr *)imgp->image_header; phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff); b_arg.brandnote = brandnote; b_arg.osrel = osrel; + f_arg.fctl0 = fctl0; for (i = 0; i < hdr->e_phnum; i++) { if (phdr[i].p_type == PT_NOTE && __elfN(parse_notes)(imgp, &brandnote->hdr, brandnote->vendor, &phdr[i], brandnote_cb, &b_arg)) { + for (j = 0; j < hdr->e_phnum; j++) { + if (phdr[j].p_type == PT_NOTE && + __elfN(parse_notes)(imgp, &fctl_note, + FREEBSD_ABI_VENDOR, &phdr[j], + note_fctl_cb, &f_arg)) + break; + } return (TRUE); } }