Merge tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Aug 2016 13:14:38 +0000 (09:14 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Aug 2016 13:14:38 +0000 (09:14 -0400)
Pull module updates from Rusty Russell:
 "The only interesting thing here is Jessica's patch to add
  ro_after_init support to modules.  The rest are all trivia"

* tag 'modules-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  extable.h: add stddef.h so "NULL" definition is not implicit
  modules: add ro_after_init support
  jump_label: disable preemption around __module_text_address().
  exceptions: fork exception table content from module.h into extable.h
  modules: Add kernel parameter to blacklist modules
  module: Do a WARN_ON_ONCE() for assert module mutex not held
  Documentation/module-signing.txt: Note need for version info if reusing a key
  module: Invalidate signatures on force-loaded modules
  module: Issue warnings when tainting kernel
  module: fix redundant test.
  module: fix noreturn attribute for __module_put_and_exit()

1  2 
Documentation/kernel-parameters.txt
kernel/jump_label.c
kernel/module.c

index 00e4c2f615a84de444cb1d1c4652b49edf94bc57,c59ae1af02b3dd7ed955a7bb4fc85b80b9eb7dbc..1a855d0c11fa7c07d7e69f9983f478aa26c850e6
@@@ -582,9 -582,6 +582,9 @@@ bytes respectively. Such letter suffixe
  
        bootmem_debug   [KNL] Enable bootmem allocator debug messages.
  
 +      bert_disable    [ACPI]
 +                      Disable BERT OS support on buggy BIOSes.
 +
        bttv.card=      [HW,V4L] bttv (bt848 + bt878 based grabber cards)
        bttv.radio=     Most important insmod options are available as
                        kernel args too.
        dhash_entries=  [KNL]
                        Set number of hash buckets for dentry cache.
  
 +      disable_1tb_segments [PPC]
 +                      Disables the use of 1TB hash page table segments. This
 +                      causes the kernel to fall back to 256MB segments which
 +                      can be useful when debugging issues that require an SLB
 +                      miss to occur.
 +
        disable=        [IPV6]
                        See Documentation/networking/ipv6.txt.
  
 +      disable_radix   [PPC]
 +                      Disable RADIX MMU mode on POWER9
 +
        disable_cpu_apicid= [X86,APIC,SMP]
                        Format: <int>
                        The number of initial APIC ID for the
                        Address Range Mirroring feature even if your box
                        doesn't support it.
  
 +      efivar_ssdt=    [EFI; X86] Name of an EFI variable that contains an SSDT
 +                      that is to be dynamically loaded by Linux. If there are
 +                      multiple variables with the same name but with different
 +                      vendor GUIDs, all of them will be loaded. See
 +                      Documentation/acpi/ssdt-overlays.txt for details.
 +
 +
        eisa_irq_edge=  [PARISC,HW]
                        See header of drivers/parisc/eisa.c.
  
                        Note that if CONFIG_MODULE_SIG_FORCE is set, that
                        is always true, so this option does nothing.
  
+       module_blacklist=  [KNL] Do not load a comma-separated list of
+                       modules.  Useful for debugging problem modules.
        mousedev.tap_time=
                        [MOUSE] Maximum time between finger touching and
                        leaving touchpad surface for touch to be considered
                resource_alignment=
                                Format:
                                [<order of align>@][<domain>:]<bus>:<slot>.<func>[; ...]
 +                              [<order of align>@]pci:<vendor>:<device>\
 +                                              [:<subvendor>:<subdevice>][; ...]
                                Specifies alignment and device to reassign
                                aligned memory resources.
                                If <order of align> is not specified,
                hpmemsize=nn[KMG]       The fixed amount of bus space which is
                                reserved for hotplug bridge's memory window.
                                Default size is 2 megabytes.
 +              hpbussize=nn    The minimum amount of additional bus numbers
 +                              reserved for buses below a hotplug bridge.
 +                              Default is 1.
                realloc=        Enable/disable reallocating PCI bridge resources
                                if allocations done by BIOS are too small to
                                accommodate resources required by all child
                compat  Treat PCIe ports as PCI-to-PCI bridges, disable the PCIe
                        ports driver.
  
 +      pcie_port_pm=   [PCIE] PCIe port power management handling:
 +              off     Disable power management of all PCIe ports
 +              force   Forcibly enable power management of all PCIe ports
 +
        pcie_pme=       [PCIE,PM] Native PCIe PME signaling options:
                nomsi   Do not use MSI for native PCIe PME signaling (this makes
                        all PCIe root ports use INTx for all services).
                        Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
                        default: disabled
  
 +      printk.devkmsg={on,off,ratelimit}
 +                      Control writing to /dev/kmsg.
 +                      on - unlimited logging to /dev/kmsg from userspace
 +                      off - logging to /dev/kmsg disabled
 +                      ratelimit - ratelimit the logging
 +                      Default: ratelimit
 +
        printk.time=    Show timing data prefixed to each printk message line
                        Format: <bool>  (1/Y/y=enable, 0/N/n=disable)
  
                                present during boot.
                nocompress      Don't compress/decompress hibernation images.
                no              Disable hibernation and resume.
 +              protect_image   Turn on image protection during restoration
 +                              (that will set all pages holding image data
 +                              during restoration read-only).
  
        retain_initrd   [RAM] Keep initrd memory after extraction
  
diff --combined kernel/jump_label.c
index f19aa02a8f48d5eca636ea906446fda5e0e6aee2,0eef93962a91b7a4518f3a36f4abd190db4a50f5..20400055f177cd9ab83748fd740a01036747df90
@@@ -14,7 -14,6 +14,7 @@@
  #include <linux/err.h>
  #include <linux/static_key.h>
  #include <linux/jump_label_ratelimit.h>
 +#include <linux/bug.h>
  
  #ifdef HAVE_JUMP_LABEL
  
@@@ -57,49 -56,6 +57,49 @@@ jump_label_sort_entries(struct jump_ent
  
  static void jump_label_update(struct static_key *key);
  
 +/*
 + * There are similar definitions for the !HAVE_JUMP_LABEL case in jump_label.h.
 + * The use of 'atomic_read()' requires atomic.h and its problematic for some
 + * kernel headers such as kernel.h and others. Since static_key_count() is not
 + * used in the branch statements as it is for the !HAVE_JUMP_LABEL case its ok
 + * to have it be a function here. Similarly, for 'static_key_enable()' and
 + * 'static_key_disable()', which require bug.h. This should allow jump_label.h
 + * to be included from most/all places for HAVE_JUMP_LABEL.
 + */
 +int static_key_count(struct static_key *key)
 +{
 +      /*
 +       * -1 means the first static_key_slow_inc() is in progress.
 +       *  static_key_enabled() must return true, so return 1 here.
 +       */
 +      int n = atomic_read(&key->enabled);
 +
 +      return n >= 0 ? n : 1;
 +}
 +EXPORT_SYMBOL_GPL(static_key_count);
 +
 +void static_key_enable(struct static_key *key)
 +{
 +      int count = static_key_count(key);
 +
 +      WARN_ON_ONCE(count < 0 || count > 1);
 +
 +      if (!count)
 +              static_key_slow_inc(key);
 +}
 +EXPORT_SYMBOL_GPL(static_key_enable);
 +
 +void static_key_disable(struct static_key *key)
 +{
 +      int count = static_key_count(key);
 +
 +      WARN_ON_ONCE(count < 0 || count > 1);
 +
 +      if (count)
 +              static_key_slow_dec(key);
 +}
 +EXPORT_SYMBOL_GPL(static_key_disable);
 +
  void static_key_slow_inc(struct static_key *key)
  {
        int v, v1;
@@@ -279,15 -235,6 +279,15 @@@ void __init jump_label_init(void
        struct static_key *key = NULL;
        struct jump_entry *iter;
  
 +      /*
 +       * Since we are initializing the static_key.enabled field with
 +       * with the 'raw' int values (to avoid pulling in atomic.h) in
 +       * jump_label.h, let's make sure that is safe. There are only two
 +       * cases to check since we initialize to 0 or 1.
 +       */
 +      BUILD_BUG_ON((int)ATOMIC_INIT(0) != 0);
 +      BUILD_BUG_ON((int)ATOMIC_INIT(1) != 1);
 +
        jump_label_lock();
        jump_label_sort_entries(iter_start, iter_stop);
  
@@@ -337,11 -284,14 +337,14 @@@ static int __jump_label_mod_text_reserv
  {
        struct module *mod;
  
+       preempt_disable();
        mod = __module_text_address((unsigned long)start);
+       WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
+       preempt_enable();
        if (!mod)
                return 0;
  
-       WARN_ON_ONCE(__module_text_address((unsigned long)end) != mod);
  
        return __jump_label_text_reserved(mod->jump_entries,
                                mod->jump_entries + mod->num_jump_entries,
diff --combined kernel/module.c
index a0f48b8b00da85330eb6e2b27cf1eb264c58adc5,205a71a97852e61d1494ceb3b79f558ada1dcf9b..529efae9f481e6e071d084735bd54ad5e024b153
@@@ -60,7 -60,6 +60,7 @@@
  #include <linux/jump_label.h>
  #include <linux/pfn.h>
  #include <linux/bsearch.h>
 +#include <linux/dynamic_debug.h>
  #include <uapi/linux/module.h>
  #include "module-internal.h"
  
@@@ -265,7 -264,7 +265,7 @@@ static void module_assert_mutex_or_pree
        if (unlikely(!debug_locks))
                return;
  
-       WARN_ON(!rcu_read_lock_sched_held() &&
+       WARN_ON_ONCE(!rcu_read_lock_sched_held() &&
                !lockdep_is_held(&module_mutex));
  #endif
  }
@@@ -337,7 -336,7 +337,7 @@@ static inline void add_taint_module(str
   * A thread that wants to hold a reference to a module only while it
   * is running can call this to safely exit.  nfsd and lockd use this.
   */
- void __module_put_and_exit(struct module *mod, long code)
+ void __noreturn __module_put_and_exit(struct module *mod, long code)
  {
        module_put(mod);
        do_exit(code);
@@@ -1694,8 -1693,7 +1694,7 @@@ static int module_add_modinfo_attrs(str
  
        temp_attr = mod->modinfo_attrs;
        for (i = 0; (attr = modinfo_attrs[i]) && !error; i++) {
-               if (!attr->test ||
-                   (attr->test && attr->test(mod))) {
+               if (!attr->test || attr->test(mod)) {
                        memcpy(temp_attr, attr, sizeof(*temp_attr));
                        sysfs_attr_init(&temp_attr->attr);
                        error = sysfs_create_file(&mod->mkobj.kobj,
@@@ -1859,10 -1857,11 +1858,11 @@@ static void mod_sysfs_teardown(struct m
   * from modification and any data from execution.
   *
   * General layout of module is:
-  *          [text] [read-only-data] [writable data]
-  * text_size -----^                ^               ^
-  * ro_size ------------------------|               |
-  * size -------------------------------------------|
+  *          [text] [read-only-data] [ro-after-init] [writable data]
+  * text_size -----^                ^               ^               ^
+  * ro_size ------------------------|               |               |
+  * ro_after_init_size -----------------------------|               |
+  * size -----------------------------------------------------------|
   *
   * These values are always page-aligned (as is base)
   */
@@@ -1885,14 -1884,24 +1885,24 @@@ static void frob_rodata(const struct mo
                   (layout->ro_size - layout->text_size) >> PAGE_SHIFT);
  }
  
+ static void frob_ro_after_init(const struct module_layout *layout,
+                               int (*set_memory)(unsigned long start, int num_pages))
+ {
+       BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
+       BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
+       BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
+       set_memory((unsigned long)layout->base + layout->ro_size,
+                  (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT);
+ }
  static void frob_writable_data(const struct module_layout *layout,
                               int (*set_memory)(unsigned long start, int num_pages))
  {
        BUG_ON((unsigned long)layout->base & (PAGE_SIZE-1));
-       BUG_ON((unsigned long)layout->ro_size & (PAGE_SIZE-1));
+       BUG_ON((unsigned long)layout->ro_after_init_size & (PAGE_SIZE-1));
        BUG_ON((unsigned long)layout->size & (PAGE_SIZE-1));
-       set_memory((unsigned long)layout->base + layout->ro_size,
-                  (layout->size - layout->ro_size) >> PAGE_SHIFT);
+       set_memory((unsigned long)layout->base + layout->ro_after_init_size,
+                  (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
  }
  
  /* livepatching wants to disable read-only so it can frob module. */
@@@ -1900,21 -1909,26 +1910,26 @@@ void module_disable_ro(const struct mod
  {
        frob_text(&mod->core_layout, set_memory_rw);
        frob_rodata(&mod->core_layout, set_memory_rw);
+       frob_ro_after_init(&mod->core_layout, set_memory_rw);
        frob_text(&mod->init_layout, set_memory_rw);
        frob_rodata(&mod->init_layout, set_memory_rw);
  }
  
- void module_enable_ro(const struct module *mod)
+ void module_enable_ro(const struct module *mod, bool after_init)
  {
        frob_text(&mod->core_layout, set_memory_ro);
        frob_rodata(&mod->core_layout, set_memory_ro);
        frob_text(&mod->init_layout, set_memory_ro);
        frob_rodata(&mod->init_layout, set_memory_ro);
+       if (after_init)
+               frob_ro_after_init(&mod->core_layout, set_memory_ro);
  }
  
  static void module_enable_nx(const struct module *mod)
  {
        frob_rodata(&mod->core_layout, set_memory_nx);
+       frob_ro_after_init(&mod->core_layout, set_memory_nx);
        frob_writable_data(&mod->core_layout, set_memory_nx);
        frob_rodata(&mod->init_layout, set_memory_nx);
        frob_writable_data(&mod->init_layout, set_memory_nx);
  static void module_disable_nx(const struct module *mod)
  {
        frob_rodata(&mod->core_layout, set_memory_x);
+       frob_ro_after_init(&mod->core_layout, set_memory_x);
        frob_writable_data(&mod->core_layout, set_memory_x);
        frob_rodata(&mod->init_layout, set_memory_x);
        frob_writable_data(&mod->init_layout, set_memory_x);
@@@ -1965,6 -1980,8 +1981,8 @@@ static void disable_ro_nx(const struct 
        frob_text(layout, set_memory_rw);
        frob_rodata(layout, set_memory_rw);
        frob_rodata(layout, set_memory_x);
+       frob_ro_after_init(layout, set_memory_rw);
+       frob_ro_after_init(layout, set_memory_x);
        frob_writable_data(layout, set_memory_x);
  }
  
@@@ -2307,6 -2324,7 +2325,7 @@@ static void layout_sections(struct modu
                 * finder in the two loops below */
                { SHF_EXECINSTR | SHF_ALLOC, ARCH_SHF_SMALL },
                { SHF_ALLOC, SHF_WRITE | ARCH_SHF_SMALL },
+               { SHF_RO_AFTER_INIT | SHF_ALLOC, ARCH_SHF_SMALL },
                { SHF_WRITE | SHF_ALLOC, ARCH_SHF_SMALL },
                { ARCH_SHF_SMALL | SHF_ALLOC, 0 }
        };
                        mod->core_layout.size = debug_align(mod->core_layout.size);
                        mod->core_layout.ro_size = mod->core_layout.size;
                        break;
-               case 3: /* whole core */
+               case 2: /* RO after init */
+                       mod->core_layout.size = debug_align(mod->core_layout.size);
+                       mod->core_layout.ro_after_init_size = mod->core_layout.size;
+                       break;
+               case 4: /* whole core */
                        mod->core_layout.size = debug_align(mod->core_layout.size);
                        break;
                }
                        mod->init_layout.size = debug_align(mod->init_layout.size);
                        mod->init_layout.ro_size = mod->init_layout.size;
                        break;
-               case 3: /* whole init */
+               case 2:
+                       /*
+                        * RO after init doesn't apply to init_layout (only
+                        * core_layout), so it just takes the value of ro_size.
+                        */
+                       mod->init_layout.ro_after_init_size = mod->init_layout.ro_size;
+                       break;
+               case 4: /* whole init */
                        mod->init_layout.size = debug_align(mod->init_layout.size);
                        break;
                }
@@@ -2688,13 -2717,18 +2718,18 @@@ static inline void kmemleak_load_module
  #endif
  
  #ifdef CONFIG_MODULE_SIG
- static int module_sig_check(struct load_info *info)
+ static int module_sig_check(struct load_info *info, int flags)
  {
        int err = -ENOKEY;
        const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
        const void *mod = info->hdr;
  
-       if (info->len > markerlen &&
+       /*
+        * Require flags == 0, as a module with version information
+        * removed is no longer the module that was signed
+        */
+       if (flags == 0 &&
+           info->len > markerlen &&
            memcmp(mod + info->len - markerlen, MODULE_SIG_STRING, markerlen) == 0) {
                /* We truncate the module to discard the signature */
                info->len -= markerlen;
        return err;
  }
  #else /* !CONFIG_MODULE_SIG */
- static int module_sig_check(struct load_info *info)
+ static int module_sig_check(struct load_info *info, int flags)
  {
        return 0;
  }
@@@ -2921,8 -2955,12 +2956,12 @@@ static int check_modinfo(struct module 
                return -ENOEXEC;
        }
  
-       if (!get_modinfo(info, "intree"))
+       if (!get_modinfo(info, "intree")) {
+               if (!test_taint(TAINT_OOT_MODULE))
+                       pr_warn("%s: loading out-of-tree module taints kernel.\n",
+                               mod->name);
                add_taint_module(mod, TAINT_OOT_MODULE, LOCKDEP_STILL_OK);
+       }
  
        if (get_modinfo(info, "staging")) {
                add_taint_module(mod, TAINT_CRAP, LOCKDEP_STILL_OK);
@@@ -3091,6 -3129,8 +3130,8 @@@ static int move_module(struct module *m
  
  static int check_module_license_and_versions(struct module *mod)
  {
+       int prev_taint = test_taint(TAINT_PROPRIETARY_MODULE);
        /*
         * ndiswrapper is under GPL by itself, but loads proprietary modules.
         * Don't use add_taint_module(), as it would prevent ndiswrapper from
                add_taint_module(mod, TAINT_PROPRIETARY_MODULE,
                                 LOCKDEP_NOW_UNRELIABLE);
  
+       if (!prev_taint && test_taint(TAINT_PROPRIETARY_MODULE))
+               pr_warn("%s: module license taints kernel.\n", mod->name);
  #ifdef CONFIG_MODVERSIONS
        if ((mod->num_syms && !mod->crcs)
            || (mod->num_gpl_syms && !mod->gpl_crcs)
@@@ -3156,16 -3199,41 +3200,41 @@@ int __weak module_frob_arch_sections(El
        return 0;
  }
  
+ /* module_blacklist is a comma-separated list of module names */
+ static char *module_blacklist;
+ static bool blacklisted(char *module_name)
+ {
+       const char *p;
+       size_t len;
+       if (!module_blacklist)
+               return false;
+       for (p = module_blacklist; *p; p += len) {
+               len = strcspn(p, ",");
+               if (strlen(module_name) == len && !memcmp(module_name, p, len))
+                       return true;
+               if (p[len] == ',')
+                       len++;
+       }
+       return false;
+ }
+ core_param(module_blacklist, module_blacklist, charp, 0400);
  static struct module *layout_and_allocate(struct load_info *info, int flags)
  {
        /* Module within temporary copy. */
        struct module *mod;
+       unsigned int ndx;
        int err;
  
        mod = setup_load_info(info, flags);
        if (IS_ERR(mod))
                return mod;
  
+       if (blacklisted(mod->name))
+               return ERR_PTR(-EPERM);
        err = check_modinfo(mod, info, flags);
        if (err)
                return ERR_PTR(err);
        /* We will do a special allocation for per-cpu sections later. */
        info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC;
  
+       /*
+        * Mark ro_after_init section with SHF_RO_AFTER_INIT so that
+        * layout_sections() can put it in the right place.
+        * Note: ro_after_init sections also have SHF_{WRITE,ALLOC} set.
+        */
+       ndx = find_sec(info, ".data..ro_after_init");
+       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
           special cases for the architectures. */
@@@ -3345,12 -3422,14 +3423,14 @@@ static noinline int do_init_module(stru
        /* Switch to core kallsyms now init is done: kallsyms may be walking! */
        rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
  #endif
+       module_enable_ro(mod, true);
        mod_tree_remove_init(mod);
        disable_ro_nx(&mod->init_layout);
        module_arch_freeing_init(mod);
        mod->init_layout.base = NULL;
        mod->init_layout.size = 0;
        mod->init_layout.ro_size = 0;
+       mod->init_layout.ro_after_init_size = 0;
        mod->init_layout.text_size = 0;
        /*
         * We want to free module_init, but be aware that kallsyms may be
@@@ -3442,8 -3521,7 +3522,7 @@@ static int complete_formation(struct mo
        /* This relies on module_mutex for list integrity. */
        module_bug_finalize(info->hdr, info->sechdrs, mod);
  
-       /* Set RO and NX regions */
-       module_enable_ro(mod);
+       module_enable_ro(mod, false);
        module_enable_nx(mod);
  
        /* Mark state as coming so strong_try_module_get() ignores us,
@@@ -3499,7 -3577,7 +3578,7 @@@ static int load_module(struct load_inf
        long err;
        char *after_dashes;
  
-       err = module_sig_check(info);
+       err = module_sig_check(info, flags);
        if (err)
                goto free_copy;
  
This page took 0.039322 seconds and 5 git commands to generate.