diff options
| author | Mark Johnston <markj@FreeBSD.org> | 2026-01-06 16:48:54 +0000 |
|---|---|---|
| committer | Mark Johnston <markj@FreeBSD.org> | 2026-01-06 20:54:10 +0000 |
| commit | 203e5a1eeec1153b0bcb230ccfb90531fa8cbeb5 (patch) | |
| tree | 20c8c848c9fe62505e1b4bc8e64f4198a11febbd | |
| parent | 8b210276cde207ca3dc1f7f46d5a6d32e0a1c51d (diff) | |
| -rw-r--r-- | sys/kern/link_elf.c | 46 | ||||
| -rw-r--r-- | sys/kern/link_elf_obj.c | 14 | ||||
| -rw-r--r-- | sys/vm/vm_kern.c | 8 |
3 files changed, 47 insertions, 21 deletions
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index ebd203858b66..45edd186e6ce 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -155,7 +155,7 @@ static int link_elf_search_symbol(linker_file_t, caddr_t, c_linker_sym_t *, long *); static void link_elf_unload_file(linker_file_t); -static void link_elf_unload_preload(linker_file_t); +static void link_elf_unload_preload(elf_file_t); static int link_elf_lookup_set(linker_file_t, const char *, void ***, void ***, int *); static int link_elf_each_function_name(linker_file_t, @@ -799,10 +799,10 @@ parse_vnet(elf_file_t ef) /* * Apply the specified protection to the loadable segments of a preloaded linker - * file. + * file. If "reset" is not set, the original segment protections are ORed in. */ static int -preload_protect(elf_file_t ef, vm_prot_t prot) +preload_protect1(elf_file_t ef, vm_prot_t prot, bool reset) { #if defined(__aarch64__) || defined(__amd64__) Elf_Ehdr *hdr; @@ -818,13 +818,16 @@ preload_protect(elf_file_t ef, vm_prot_t prot) if (phdr->p_type != PT_LOAD) continue; - nprot = prot | VM_PROT_READ; - if ((phdr->p_flags & PF_W) != 0) - nprot |= VM_PROT_WRITE; - if ((phdr->p_flags & PF_X) != 0) - nprot |= VM_PROT_EXECUTE; + nprot = VM_PROT_NONE; + if (!reset) { + nprot = VM_PROT_READ; + if ((phdr->p_flags & PF_W) != 0) + nprot |= VM_PROT_WRITE; + if ((phdr->p_flags & PF_X) != 0) + nprot |= VM_PROT_EXECUTE; + } error = pmap_change_prot((vm_offset_t)ef->address + - phdr->p_vaddr, round_page(phdr->p_memsz), nprot); + phdr->p_vaddr, round_page(phdr->p_memsz), prot | nprot); if (error != 0) break; } @@ -834,6 +837,18 @@ preload_protect(elf_file_t ef, vm_prot_t prot) #endif } +static int +preload_protect(elf_file_t ef, vm_prot_t prot) +{ + return (preload_protect1(ef, prot, false)); +} + +static int +preload_protect_reset(elf_file_t ef, vm_prot_t prot) +{ + return (preload_protect1(ef, prot, true)); +} + #ifdef __arm__ /* * Locate the ARM exception/unwind table info for DDB and stack(9) use by @@ -1396,7 +1411,7 @@ link_elf_unload_file(linker_file_t file) elf_cpu_unload_file(file); if (ef->preloaded) { - link_elf_unload_preload(file); + link_elf_unload_preload(ef); return; } @@ -1417,11 +1432,16 @@ link_elf_unload_file(linker_file_t file) } static void -link_elf_unload_preload(linker_file_t file) +link_elf_unload_preload(elf_file_t ef) { + /* + * Reset mapping protections to their original state. This affects the + * direct map alias of the module mapping as well. + */ + preload_protect_reset(ef, VM_PROT_RW); - if (file->pathname != NULL) - preload_delete_name(file->pathname); + if (ef->lf.pathname != NULL) + preload_delete_name(ef->lf.pathname); } static const char * diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index a3a53a39bfd6..4128baa5a909 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -1305,6 +1305,20 @@ link_elf_unload_file(linker_file_t file) vnet_data_free(ef->progtab[i].addr, ef->progtab[i].size); #endif + else if (ef->preloaded) { + vm_offset_t start, end; + + start = (vm_offset_t)ef->progtab[i].addr; + end = start + ef->progtab[i].size; + + /* + * Reset mapping protections to their original + * state. This affects the direct map alias of + * the module mapping as well. + */ + link_elf_protect_range(ef, trunc_page(start), + round_page(end), VM_PROT_RW); + } } } if (ef->preloaded) { diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index ac327aa37b72..626632b74add 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -953,14 +953,6 @@ kmem_bootstrap_free(vm_offset_t start, vm_size_t size) end = trunc_page(start + size); start = round_page(start); -#ifdef __amd64__ - /* - * Preloaded files do not have execute permissions by default on amd64. - * Restore the default permissions to ensure that the direct map alias - * is updated. - */ - pmap_change_prot(start, end - start, VM_PROT_RW); -#endif for (va = start; va < end; va += PAGE_SIZE) { pa = pmap_kextract(va); m = PHYS_TO_VM_PAGE(pa); |
