Merge tag 'rodata-v4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Feb 2017 01:56:45 +0000 (17:56 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 22 Feb 2017 01:56:45 +0000 (17:56 -0800)
Pull rodata updates from Kees Cook:
 "This renames the (now inaccurate) DEBUG_RODATA and related
  SET_MODULE_RONX configs to the more sensible STRICT_KERNEL_RWX and
  STRICT_MODULE_RWX"

* tag 'rodata-v4.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  arch: Rename CONFIG_DEBUG_RODATA and CONFIG_DEBUG_MODULE_RONX
  arch: Move CONFIG_DEBUG_RODATA and CONFIG_SET_MODULE_RONX to be common

1  2 
arch/arm/Kconfig
arch/arm64/Kconfig
arch/x86/Kconfig
arch/x86/Kconfig.debug
include/linux/filter.h
include/linux/module.h
init/main.c
kernel/module.c

diff --combined arch/arm/Kconfig
index 186c4c214e0a756b4468b597d5680093408c28c3,8c88c8ad064bdc0ea43582d078c3742a6db7bb1d..8748353ed5e0e1160355c18e471125897e9b7fb8
@@@ -4,10 -4,14 +4,14 @@@ config AR
        select ARCH_CLOCKSOURCE_DATA
        select ARCH_HAS_DEVMEM_IS_ALLOWED
        select ARCH_HAS_ELF_RANDOMIZE
+       select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
+       select ARCH_HAS_STRICT_MODULE_RWX if MMU
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_HAS_GCOV_PROFILE_ALL
        select ARCH_MIGHT_HAVE_PC_PARPORT
+       select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
+       select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
        select ARCH_SUPPORTS_ATOMIC_RMW
        select ARCH_USE_BUILTIN_BSWAP
        select ARCH_USE_CMPXCHG_LOCKREF
@@@ -1502,7 -1506,8 +1506,7 @@@ source kernel/Kconfig.preemp
  
  config HZ_FIXED
        int
 -      default 200 if ARCH_EBSA110 || ARCH_S3C24XX || \
 -              ARCH_S5PV210 || ARCH_EXYNOS4
 +      default 200 if ARCH_EBSA110
        default 128 if SOC_AT91RM9200
        default 0
  
diff --combined arch/arm64/Kconfig
index f7dfd6d5865977fe23c156e47c3c5f49775362b6,e1efbcc9de32a779a637dee044a76244b4d38b30..3bebdaf1d00998e22e0194c8dd6cde24099c91a8
@@@ -13,6 -13,8 +13,8 @@@ config ARM6
        select ARCH_HAS_GIGANTIC_PAGE
        select ARCH_HAS_KCOV
        select ARCH_HAS_SG_CHAIN
+       select ARCH_HAS_STRICT_KERNEL_RWX
+       select ARCH_HAS_STRICT_MODULE_RWX
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_USE_CMPXCHG_LOCKREF
        select ARCH_SUPPORTS_ATOMIC_RMW
@@@ -96,7 -98,7 +98,7 @@@
        select HAVE_RCU_TABLE_FREE
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_KPROBES
 -      select HAVE_KRETPROBES if HAVE_KPROBES
 +      select HAVE_KRETPROBES
        select IOMMU_DMA if IOMMU_SUPPORT
        select IRQ_DOMAIN
        select IRQ_FORCED_THREADING
@@@ -123,9 -125,6 +125,6 @@@ config ARCH_PHYS_ADDR_T_64BI
  config MMU
        def_bool y
  
- config DEBUG_RODATA
-       def_bool y
  config ARM64_PAGE_SHIFT
        int
        default 16 if ARM64_64K_PAGES
diff --combined arch/x86/Kconfig
index f8fbfc5a98babdc2208932970e8a98099b577950,13e1bf4b0fe5cd4dbb6e2da93b9034b628399994..4ca8c41623f40112c4dcc483a9078f896cc8a273
@@@ -54,6 -54,8 +54,8 @@@ config X8
        select ARCH_HAS_MMIO_FLUSH
        select ARCH_HAS_PMEM_API                if X86_64
        select ARCH_HAS_SG_CHAIN
