Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 22 Jan 2015 18:40:36 +0000 (06:40 +1200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 22 Jan 2015 18:40:36 +0000 (06:40 +1200)
Pull module and param fixes from Rusty Russell:
 "Surprising number of fixes this merge window :(

  The first two are minor fallout from the param rework which went in
  this merge window.

  The next three are a series which fixes a longstanding (but never
  previously reported and unlikely , so no CC stable) race between
  kallsyms and freeing the init section.

  Finally, a minor cleanup as our module refcount will now be -1 during
  unload"

* tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
  module: make module_refcount() a signed integer.
  module: fix race in kallsyms resolution during module load success.
  module: remove mod arg from module_free, rename module_memfree().
  module_arch_freeing_init(): new hook for archs before module->module_init freed.
  param: fix uninitialized read with CONFIG_DEBUG_LOCK_ALLOC
  param: initialize store function to NULL if not available.

1  2 
kernel/debug/kdb/kdb_main.c

index f191bddf64b8ebdd0227556e119b1a804a30db88,2934889f2cce602c605a5c8040b14ba1a5af9361..7b40c5f07dce8d09e1ebaba547e401b5655befbb
@@@ -12,7 -12,6 +12,7 @@@
   */
  
  #include <linux/ctype.h>
 +#include <linux/types.h>
  #include <linux/string.h>
  #include <linux/kernel.h>
  #include <linux/kmsg_dump.h>
@@@ -24,7 -23,6 +24,7 @@@
  #include <linux/vmalloc.h>
  #include <linux/atomic.h>
  #include <linux/module.h>
 +#include <linux/moduleparam.h>
  #include <linux/mm.h>
  #include <linux/init.h>
  #include <linux/kallsyms.h>
  #include <linux/slab.h>
  #include "kdb_private.h"
  
 +#undef        MODULE_PARAM_PREFIX
 +#define       MODULE_PARAM_PREFIX "kdb."
 +
 +static int kdb_cmd_enabled = CONFIG_KDB_DEFAULT_ENABLE;
 +module_param_named(cmd_enable, kdb_cmd_enabled, int, 0600);
 +
  #define GREP_LEN 256
  char kdb_grep_string[GREP_LEN];
  int kdb_grepping_flag;
@@@ -129,7 -121,6 +129,7 @@@ static kdbmsg_t kdbmsgs[] = 
        KDBMSG(BADLENGTH, "Invalid length field"),
        KDBMSG(NOBP, "No Breakpoint exists"),
        KDBMSG(BADADDR, "Invalid address"),
 +      KDBMSG(NOPERM, "Permission denied"),
  };
  #undef KDBMSG
  
@@@ -196,26 -187,6 +196,26 @@@ struct task_struct *kdb_curr_task(int c
        return p;
  }
  
 +/*
 + * Check whether the flags of the current command and the permissions
 + * of the kdb console has allow a command to be run.
 + */
 +static inline bool kdb_check_flags(kdb_cmdflags_t flags, int permissions,
 +                                 bool no_args)
 +{
 +      /* permissions comes from userspace so needs massaging slightly */
 +      permissions &= KDB_ENABLE_MASK;
 +      permissions |= KDB_ENABLE_ALWAYS_SAFE;
 +
 +      /* some commands change group when launched with no arguments */
 +      if (no_args)
 +              permissions |= permissions << KDB_ENABLE_NO_ARGS_SHIFT;
 +
 +      flags |= KDB_ENABLE_ALL;
 +
 +      return permissions & flags;
 +}
 +
  /*
   * kdbgetenv - This function will return the character string value of
   *    an environment variable.
@@@ -504,15 -475,6 +504,15 @@@ int kdbgetaddrarg(int argc, const char 
        char *cp;
        kdb_symtab_t symtab;
  
 +      /*
 +       * If the enable flags prohibit both arbitrary memory access
 +       * and flow control then there are no reasonable grounds to
 +       * provide symbol lookup.
 +       */
 +      if (!kdb_check_flags(KDB_ENABLE_MEM_READ | KDB_ENABLE_FLOW_CTRL,
 +                           kdb_cmd_enabled, false))
 +              return KDB_NOPERM;
 +
        /*
         * Process arguments which follow the following syntax:
         *
@@@ -679,13 -641,8 +679,13 @@@ static int kdb_defcmd2(const char *cmds
                if (!s->count)
                        s->usable = 0;
                if (s->usable)
 -                      kdb_register(s->name, kdb_exec_defcmd,
 -                                   s->usage, s->help, 0);
 +                      /* macros are always safe because when executed each
 +                       * internal command re-enters kdb_parse() and is
 +                       * safety checked individually.
 +                       */
 +                      kdb_register_flags(s->name, kdb_exec_defcmd, s->usage,
 +                                         s->help, 0,
 +                                         KDB_ENABLE_ALWAYS_SAFE);
                return 0;
        }
        if (!s->usable)
