Module Name: src Committed By: maxv Date: Wed Jul 20 13:36:19 UTC 2016
Modified Files: src/sys/kern: subr_kobj.c subr_kobj_vfs.c src/sys/sys: kobj_impl.h Log Message: Split the data+bss+rodata segment in two data+bss and rodata segments. The latter is made read-only. To generate a diff of this commit: cvs rdiff -u -r1.56 -r1.57 src/sys/kern/subr_kobj.c cvs rdiff -u -r1.9 -r1.10 src/sys/kern/subr_kobj_vfs.c cvs rdiff -u -r1.4 -r1.5 src/sys/sys/kobj_impl.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/subr_kobj.c diff -u src/sys/kern/subr_kobj.c:1.56 src/sys/kern/subr_kobj.c:1.57 --- src/sys/kern/subr_kobj.c:1.56 Wed Jul 20 13:11:58 2016 +++ src/sys/kern/subr_kobj.c Wed Jul 20 13:36:19 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_kobj.c,v 1.56 2016/07/20 13:11:58 maxv Exp $ */ +/* $NetBSD: subr_kobj.c,v 1.57 2016/07/20 13:36:19 maxv Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -63,7 +63,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.56 2016/07/20 13:11:58 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_kobj.c,v 1.57 2016/07/20 13:36:19 maxv Exp $"); #ifdef _KERNEL_OPT #include "opt_modular.h" @@ -162,8 +162,10 @@ kobj_load(kobj_t ko) Elf_Sym *es; vaddr_t map_text_base; vaddr_t map_data_base; + vaddr_t map_rodata_base; size_t map_text_size; size_t map_data_size; + size_t map_rodata_size; int error; int symtabindex; int symstrindex; @@ -396,6 +398,7 @@ kobj_load(kobj_t ko) alignmask = 0; map_text_size = 0; map_data_size = 0; + map_rodata_size = 0; for (i = 0; i < hdr->e_shnum; i++) { if (shdr[i].sh_type != SHT_PROGBITS && shdr[i].sh_type != SHT_NOBITS) @@ -405,6 +408,10 @@ kobj_load(kobj_t ko) map_text_size += alignmask; map_text_size &= ~alignmask; map_text_size += shdr[i].sh_size; + } else if (!(shdr[i].sh_flags & SHF_WRITE)) { + map_rodata_size += alignmask; + map_rodata_size &= ~alignmask; + map_rodata_size += shdr[i].sh_size; } else { map_data_size += alignmask; map_data_size &= ~alignmask; @@ -422,6 +429,11 @@ kobj_load(kobj_t ko) error = ENOEXEC; goto out; } + if (map_rodata_size == 0) { + kobj_error(ko, "no rodata"); + error = ENOEXEC; + goto out; + } map_text_base = uvm_km_alloc(module_map, round_page(map_text_size), 0, UVM_KMF_WIRED | UVM_KMF_EXEC); @@ -443,6 +455,16 @@ kobj_load(kobj_t ko) ko->ko_data_address = map_data_base; ko->ko_data_size = map_data_size; + map_rodata_base = uvm_km_alloc(module_map, round_page(map_rodata_size), + 0, UVM_KMF_WIRED); + if (map_rodata_base == 0) { + kobj_error(ko, "out of memory"); + error = ENOMEM; + goto out; + } + ko->ko_rodata_address = map_rodata_base; + ko->ko_rodata_size = map_rodata_size; + /* * Now load code/data(progbits), zero bss(nobits), allocate space * for and load relocs @@ -461,6 +483,11 @@ kobj_load(kobj_t ko) map_text_base &= ~alignmask; addr = (void *)map_text_base; map_text_base += shdr[i].sh_size; + } else if (!(shdr[i].sh_flags & SHF_WRITE)) { + map_rodata_base += alignmask; + map_rodata_base &= ~alignmask; + addr = (void *)map_rodata_base; + map_rodata_base += shdr[i].sh_size; } else { map_data_base += alignmask; map_data_base &= ~alignmask; @@ -572,6 +599,13 @@ kobj_load(kobj_t ko) (long)ko->ko_data_address, (long)map_data_size, (long)ko->ko_data_address + map_data_size); } + if (map_rodata_base != ko->ko_rodata_address + map_rodata_size) { + panic("%s:%d: %s: map_rodata_base 0x%lx != address %lx " + "+ map_rodata_size %ld (0x%lx)\n", + __func__, __LINE__, ko->ko_name, (long)map_rodata_base, + (long)ko->ko_rodata_address, (long)map_rodata_size, + (long)ko->ko_rodata_address + map_rodata_size); + } /* * Perform local relocations only. Relocations relating to global @@ -620,6 +654,11 @@ kobj_unload(kobj_t ko) if (error != 0) kobj_error(ko, "machine dependent deinit failed (data) %d", error); + error = kobj_machdep(ko, (void *)ko->ko_rodata_address, + ko->ko_rodata_size, false); + if (error != 0) + kobj_error(ko, "machine dependent deinit failed (rodata) %d", + error); } if (ko->ko_text_address != 0) { uvm_km_free(module_map, ko->ko_text_address, @@ -629,6 +668,10 @@ kobj_unload(kobj_t ko) uvm_km_free(module_map, ko->ko_data_address, round_page(ko->ko_data_size), UVM_KMF_WIRED); } + if (ko->ko_rodata_address != 0) { + uvm_km_free(module_map, ko->ko_rodata_address, + round_page(ko->ko_rodata_size), UVM_KMF_WIRED); + } if (ko->ko_ksyms == true) { ksyms_modunload(ko->ko_name); } @@ -709,6 +752,8 @@ kobj_affix(kobj_t ko, const char *name) /* Change the memory protections, when needed. */ uvm_km_protect(module_map, ko->ko_text_address, ko->ko_text_size, VM_PROT_READ|VM_PROT_EXECUTE); + uvm_km_protect(module_map, ko->ko_rodata_address, ko->ko_rodata_size, + VM_PROT_READ); /* * Notify MD code that a module has been loaded. @@ -726,6 +771,11 @@ kobj_affix(kobj_t ko, const char *name) if (error != 0) kobj_error(ko, "machine dependent init failed (data) %d", error); + error = kobj_machdep(ko, (void *)ko->ko_rodata_address, + ko->ko_rodata_size, true); + if (error != 0) + kobj_error(ko, "machine dependent init failed (rodata) %d", + error); ko->ko_loaded = true; } Index: src/sys/kern/subr_kobj_vfs.c diff -u src/sys/kern/subr_kobj_vfs.c:1.9 src/sys/kern/subr_kobj_vfs.c:1.10 --- src/sys/kern/subr_kobj_vfs.c:1.9 Sat Jul 9 07:25:00 2016 +++ src/sys/kern/subr_kobj_vfs.c Wed Jul 20 13:36:19 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_kobj_vfs.c,v 1.9 2016/07/09 07:25:00 maxv Exp $ */ +/* $NetBSD: subr_kobj_vfs.c,v 1.10 2016/07/20 13:36:19 maxv Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -75,7 +75,7 @@ #include <sys/vnode.h> #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_kobj_vfs.c,v 1.9 2016/07/09 07:25:00 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_kobj_vfs.c,v 1.10 2016/07/20 13:36:19 maxv Exp $"); static void kobj_close_vfs(kobj_t ko) @@ -114,6 +114,10 @@ kobj_read_vfs(kobj_t ko, void **basep, s (uintptr_t)base + size <= (uintptr_t)ko->ko_data_address + ko->ko_data_size) ok = true; + if ((uintptr_t)base >= (uintptr_t)ko->ko_rodata_address && + (uintptr_t)base + size <= + (uintptr_t)ko->ko_rodata_address + ko->ko_rodata_size) + ok = true; if (!ok) panic("kobj_read_vfs: not in a dedicated segment"); #endif Index: src/sys/sys/kobj_impl.h diff -u src/sys/sys/kobj_impl.h:1.4 src/sys/sys/kobj_impl.h:1.5 --- src/sys/sys/kobj_impl.h:1.4 Sat Jul 9 07:25:00 2016 +++ src/sys/sys/kobj_impl.h Wed Jul 20 13:36:19 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: kobj_impl.h,v 1.4 2016/07/09 07:25:00 maxv Exp $ */ +/* $NetBSD: kobj_impl.h,v 1.5 2016/07/20 13:36:19 maxv Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -109,6 +109,7 @@ struct kobj { ssize_t ko_memsize; vaddr_t ko_text_address; /* Address of text segment */ vaddr_t ko_data_address; /* Address of data segment */ + vaddr_t ko_rodata_address; /* Address of rodata segment */ Elf_Shdr *ko_shdr; progent_t *ko_progtab; relaent_t *ko_relatab; @@ -117,7 +118,8 @@ struct kobj { char *ko_strtab; /* String table */ char *ko_shstrtab; /* Section name string table */ size_t ko_text_size; /* Size of text segment */ - size_t ko_data_size; /* Size of data/bss/rodata segment */ + size_t ko_data_size; /* Size of data/bss segment */ + size_t ko_rodata_size; /* Size of rodata segment */ size_t ko_symcnt; /* Number of symbols */ size_t ko_strtabsz; /* Number of bytes in string table */ size_t ko_shstrtabsz; /* Number of bytes in scn str table */