Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Split the data+bss+rodata segment in two data+bss and ro...



details:   https://anonhg.NetBSD.org/src/rev/8db055260cef
branches:  trunk
changeset: 816725:8db055260cef
user:      maxv <maxv%NetBSD.org@localhost>
date:      Wed Jul 20 13:36:19 2016 +0000

description:
Split the data+bss+rodata segment in two data+bss and rodata segments. The
latter is made read-only.

diffstat:

 sys/kern/subr_kobj.c     |  54 ++++++++++++++++++++++++++++++++++++++++++++++-
 sys/kern/subr_kobj_vfs.c |   8 +++++-
 sys/sys/kobj_impl.h      |   6 +++-
 3 files changed, 62 insertions(+), 6 deletions(-)

diffs (203 lines):

diff -r db46be58004a -r 8db055260cef sys/kern/subr_kobj.c
--- a/sys/kern/subr_kobj.c      Wed Jul 20 13:11:58 2016 +0000
+++ b/sys/kern/subr_kobj.c      Wed Jul 20 13:36:19 2016 +0000
@@ -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 @@
        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 @@
        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 @@
                        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 @@
                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 @@
        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 @@
                                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 @@
                    (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 @@
                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 @@
                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 @@
        /* 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 @@
                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;
        }
 
diff -r db46be58004a -r 8db055260cef sys/kern/subr_kobj_vfs.c
--- a/sys/kern/subr_kobj_vfs.c  Wed Jul 20 13:11:58 2016 +0000
+++ b/sys/kern/subr_kobj_vfs.c  Wed Jul 20 13:36:19 2016 +0000
@@ -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 @@
                    (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
diff -r db46be58004a -r 8db055260cef sys/sys/kobj_impl.h
--- a/sys/sys/kobj_impl.h       Wed Jul 20 13:11:58 2016 +0000
+++ b/sys/sys/kobj_impl.h       Wed Jul 20 13:36:19 2016 +0000
@@ -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 @@
        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 @@
        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 */



Home | Main Index | Thread Index | Old Index