OSDN Git Service

jump_table: Move entries into ro_after_init region
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Wed, 19 Sep 2018 06:51:43 +0000 (23:51 -0700)
committerThomas Gleixner <tglx@linutronix.de>
Thu, 27 Sep 2018 15:56:49 +0000 (17:56 +0200)
The __jump_table sections emitted into the core kernel and into
each module consist of statically initialized references into
other parts of the code, and with the exception of entries that
point into init code, which are defused at post-init time, these
data structures are never modified.

So let's move them into the ro_after_init section, to prevent them
from being corrupted inadvertently by buggy code, or deliberately
by an attacker.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Kees Cook <keescook@chromium.org>
Acked-by: Jessica Yu <jeyu@kernel.org>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-s390@vger.kernel.org
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Link: https://lkml.kernel.org/r/20180919065144.25010-9-ard.biesheuvel@linaro.org
arch/s390/kernel/vmlinux.lds.S
include/asm-generic/vmlinux.lds.h
kernel/module.c

index b43f8d3..4042bbf 100644 (file)
@@ -66,6 +66,7 @@ SECTIONS
                 *(.data..ro_after_init)
        }
        EXCEPTION_TABLE(16)
+       JUMP_TABLE_DATA
        . = ALIGN(PAGE_SIZE);
        __end_ro_after_init = .;
 
index 7b75ff6..f09ee3c 100644 (file)
        STRUCT_ALIGN();                                                 \
        *(__tracepoints)                                                \
        /* implement dynamic printk debug */                            \
-       . = ALIGN(8);                                                   \
-       __start___jump_table = .;                                       \
-       KEEP(*(__jump_table))                                           \
-       __stop___jump_table = .;                                        \
        . = ALIGN(8);                                                   \
        __start___verbose = .;                                          \
        KEEP(*(__verbose))                                              \
        . = __start_init_task + THREAD_SIZE;                            \
        __end_init_task = .;
 
+#define JUMP_TABLE_DATA                                                        \
+       . = ALIGN(8);                                                   \
+       __start___jump_table = .;                                       \
+       KEEP(*(__jump_table))                                           \
+       __stop___jump_table = .;
+
 /*
  * Allow architectures to handle ro_after_init data on their
  * own by defining an empty RO_AFTER_INIT_DATA.
 #define RO_AFTER_INIT_DATA                                             \
        __start_ro_after_init = .;                                      \
        *(.data..ro_after_init)                                         \
+       JUMP_TABLE_DATA                                                 \
        __end_ro_after_init = .;
 #endif
 
index 6746c85..49a4058 100644 (file)
@@ -3317,6 +3317,15 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
        ndx = find_sec(info, ".data..ro_after_init");
        if (ndx)
                info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
+       /*
+        * Mark the __jump_table section as ro_after_init as well: these data
+        * structures are never modified, with the exception of entries that
+        * refer to code in the __init section, which are annotated as such
+        * at module load time.
+        */
+       ndx = find_sec(info, "__jump_table");
+       if (ndx)
+               info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT;
 
        /* Determine total sizes, and put offsets in sh_entsize.  For now
           this is done generically; there doesn't appear to be any