+       select ARCH_HAS_STRICT_KERNEL_RWX
+       select ARCH_HAS_STRICT_MODULE_RWX
        select ARCH_HAS_UBSAN_SANITIZE_ALL
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select ARCH_MIGHT_HAVE_ACPI_PDC         if ACPI
@@@ -309,9 -311,6 +311,6 @@@ config ARCH_SUPPORTS_UPROBE
  config FIX_EARLYCON_MEM
        def_bool y
  
- config DEBUG_RODATA
-       def_bool y
  config PGTABLE_LEVELS
        int
        default 4 if X86_64
@@@ -1070,7 -1069,7 +1069,7 @@@ config X86_MCE_THRESHOL
        def_bool y
  
  config X86_MCE_INJECT
 -      depends on X86_MCE
 +      depends on X86_MCE && X86_LOCAL_APIC
        tristate "Machine check injector support"
        ---help---
          Provide support for injecting machine checks for testing purposes.
@@@ -1994,6 -1993,10 +1993,6 @@@ config RANDOMIZE_BAS
          theoretically possible, but the implementations are further
          limited due to memory layouts.
  
 -        If CONFIG_HIBERNATE is also enabled, KASLR is disabled at boot
 -        time. To enable it, boot with "kaslr" on the kernel command
 -        line (which will also disable hibernation).
 -
          If unsure, say N.
  
  # Relocation on x86 needs some additional build support
diff --combined arch/x86/Kconfig.debug
index 783099f2ac72bc45c7196f71f344c81728521d95,69cdd0b2176b54b1e1f5a7c03efa4e9f028b7b5a..c4cba00dbdee5ec48af1fff44adbe0f7e6582c26
@@@ -109,17 -109,14 +109,6 @@@ config DEBUG_W
  
          If in doubt, say "Y".
  
- config DEBUG_SET_MODULE_RONX
-       bool "Set loadable kernel module data as NX and text as RO"
-       depends on MODULES
 -config DEBUG_NX_TEST
 -      tristate "Testcase for the NX non-executable stack feature"
 -      depends on DEBUG_KERNEL && m
--      ---help---
-         This option helps catch unintended modifications to loadable
-         kernel module's text and read-only data. It also prevents execution
-         of module data. Such protection may interfere with run-time code
-         patching and dynamic kernel tracing - and they might also protect
-         against certain classes of kernel exploits.
-         If in doubt, say "N".
 -        This option enables a testcase for the CPU NX capability
 -        and the software setup of this feature.
 -        If in doubt, say "N"
--
  config DOUBLEFAULT
        default y
        bool "Enable doublefault exception handler" if EXPERT
diff --combined include/linux/filter.h
index e4eb2546339afbf2764f5ba335e1e66947fc5af3,c6dd53e8871119336c99ca2987777b77957ec88e..c2d282764d5de739555212814a86259606a77841
@@@ -57,8 -57,6 +57,8 @@@ struct bpf_prog_aux
  /* BPF program can access up to 512 bytes of stack space. */
  #define MAX_BPF_STACK 512
  
 +#define BPF_TAG_SIZE  8
 +
  /* Helper macros for filter block array initializers. */
  
  /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */
@@@ -410,7 -408,7 +410,7 @@@ struct bpf_prog 
        kmemcheck_bitfield_end(meta);
        enum bpf_prog_type      type;           /* Type of BPF program */
        u32                     len;            /* Number of filter blocks */
 -      u32                     digest[SHA_DIGEST_WORDS]; /* Program digest */
 +      u8                      tag[BPF_TAG_SIZE];
        struct bpf_prog_aux     *aux;           /* Auxiliary fields */
        struct sock_fprog_kern  *orig_prog;     /* Original BPF program */
        unsigned int            (*bpf_func)(const void *ctx,
@@@ -521,7 -519,7 +521,7 @@@ static inline u32 bpf_prog_insn_size(co
        return prog->len * sizeof(struct bpf_insn);
  }
  
 -static inline u32 bpf_prog_digest_scratch_size(const struct bpf_prog *prog)
 +static inline u32 bpf_prog_tag_scratch_size(const struct bpf_prog *prog)
  {
        return round_up(bpf_prog_insn_size(prog) +
                        sizeof(__be64) + 1, SHA_MESSAGE_BYTES);
@@@ -545,7 -543,7 +545,7 @@@ static inline bool bpf_prog_was_classic
  
  #define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))
  
- #ifdef CONFIG_DEBUG_SET_MODULE_RONX
+ #ifdef CONFIG_STRICT_MODULE_RWX
  static inline void bpf_prog_lock_ro(struct bpf_prog *fp)
  {
        set_memory_ro((unsigned long)fp, fp->pages);
@@@ -563,7 -561,7 +563,7 @@@ static inline void bpf_prog_lock_ro(str
  static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
  {
  }
- #endif /* CONFIG_DEBUG_SET_MODULE_RONX */
+ #endif /* CONFIG_STRICT_MODULE_RWX */
  
  int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
  static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
diff --combined include/linux/module.h
index 5cddadff2c25a2040c8610fa2ae4a47a33b1257e,d5afd142818f5da0d6f3c50b4fecbffefe0f2f74..f4f542ed3d9204c8f48a6fb9a1b5571bff8ed192
@@@ -18,6 -18,7 +18,6 @@@
  #include <linux/moduleparam.h>
  #include <linux/jump_label.h>
  #include <linux/export.h>
 -#include <linux/extable.h>    /* only as arch move module.h -> extable.h */
  #include <linux/rbtree_latch.h>
  
  #include <linux/percpu.h>
@@@ -345,7 -346,7 +345,7 @@@ struct module 
  
        /* Exported symbols */
        const struct kernel_symbol *syms;
 -      const unsigned long *crcs;
 +      const s32 *crcs;
        unsigned int num_syms;
  
        /* Kernel parameters. */
        /* GPL-only exported symbols. */
        unsigned int num_gpl_syms;
        const struct kernel_symbol *gpl_syms;
 -      const unsigned long *gpl_crcs;
 +      const s32 *gpl_crcs;
  
  #ifdef CONFIG_UNUSED_SYMBOLS
        /* unused exported symbols. */
        const struct kernel_symbol *unused_syms;
 -      const unsigned long *unused_crcs;
 +      const s32 *unused_crcs;
        unsigned int num_unused_syms;
  
        /* GPL-only, unused exported symbols. */
        unsigned int num_unused_gpl_syms;
        const struct kernel_symbol *unused_gpl_syms;
 -      const unsigned long *unused_gpl_crcs;
 +      const s32 *unused_gpl_crcs;
  #endif
  
  #ifdef CONFIG_MODULE_SIG
  
        /* symbols that will be GPL-only in the near future. */
        const struct kernel_symbol *gpl_future_syms;
 -      const unsigned long *gpl_future_crcs;
 +      const s32 *gpl_future_crcs;
        unsigned int num_gpl_future_syms;
  
        /* Exception table */
@@@ -522,7 -523,7 +522,7 @@@ struct module *find_module(const char *
  
  struct symsearch {
        const struct kernel_symbol *start, *stop;
 -      const unsigned long *crcs;
 +      const s32 *crcs;
        enum {
                NOT_GPL_ONLY,
                GPL_ONLY,
   */
  const struct kernel_symbol *find_symbol(const char *name,
                                        struct module **owner,
 -                                      const unsigned long **crc,
 +                                      const s32 **crc,
                                        bool gplok,
                                        bool warn);
  
@@@ -763,7 -764,7 +763,7 @@@ extern int module_sysfs_initialized
  
  #define __MODULE_STRING(x) __stringify(x)
  
- #ifdef CONFIG_DEBUG_SET_MODULE_RONX
+ #ifdef CONFIG_STRICT_MODULE_RWX
  extern void set_all_modules_text_rw(void);
  extern void set_all_modules_text_ro(void);
  extern void module_enable_ro(const struct module *mod, bool after_init);
diff --combined init/main.c
index 6d98664e843b0a4bb9d4d6ebdc71fd98797bff14,0b7bae29eef67c43100f294caac22b5de1818e89..c8a00f0f10ff692956afd0ce7651eb1919457c63
@@@ -12,7 -12,6 +12,7 @@@
  #define DEBUG         /* Enable initcall_debug */
  
  #include <linux/types.h>
 +#include <linux/extable.h>
  #include <linux/module.h>
  #include <linux/proc_fs.h>
  #include <linux/kernel.h>
@@@ -626,6 -625,7 +626,6 @@@ asmlinkage __visible void __init start_
        numa_policy_init();
        if (late_time_init)
                late_time_init();
 -      sched_clock_init();
        calibrate_delay();
        pidmap_init();
        anon_vma_init();
        sfi_init_late();
  
        if (efi_enabled(EFI_RUNTIME_SERVICES)) {
 -              efi_late_init();
                efi_free_boot_services();
        }
  
@@@ -924,7 -925,7 +924,7 @@@ static int try_to_run_init_process(cons
  
  static noinline void __init kernel_init_freeable(void);
  
- #if defined(CONFIG_DEBUG_RODATA) || defined(CONFIG_DEBUG_SET_MODULE_RONX)
+ #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX)
  bool rodata_enabled __ro_after_init = true;
  static int __init set_debug_rodata(char *str)
  {
  __setup("rodata=", set_debug_rodata);
  #endif
  
- #ifdef CONFIG_DEBUG_RODATA
+ #ifdef CONFIG_STRICT_KERNEL_RWX
  static void mark_readonly(void)
  {
        if (rodata_enabled)
diff --combined kernel/module.c
index 1a17ec0c8ae7889a34ffcf53cde513b3d0ebc2c5,e71478569273c316ee133f4524d2355675589f87..a3889169a3ae2e50091fcb019f41a9a43ce17a19
@@@ -17,7 -17,6 +17,7 @@@
      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
  #include <linux/export.h>
 +#include <linux/extable.h>
  #include <linux/moduleloader.h>
  #include <linux/trace_events.h>
  #include <linux/init.h>
@@@ -62,7 -61,6 +62,7 @@@
  #include <linux/pfn.h>
  #include <linux/bsearch.h>
  #include <linux/dynamic_debug.h>
 +#include <linux/audit.h>
  #include <uapi/linux/module.h>
  #include "module-internal.h"
  
@@@ -76,9 -74,9 +76,9 @@@
  /*
   * Modules' sections will be aligned on page boundaries
   * to ensure complete separation of code and data, but
-  * only when CONFIG_DEBUG_SET_MODULE_RONX=y
+  * only when CONFIG_STRICT_MODULE_RWX=y
   */
- #ifdef CONFIG_DEBUG_SET_MODULE_RONX
+ #ifdef CONFIG_STRICT_MODULE_RWX
  # define debug_align(X) ALIGN(X, PAGE_SIZE)
  #else
  # define debug_align(X) (X)
@@@ -391,16 -389,16 +391,16 @@@ extern const struct kernel_symbol __sta
  extern const struct kernel_symbol __stop___ksymtab_gpl[];
  extern const struct kernel_symbol __start___ksymtab_gpl_future[];
  extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
 -extern const unsigned long __start___kcrctab[];
 -extern const unsigned long __start___kcrctab_gpl[];
 -extern const unsigned long __start___kcrctab_gpl_future[];
 +extern const s32 __start___kcrctab[];
 +extern const s32 __start___kcrctab_gpl[];
 +extern const s32 __start___kcrctab_gpl_future[];
  #ifdef CONFIG_UNUSED_SYMBOLS
  extern const struct kernel_symbol __start___ksymtab_unused[];
  extern const struct kernel_symbol __stop___ksymtab_unused[];
  extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
  extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
 -extern const unsigned long __start___kcrctab_unused[];
 -extern const unsigned long __start___kcrctab_unused_gpl[];
 +extern const s32 __start___kcrctab_unused[];
 +extern const s32 __start___kcrctab_unused_gpl[];
  #endif
  
  #ifndef CONFIG_MODVERSIONS
@@@ -499,7 -497,7 +499,7 @@@ struct find_symbol_arg 
  
        /* Output */
        struct module *owner;
 -      const unsigned long *crc;
 +      const s32 *crc;
        const struct kernel_symbol *sym;
  };
  
@@@ -565,7 -563,7 +565,7 @@@ static bool find_symbol_in_section(cons
   * (optional) module which owns it.  Needs preempt disabled or module_mutex. */
  const struct kernel_symbol *find_symbol(const char *name,
                                        struct module **owner,
 -                                      const unsigned long **crc,
 +                                      const s32 **crc,
                                        bool gplok,
                                        bool warn)
  {
@@@ -1147,7 -1145,7 +1147,7 @@@ static size_t module_flags_taint(struc
  
        for (i = 0; i < TAINT_FLAGS_COUNT; i++) {
                if (taint_flags[i].module && test_bit(i, &mod->taints))
 -                      buf[l++] = taint_flags[i].true;
 +                      buf[l++] = taint_flags[i].c_true;
        }
  
        return l;
@@@ -1251,17 -1249,23 +1251,17 @@@ static int try_to_force_load(struct mod
  }
  
  #ifdef CONFIG_MODVERSIONS
 -/* If the arch applies (non-zero) relocations to kernel kcrctab, unapply it. */
 -static unsigned long maybe_relocated(unsigned long crc,
 -                                   const struct module *crc_owner)
 +
 +static u32 resolve_rel_crc(const s32 *crc)
  {
 -#ifdef ARCH_RELOCATES_KCRCTAB
 -      if (crc_owner == NULL)
 -              return crc - (unsigned long)reloc_start;
 -#endif
 -      return crc;
 +      return *(u32 *)((void *)crc + *crc);
  }
  
  static int check_version(Elf_Shdr *sechdrs,
                         unsigned int versindex,
                         const char *symname,
                         struct module *mod,
 -                       const unsigned long *crc,
 -                       const struct module *crc_owner)
 +                       const s32 *crc)
  {
        unsigned int i, num_versions;
        struct modversion_info *versions;
                / sizeof(struct modversion_info);
  
        for (i = 0; i < num_versions; i++) {
 +              u32 crcval;
 +
                if (strcmp(versions[i].name, symname) != 0)
                        continue;
  
 -              if (versions[i].crc == maybe_relocated(*crc, crc_owner))
 +              if (IS_ENABLED(CONFIG_MODULE_REL_CRCS))
 +                      crcval = resolve_rel_crc(crc);
 +              else
 +                      crcval = *crc;
 +              if (versions[i].crc == crcval)
                        return 1;
 -              pr_debug("Found checksum %lX vs module %lX\n",
 -                     maybe_relocated(*crc, crc_owner), versions[i].crc);
 +              pr_debug("Found checksum %X vs module %lX\n",
 +                       crcval, versions[i].crc);
                goto bad_version;
        }
  
@@@ -1309,7 -1307,7 +1309,7 @@@ static inline int check_modstruct_versi
                                          unsigned int versindex,
                                          struct module *mod)
  {
 -      const unsigned long *crc;
 +      const s32 *crc;
  
        /*
         * Since this should be found in kernel (which can't be removed), no
        }
        preempt_enable();
        return check_version(sechdrs, versindex,
 -                           VMLINUX_SYMBOL_STR(module_layout), mod, crc,
 -                           NULL);
 +                           VMLINUX_SYMBOL_STR(module_layout), mod, crc);
  }
  
  /* First part is kernel version, which we ignore if module has crcs. */
@@@ -1341,7 -1340,8 +1341,7 @@@ static inline int check_version(Elf_Shd
                                unsigned int versindex,
                                const char *symname,
                                struct module *mod,
 -                              const unsigned long *crc,
 -                              const struct module *crc_owner)
 +                              const s32 *crc)
  {
        return 1;
  }
@@@ -1368,7 -1368,7 +1368,7 @@@ static const struct kernel_symbol *reso
  {
        struct module *owner;
        const struct kernel_symbol *sym;
 -      const unsigned long *crc;
 +      const s32 *crc;
        int err;
  
        /*
        if (!sym)
                goto unlock;
  
 -      if (!check_version(info->sechdrs, info->index.vers, name, mod, crc,
 -                         owner)) {
 +      if (!check_version(info->sechdrs, info->index.vers, name, mod, crc)) {
                sym = ERR_PTR(-EINVAL);
                goto getname;
        }
@@@ -1846,7 -1847,7 +1846,7 @@@ static void mod_sysfs_teardown(struct m
        mod_sysfs_fini(mod);
  }
  
- #ifdef CONFIG_DEBUG_SET_MODULE_RONX
+ #ifdef CONFIG_STRICT_MODULE_RWX
  /*
   * LKM RO/NX protection: protect module's text/ro-data
   * from modification and any data from execution.
@@@ -3610,8 -3611,6 +3610,8 @@@ static int load_module(struct load_inf
                goto free_copy;
        }
  
 +      audit_log_kern_module(mod->name);
 +
        /* Reserve our place in the list. */
        err = add_unformed_module(mod);
        if (err)
                       mod->name, after_dashes);
        }
  
 -      /* Link in to syfs. */
 +      /* Link in to sysfs. */
        err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
        if (err < 0)
                goto coming_cleanup;