@@@ -1046,22 -1003,25 +1046,22 @@@ int kdb_parse(const char *cmdstr
  
        if (i < kdb_max_commands) {
                int result;
 +
 +              if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1))
 +                      return KDB_NOPERM;
 +
                KDB_STATE_SET(CMD);
                result = (*tp->cmd_func)(argc-1, (const char **)argv);
                if (result && ignore_errors && result > KDB_CMD_GO)
                        result = 0;
                KDB_STATE_CLEAR(CMD);
 -              switch (tp->cmd_repeat) {
 -              case KDB_REPEAT_NONE:
 -                      argc = 0;
 -                      if (argv[0])
 -                              *(argv[0]) = '\0';
 -                      break;
 -              case KDB_REPEAT_NO_ARGS:
 -                      argc = 1;
 -                      if (argv[1])
 -                              *(argv[1]) = '\0';
 -                      break;
 -              case KDB_REPEAT_WITH_ARGS:
 -                      break;
 -              }
 +
 +              if (tp->cmd_flags & KDB_REPEAT_WITH_ARGS)
 +                      return result;
 +
 +              argc = tp->cmd_flags & KDB_REPEAT_NO_ARGS ? 1 : 0;
 +              if (argv[argc])
 +                      *(argv[argc]) = '\0';
                return result;
        }
  
