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 */

Reply via email to