-/* $OpenBSD: exec_elf.c,v 1.172 2022/10/27 16:01:18 deraadt Exp $ */
+/* $OpenBSD: exec_elf.c,v 1.173 2022/10/27 22:48:17 deraadt Exp $ */
/*
* Copyright (c) 1996 Per Fogelstrom
* initially. The dynamic linker will make these read-only
* and add back X permission after relocation processing.
* Static executables with W|X segments will probably crash.
- * Apply immutability as much as possible, but not for RELRO
- * or PT_OPENBSD_MUTABLE sections, or LOADS marked
- * PF_OPENBSD_MUTABLE, or LOADS which violate W^X. Userland
- * (meaning crt0 or ld.so) will repair those regions.
*/
*prot |= (ph->p_flags & PF_R) ? PROT_READ : 0;
*prot |= (ph->p_flags & PF_W) ? PROT_WRITE : 0;
if ((ph->p_flags & PF_W) == 0)
*prot |= (ph->p_flags & PF_X) ? PROT_EXEC : 0;
+
+ /*
+ * Apply immutability as much as possible, but not text-segments
+ * of textrel binaries, or RELRO or PT_OPENBSD_MUTABLE sections,
+ * or LOADS marked PF_OPENBSD_MUTABLE, or LOADS which violate W^X.
+ * Userland (meaning crt0 or ld.so) will repair those regions.
+ */
if ((ph->p_flags & (PF_X | PF_W)) != (PF_X | PF_W) &&
- (ph->p_flags & PF_OPENBSD_MUTABLE) == 0)
+ ((ph->p_flags & PF_OPENBSD_MUTABLE) == 0) &&
+ ((flags & VMCMD_TEXTREL) == 0 && (ph->p_flags & PF_X) == 0))
flags |= VMCMD_IMMUTABLE;
msize = ph->p_memsz + diff;
Elf_Ehdr *eh = epp->ep_hdr;
Elf_Phdr *ph, *pp, *base_ph = NULL;
Elf_Addr phdr = 0, exe_base = 0;
- int error, i, has_phdr = 0, names = 0;
+ int error, i, has_phdr = 0, names = 0, textrel = 0;
char *interp = NULL;
u_long phsize;
size_t randomizequota = ELF_RANDOMIZE_LIMIT;
}
}
+ /*
+ * Verify this is an OpenBSD executable. If it's marked that way
+ * via a PT_NOTE then also check for a PT_OPENBSD_WXNEEDED segment.
+ */
+ if ((error = elf_os_pt_note(p, epp, epp->ep_hdr, &names)) != 0)
+ goto bad;
+ if (eh->e_ident[EI_OSABI] == ELFOSABI_OPENBSD)
+ names |= ELF_NOTE_NAME_OPENBSD;
+
if (eh->e_type == ET_DYN) {
/* need phdr and load sections for PIE */
if (!has_phdr || base_ph == NULL) {
}
/* randomize exe_base for PIE */
exe_base = uvm_map_pie(base_ph->p_align);
- }
- /*
- * Verify this is an OpenBSD executable. If it's marked that way
- * via a PT_NOTE then also check for a PT_OPENBSD_WXNEEDED segment.
- */
- if ((error = elf_os_pt_note(p, epp, epp->ep_hdr, &names)) != 0)
- goto bad;
- if (eh->e_ident[EI_OSABI] == ELFOSABI_OPENBSD)
- names |= ELF_NOTE_NAME_OPENBSD;
+ /*
+ * Check if DYNAMIC contains DT_TEXTREL
+ */
+ for (i = 0, pp = ph; i < eh->e_phnum; i++, pp++) {
+ Elf32_Dyn *dt;
+ int j;
+
+ switch (pp->p_type) {
+ case PT_DYNAMIC:
+ if (pp->p_filesz > 64*1024)
+ break;
+ dt = malloc(pp->p_filesz, M_TEMP, M_WAITOK);
+ error = vn_rdwr(UIO_READ, epp->ep_vp,
+ (caddr_t)dt, pp->p_filesz, pp->p_offset,
+ UIO_SYSSPACE, IO_UNIT, p->p_ucred, NULL, p);
+ if (error) {
+ free(dt, M_TEMP, pp->p_filesz);
+ break;
+ }
+ for (j = 0; j * sizeof(*dt) < pp->p_filesz; j++) {
+ if (dt[j].d_tag == DT_TEXTREL) {
+ textrel = VMCMD_TEXTREL;
+ break;
+ }
+ }
+ free(dt, M_TEMP, pp->p_filesz);
+ break;
+ default:
+ break;
+ }
+ }
+ }
/*
* Load all the necessary sections
* for DATA_PLT, is fine for TEXT_PLT.
*/
elf_load_psection(&epp->ep_vmcmds, epp->ep_vp,
- pp, &addr, &size, &prot, flags | syscall);
+ pp, &addr, &size, &prot, flags | textrel | syscall);
/*
* Update exe_base in case alignment was off.