@@@ -1961,14 -1921,10 +1961,14 @@@ static int kdb_rm(int argc, const char 
   */
  static int kdb_sr(int argc, const char **argv)
  {
 +      bool check_mask =
 +          !kdb_check_flags(KDB_ENABLE_ALL, kdb_cmd_enabled, false);
 +
        if (argc != 1)
                return KDB_ARGCOUNT;
 +
        kdb_trap_printk++;
 -      __handle_sysrq(*argv[1], false);
 +      __handle_sysrq(*argv[1], check_mask);
        kdb_trap_printk--;
  
        return 0;
@@@ -2023,7 -1979,7 +2023,7 @@@ static int kdb_lsmod(int argc, const ch
                kdb_printf("%-20s%8u  0x%p ", mod->name,
                           mod->core_size, (void *)mod);
  #ifdef CONFIG_MODULE_UNLOAD
-               kdb_printf("%4ld ", module_refcount(mod));
+               kdb_printf("%4d ", module_refcount(mod));
  #endif
                if (mod->state == MODULE_STATE_GOING)
                        kdb_printf(" (Unloading)");
@@@ -2201,8 -2157,6 +2201,8 @@@ static void kdb_cpu_status(void
        for (start_cpu = -1, i = 0; i < NR_CPUS; i++) {
                if (!cpu_online(i)) {
                        state = 'F';    /* cpu is offline */
 +              } else if (!kgdb_info[i].enter_kgdb) {
 +                      state = 'D';    /* cpu is online but unresponsive */
                } else {
                        state = ' ';    /* cpu is responding to kdb */
                        if (kdb_task_state_char(KDB_TSK(i)) == 'I')
@@@ -2256,7 -2210,7 +2256,7 @@@ static int kdb_cpu(int argc, const cha
        /*
         * Validate cpunum
         */
 -      if ((cpunum > NR_CPUS) || !cpu_online(cpunum))
 +      if ((cpunum > NR_CPUS) || !kgdb_info[cpunum].enter_kgdb)
                return KDB_BADCPUNUM;
  
        dbg_switch_cpu = cpunum;
@@@ -2421,8 -2375,6 +2421,8 @@@ static int kdb_help(int argc, const cha
                        return 0;
                if (!kt->cmd_name)
                        continue;
 +              if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true))
 +                      continue;
                if (strlen(kt->cmd_usage) > 20)
                        space = "\n                                    ";
                kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name,
@@@ -2677,7 -2629,7 +2677,7 @@@ static int kdb_grep_help(int argc, cons
  }
  
  /*
 - * kdb_register_repeat - This function is used to register a kernel
 + * kdb_register_flags - This function is used to register a kernel
   *    debugger command.
   * Inputs:
   *    cmd     Command name
   *    zero for success, one if a duplicate command.
   */
  #define kdb_command_extend 50 /* arbitrary */
 -int kdb_register_repeat(char *cmd,
 -                      kdb_func_t func,
 -                      char *usage,
 -                      char *help,
 -                      short minlen,
 -                      kdb_repeat_t repeat)
 +int kdb_register_flags(char *cmd,
 +                     kdb_func_t func,
 +                     char *usage,
 +                     char *help,
 +                     short minlen,
 +                     kdb_cmdflags_t flags)
  {
        int i;
        kdbtab_t *kp;
        kp->cmd_func   = func;
        kp->cmd_usage  = usage;
        kp->cmd_help   = help;
 -      kp->cmd_flags  = 0;
        kp->cmd_minlen = minlen;
 -      kp->cmd_repeat = repeat;
 +      kp->cmd_flags  = flags;
  
        return 0;
  }
 -EXPORT_SYMBOL_GPL(kdb_register_repeat);
 +EXPORT_SYMBOL_GPL(kdb_register_flags);
  
  
  /*
   * kdb_register - Compatibility register function for commands that do
   *    not need to specify a repeat state.  Equivalent to
 - *    kdb_register_repeat with KDB_REPEAT_NONE.
 + *    kdb_register_flags with flags set to 0.
   * Inputs:
   *    cmd     Command name
   *    func    Function to execute the command
@@@ -2768,7 -2721,8 +2768,7 @@@ int kdb_register(char *cmd
             char *help,
             short minlen)
  {
 -      return kdb_register_repeat(cmd, func, usage, help, minlen,
 -                                 KDB_REPEAT_NONE);
 +      return kdb_register_flags(cmd, func, usage, help, minlen, 0);
  }
  EXPORT_SYMBOL_GPL(kdb_register);
  
@@@ -2810,109 -2764,80 +2810,109 @@@ static void __init kdb_inittab(void
        for_each_kdbcmd(kp, i)
                kp->cmd_name = NULL;
  
 -      kdb_register_repeat("md", kdb_md, "<vaddr>",
 +      kdb_register_flags("md", kdb_md, "<vaddr>",
          "Display Memory Contents, also mdWcN, e.g. md8c1", 1,
 -                          KDB_REPEAT_NO_ARGS);
 -      kdb_register_repeat("mdr", kdb_md, "<vaddr> <bytes>",
 -        "Display Raw Memory", 0, KDB_REPEAT_NO_ARGS);
 -      kdb_register_repeat("mdp", kdb_md, "<paddr> <bytes>",
 -        "Display Physical Memory", 0, KDB_REPEAT_NO_ARGS);
 -      kdb_register_repeat("mds", kdb_md, "<vaddr>",
 -        "Display Memory Symbolically", 0, KDB_REPEAT_NO_ARGS);
 -      kdb_register_repeat("mm", kdb_mm, "<vaddr> <contents>",
 -        "Modify Memory Contents", 0, KDB_REPEAT_NO_ARGS);
 -      kdb_register_repeat("go", kdb_go, "[<vaddr>]",
 -        "Continue Execution", 1, KDB_REPEAT_NONE);
 -      kdb_register_repeat("rd", kdb_rd, "",
 -        "Display Registers", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("rm", kdb_rm, "<reg> <contents>",
 -        "Modify Registers", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("ef", kdb_ef, "<vaddr>",
 -        "Display exception frame", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("bt", kdb_bt, "[<vaddr>]",
 -        "Stack traceback", 1, KDB_REPEAT_NONE);
 -      kdb_register_repeat("btp", kdb_bt, "<pid>",
 -        "Display stack for process <pid>", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
 -        "Backtrace all processes matching state flag", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("btc", kdb_bt, "",
 -        "Backtrace current process on each cpu", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("btt", kdb_bt, "<vaddr>",
 +        KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
 +      kdb_register_flags("mdr", kdb_md, "<vaddr> <bytes>",
 +        "Display Raw Memory", 0,
 +        KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
 +      kdb_register_flags("mdp", kdb_md, "<paddr> <bytes>",
 +        "Display Physical Memory", 0,
 +        KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
 +      kdb_register_flags("mds", kdb_md, "<vaddr>",
 +        "Display Memory Symbolically", 0,
 +        KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS);
 +      kdb_register_flags("mm", kdb_mm, "<vaddr> <contents>",
 +        "Modify Memory Contents", 0,
 +        KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS);
 +      kdb_register_flags("go", kdb_go, "[<vaddr>]",
 +        "Continue Execution", 1,
 +        KDB_ENABLE_REG_WRITE | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
 +      kdb_register_flags("rd", kdb_rd, "",
 +        "Display Registers", 0,
 +        KDB_ENABLE_REG_READ);
 +      kdb_register_flags("rm", kdb_rm, "<reg> <contents>",
 +        "Modify Registers", 0,
 +        KDB_ENABLE_REG_WRITE);
 +      kdb_register_flags("ef", kdb_ef, "<vaddr>",
 +        "Display exception frame", 0,
 +        KDB_ENABLE_MEM_READ);
 +      kdb_register_flags("bt", kdb_bt, "[<vaddr>]",
 +        "Stack traceback", 1,
 +        KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
 +      kdb_register_flags("btp", kdb_bt, "<pid>",
 +        "Display stack for process <pid>", 0,
 +        KDB_ENABLE_INSPECT);
 +      kdb_register_flags("bta", kdb_bt, "[D|R|S|T|C|Z|E|U|I|M|A]",
 +        "Backtrace all processes matching state flag", 0,
 +        KDB_ENABLE_INSPECT);
 +      kdb_register_flags("btc", kdb_bt, "",
 +        "Backtrace current process on each cpu", 0,
 +        KDB_ENABLE_INSPECT);
 +      kdb_register_flags("btt", kdb_bt, "<vaddr>",
          "Backtrace process given its struct task address", 0,
 -                          KDB_REPEAT_NONE);
 -      kdb_register_repeat("env", kdb_env, "",
 -        "Show environment variables", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("set", kdb_set, "",
 -        "Set environment variables", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("help", kdb_help, "",
 -        "Display Help Message", 1, KDB_REPEAT_NONE);
 -      kdb_register_repeat("?", kdb_help, "",
 -        "Display Help Message", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("cpu", kdb_cpu, "<cpunum>",
 -        "Switch to new cpu", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("kgdb", kdb_kgdb, "",
 -        "Enter kgdb mode", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("ps", kdb_ps, "[<flags>|A]",
 -        "Display active task list", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("pid", kdb_pid, "<pidnum>",
 -        "Switch to another task", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("reboot", kdb_reboot, "",
 -        "Reboot the machine immediately", 0, KDB_REPEAT_NONE);
 +        KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS);
 +      kdb_register_flags("env", kdb_env, "",
 +        "Show environment variables", 0,
 +        KDB_ENABLE_ALWAYS_SAFE);
 +      kdb_register_flags("set", kdb_set, "",
 +        "Set environment variables", 0,
 +        KDB_ENABLE_ALWAYS_SAFE);
 +      kdb_register_flags("help", kdb_help, "",
 +        "Display Help Message", 1,
 +        KDB_ENABLE_ALWAYS_SAFE);
 +      kdb_register_flags("?", kdb_help, "",
 +        "Display Help Message", 0,
 +        KDB_ENABLE_ALWAYS_SAFE);
 +      kdb_register_flags("cpu", kdb_cpu, "<cpunum>",
 +        "Switch to new cpu", 0,
 +        KDB_ENABLE_ALWAYS_SAFE_NO_ARGS);
 +      kdb_register_flags("kgdb", kdb_kgdb, "",
 +        "Enter kgdb mode", 0, 0);
 +      kdb_register_flags("ps", kdb_ps, "[<flags>|A]",
 +        "Display active task list", 0,
 +        KDB_ENABLE_INSPECT);
 +      kdb_register_flags("pid", kdb_pid, "<pidnum>",
 +        "Switch to another task", 0,
 +        KDB_ENABLE_INSPECT);
 +      kdb_register_flags("reboot", kdb_reboot, "",
 +        "Reboot the machine immediately", 0,
 +        KDB_ENABLE_REBOOT);
  #if defined(CONFIG_MODULES)
 -      kdb_register_repeat("lsmod", kdb_lsmod, "",
 -        "List loaded kernel modules", 0, KDB_REPEAT_NONE);
 +      kdb_register_flags("lsmod", kdb_lsmod, "",
 +        "List loaded kernel modules", 0,
 +        KDB_ENABLE_INSPECT);
  #endif
  #if defined(CONFIG_MAGIC_SYSRQ)
 -      kdb_register_repeat("sr", kdb_sr, "<key>",
 -        "Magic SysRq key", 0, KDB_REPEAT_NONE);
 +      kdb_register_flags("sr", kdb_sr, "<key>",
 +        "Magic SysRq key", 0,
 +        KDB_ENABLE_ALWAYS_SAFE);
  #endif
  #if defined(CONFIG_PRINTK)
 -      kdb_register_repeat("dmesg", kdb_dmesg, "[lines]",
 -        "Display syslog buffer", 0, KDB_REPEAT_NONE);
 +      kdb_register_flags("dmesg", kdb_dmesg, "[lines]",
 +        "Display syslog buffer", 0,
 +        KDB_ENABLE_ALWAYS_SAFE);
  #endif
        if (arch_kgdb_ops.enable_nmi) {
 -              kdb_register_repeat("disable_nmi", kdb_disable_nmi, "",
 -                "Disable NMI entry to KDB", 0, KDB_REPEAT_NONE);
 -      }
 -      kdb_register_repeat("defcmd", kdb_defcmd, "name \"usage\" \"help\"",
 -        "Define a set of commands, down to endefcmd", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("kill", kdb_kill, "<-signal> <pid>",
 -        "Send a signal to a process", 0, KDB_REPEAT_NONE);
 -      kdb_register_repeat("summary", kdb_summary, "",
 -        "Summarize the system", 4, KDB_REPEAT_NONE);
 -      kdb_register_repeat("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
 -        "Display per_cpu variables", 3, KDB_REPEAT_NONE);
 -      kdb_register_repeat("grephelp", kdb_grep_help, "",
 -        "Display help on | grep", 0, KDB_REPEAT_NONE);
 +              kdb_register_flags("disable_nmi", kdb_disable_nmi, "",
 +                "Disable NMI entry to KDB", 0,
 +                KDB_ENABLE_ALWAYS_SAFE);
 +      }
 +      kdb_register_flags("defcmd", kdb_defcmd, "name \"usage\" \"help\"",
 +        "Define a set of commands, down to endefcmd", 0,
 +        KDB_ENABLE_ALWAYS_SAFE);
 +      kdb_register_flags("kill", kdb_kill, "<-signal> <pid>",
 +        "Send a signal to a process", 0,
 +        KDB_ENABLE_SIGNAL);
 +      kdb_register_flags("summary", kdb_summary, "",
 +        "Summarize the system", 4,
 +        KDB_ENABLE_ALWAYS_SAFE);
 +      kdb_register_flags("per_cpu", kdb_per_cpu, "<sym> [<bytes>] [<cpu>]",
 +        "Display per_cpu variables", 3,
 +        KDB_ENABLE_MEM_READ);
 +      kdb_register_flags("grephelp", kdb_grep_help, "",
 +        "Display help on | grep", 0,
 +        KDB_ENABLE_ALWAYS_SAFE);
  }
  
  /* Execute any commands defined in kdb_cmds.  */