Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Mar 2011 00:52:22 +0000 (17:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Mar 2011 00:52:22 +0000 (17:52 -0700)
* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  futex: Fix WARN_ON() test for UP
  WARN_ON_SMP(): Allow use in if() statements on UP
  x86, dumpstack: Use %pB format specifier for stack trace
  vsprintf: Introduce %pB format specifier
  lockdep: Remove unused 'factor' variable from lockdep_stats_show()

1  2 
arch/x86/kernel/dumpstack.c
kernel/futex.c
kernel/kallsyms.c
lib/vsprintf.c

@@@ -27,7 -27,7 +27,7 @@@ static int die_counter
  
  void printk_address(unsigned long address, int reliable)
  {
-       printk(" [<%p>] %s%pS\n", (void *) address,
+       printk(" [<%p>] %s%pB\n", (void *) address,
                        reliable ? "" : "? ", (void *) address);
  }
  
@@@ -322,6 -322,16 +322,6 @@@ void die(const char *str, struct pt_reg
        oops_end(flags, regs, sig);
  }
  
 -static int __init oops_setup(char *s)
 -{
 -      if (!s)
 -              return -EINVAL;
 -      if (!strcmp(s, "panic"))
 -              panic_on_oops = 1;
 -      return 0;
 -}
 -early_param("oops", oops_setup);
 -
  static int __init kstack_setup(char *s)
  {
        if (!s)
diff --combined kernel/futex.c
@@@ -782,8 -782,8 +782,8 @@@ static void __unqueue_futex(struct fute
  {
        struct futex_hash_bucket *hb;
  
-       if (WARN_ON(!q->lock_ptr || !spin_is_locked(q->lock_ptr)
-                       || plist_node_empty(&q->list)))
+       if (WARN_ON_SMP(!q->lock_ptr || !spin_is_locked(q->lock_ptr))
+           || WARN_ON(plist_node_empty(&q->list)))
                return;
  
        hb = container_of(q->lock_ptr, struct futex_hash_bucket, lock);
@@@ -2418,19 -2418,10 +2418,19 @@@ SYSCALL_DEFINE3(get_robust_list, int, p
                        goto err_unlock;
                ret = -EPERM;
                pcred = __task_cred(p);
 +              /* If victim is in different user_ns, then uids are not
 +                 comparable, so we must have CAP_SYS_PTRACE */
 +              if (cred->user->user_ns != pcred->user->user_ns) {
 +                      if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
 +                              goto err_unlock;
 +                      goto ok;
 +              }
 +              /* If victim is in same user_ns, then uids are comparable */
                if (cred->euid != pcred->euid &&
                    cred->euid != pcred->uid &&
 -                  !capable(CAP_SYS_PTRACE))
 +                  !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
                        goto err_unlock;
 +ok:
                head = p->robust_list;
                rcu_read_unlock();
        }
diff --combined kernel/kallsyms.c
@@@ -64,14 -64,14 +64,14 @@@ static inline int is_kernel_text(unsign
        if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) ||
            arch_is_kernel_text(addr))
                return 1;
 -      return in_gate_area_no_task(addr);
 +      return in_gate_area_no_mm(addr);
  }
  
  static inline int is_kernel(unsigned long addr)
  {
        if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
                return 1;
 -      return in_gate_area_no_task(addr);
 +      return in_gate_area_no_mm(addr);
  }
  
  static int is_ksym_addr(unsigned long addr)
@@@ -342,13 -342,15 +342,15 @@@ int lookup_symbol_attrs(unsigned long a
  }
  
  /* Look up a kernel symbol and return it in a text buffer. */
- int sprint_symbol(char *buffer, unsigned long address)
+ static int __sprint_symbol(char *buffer, unsigned long address,
+                          int symbol_offset)
  {
        char *modname;
        const char *name;
        unsigned long offset, size;
        int len;
  
+       address += symbol_offset;
        name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
        if (!name)
                return sprintf(buffer, "0x%lx", address);
                strcpy(buffer, name);
        len = strlen(buffer);
        buffer += len;
+       offset -= symbol_offset;
  
        if (modname)
-               len += sprintf(buffer, "+%#lx/%#lx [%s]",
-                                               offset, size, modname);
+               len += sprintf(buffer, "+%#lx/%#lx [%s]", offset, size, modname);
        else
                len += sprintf(buffer, "+%#lx/%#lx", offset, size);
  
        return len;
  }
+ /**
+  * sprint_symbol - Look up a kernel symbol and return it in a text buffer
+  * @buffer: buffer to be stored
+  * @address: address to lookup
+  *
+  * This function looks up a kernel symbol with @address and stores its name,
+  * offset, size and module name to @buffer if possible. If no symbol was found,
+  * just saves its @address as is.
+  *
+  * This function returns the number of bytes stored in @buffer.
+  */
+ int sprint_symbol(char *buffer, unsigned long address)
+ {
+       return __sprint_symbol(buffer, address, 0);
+ }
  EXPORT_SYMBOL_GPL(sprint_symbol);
  
+ /**
+  * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
+  * @buffer: buffer to be stored
+  * @address: address to lookup
+  *
+  * This function is for stack backtrace and does the same thing as
+  * sprint_symbol() but with modified/decreased @address. If there is a
+  * tail-call to the function marked "noreturn", gcc optimized out code after
+  * the call so that the stack-saved return address could point outside of the
+  * caller. This function ensures that kallsyms will find the original caller
+  * by decreasing @address.
+  *
+  * This function returns the number of bytes stored in @buffer.
+  */
+ int sprint_backtrace(char *buffer, unsigned long address)
+ {
+       return __sprint_symbol(buffer, address, -1);
+ }
  /* Look up a kernel symbol and print it to the kernel messages. */
  void __print_symbol(const char *fmt, unsigned long address)
  {
@@@ -477,11 -515,13 +515,11 @@@ static int s_show(struct seq_file *m, v
                 */
                type = iter->exported ? toupper(iter->type) :
                                        tolower(iter->type);
 -              seq_printf(m, "%0*lx %c %s\t[%s]\n",
 -                         (int)(2 * sizeof(void *)),
 -                         iter->value, type, iter->name, iter->module_name);
 +              seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
 +                         type, iter->name, iter->module_name);
        } else
 -              seq_printf(m, "%0*lx %c %s\n",
 -                         (int)(2 * sizeof(void *)),
 -                         iter->value, iter->type, iter->name);
 +              seq_printf(m, "%pK %c %s\n", (void *)iter->value,
 +                         iter->type, iter->name);
        return 0;
  }
  
diff --combined lib/vsprintf.c
@@@ -120,6 -120,147 +120,6 @@@ long long simple_strtoll(const char *cp
  }
  EXPORT_SYMBOL(simple_strtoll);
  
 -/**
 - * strict_strtoul - convert a string to an unsigned long strictly
 - * @cp: The string to be converted
 - * @base: The number base to use
 - * @res: The converted result value
 - *
 - * strict_strtoul converts a string to an unsigned long only if the
 - * string is really an unsigned long string, any string containing
 - * any invalid char at the tail will be rejected and -EINVAL is returned,
 - * only a newline char at the tail is acceptible because people generally
 - * change a module parameter in the following way:
 - *
 - *    echo 1024 > /sys/module/e1000/parameters/copybreak
 - *
 - * echo will append a newline to the tail.
 - *
 - * It returns 0 if conversion is successful and *res is set to the converted
 - * value, otherwise it returns -EINVAL and *res is set to 0.
 - *
 - * simple_strtoul just ignores the successive invalid characters and
 - * return the converted value of prefix part of the string.
 - */
 -int strict_strtoul(const char *cp, unsigned int base, unsigned long *res)
 -{
 -      char *tail;
 -      unsigned long val;
 -
 -      *res = 0;
 -      if (!*cp)
 -              return -EINVAL;
 -
 -      val = simple_strtoul(cp, &tail, base);
 -      if (tail == cp)
 -              return -EINVAL;
 -
 -      if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) {
 -              *res = val;
 -              return 0;
 -      }
 -
 -      return -EINVAL;
 -}
 -EXPORT_SYMBOL(strict_strtoul);
 -
 -/**
 - * strict_strtol - convert a string to a long strictly
 - * @cp: The string to be converted
 - * @base: The number base to use
 - * @res: The converted result value
 - *
 - * strict_strtol is similiar to strict_strtoul, but it allows the first
 - * character of a string is '-'.
 - *
 - * It returns 0 if conversion is successful and *res is set to the converted
 - * value, otherwise it returns -EINVAL and *res is set to 0.
 - */
 -int strict_strtol(const char *cp, unsigned int base, long *res)
 -{
 -      int ret;
 -      if (*cp == '-') {
 -              ret = strict_strtoul(cp + 1, base, (unsigned long *)res);
 -              if (!ret)
 -                      *res = -(*res);
 -      } else {
 -              ret = strict_strtoul(cp, base, (unsigned long *)res);
 -      }
 -
 -      return ret;
 -}
 -EXPORT_SYMBOL(strict_strtol);
 -
 -/**
 - * strict_strtoull - convert a string to an unsigned long long strictly
 - * @cp: The string to be converted
 - * @base: The number base to use
 - * @res: The converted result value
 - *
 - * strict_strtoull converts a string to an unsigned long long only if the
 - * string is really an unsigned long long string, any string containing
 - * any invalid char at the tail will be rejected and -EINVAL is returned,
 - * only a newline char at the tail is acceptible because people generally
 - * change a module parameter in the following way:
 - *
 - *    echo 1024 > /sys/module/e1000/parameters/copybreak
 - *
 - * echo will append a newline to the tail of the string.
 - *
 - * It returns 0 if conversion is successful and *res is set to the converted
 - * value, otherwise it returns -EINVAL and *res is set to 0.
 - *
 - * simple_strtoull just ignores the successive invalid characters and
 - * return the converted value of prefix part of the string.
 - */
 -int strict_strtoull(const char *cp, unsigned int base, unsigned long long *res)
 -{
 -      char *tail;
 -      unsigned long long val;
 -
 -      *res = 0;
 -      if (!*cp)
 -              return -EINVAL;
 -
 -      val = simple_strtoull(cp, &tail, base);
 -      if (tail == cp)
 -              return -EINVAL;
 -      if ((tail[0] == '\0') || (tail[0] == '\n' && tail[1] == '\0')) {
 -              *res = val;
 -              return 0;
 -      }
 -
 -      return -EINVAL;
 -}
 -EXPORT_SYMBOL(strict_strtoull);
 -
 -/**
 - * strict_strtoll - convert a string to a long long strictly
 - * @cp: The string to be converted
 - * @base: The number base to use
 - * @res: The converted result value
 - *
 - * strict_strtoll is similiar to strict_strtoull, but it allows the first
 - * character of a string is '-'.
 - *
 - * It returns 0 if conversion is successful and *res is set to the converted
 - * value, otherwise it returns -EINVAL and *res is set to 0.
 - */
 -int strict_strtoll(const char *cp, unsigned int base, long long *res)
 -{
 -      int ret;
 -      if (*cp == '-') {
 -              ret = strict_strtoull(cp + 1, base, (unsigned long long *)res);
 -              if (!ret)
 -                      *res = -(*res);
 -      } else {
 -              ret = strict_strtoull(cp, base, (unsigned long long *)res);
 -      }
 -
 -      return ret;
 -}
 -EXPORT_SYMBOL(strict_strtoll);
 -
  static noinline_for_stack
  int skip_atoi(const char **s)
  {
@@@ -433,7 -574,9 +433,9 @@@ char *symbol_string(char *buf, char *en
        unsigned long value = (unsigned long) ptr;
  #ifdef CONFIG_KALLSYMS
        char sym[KSYM_SYMBOL_LEN];
-       if (ext != 'f' && ext != 's')
+       if (ext == 'B')
+               sprint_backtrace(sym, value);
+       else if (ext != 'f' && ext != 's')
                sprint_symbol(sym, value);
        else
                kallsyms_lookup(value, NULL, NULL, NULL, sym);
@@@ -808,6 -951,7 +810,7 @@@ int kptr_restrict = 1
   * - 'f' For simple symbolic function names without offset
   * - 'S' For symbolic direct pointers with offset
   * - 's' For symbolic direct pointers without offset
+  * - 'B' For backtraced symbolic direct pointers with offset
   * - 'R' For decoded struct resource, e.g., [mem 0x0-0x1f 64bit pref]
   * - 'r' For raw struct resource, e.g., [mem 0x0-0x1f flags 0x201]
   * - 'M' For a 6-byte MAC address, it prints the address in the
@@@ -850,7 -994,7 +853,7 @@@ static noinline_for_stac
  char *pointer(const char *fmt, char *buf, char *end, void *ptr,
              struct printf_spec spec)
  {
 -      if (!ptr) {
 +      if (!ptr && *fmt != 'K') {
                /*
                 * Print (null) with the same width as a pointer so it makes
                 * tabular output look nice.
                /* Fallthrough */
        case 'S':
        case 's':
+       case 'B':
                return symbol_string(buf, end, ptr, spec, *fmt);
        case 'R':
        case 'r':
                        if (spec.field_width == -1)
                                spec.field_width = 2 * sizeof(void *);
                        return string(buf, end, "pK-error", spec);
 -              } else if ((kptr_restrict == 0) ||
 -                       (kptr_restrict == 1 &&
 -                        has_capability_noaudit(current, CAP_SYSLOG)))
 -                      break;
 -
 -              if (spec.field_width == -1) {
 -                      spec.field_width = 2 * sizeof(void *);
 -                      spec.flags |= ZEROPAD;
                }
 -              return number(buf, end, 0, spec);
 +              if (!((kptr_restrict == 0) ||
 +                    (kptr_restrict == 1 &&
 +                     has_capability_noaudit(current, CAP_SYSLOG))))
 +                      ptr = NULL;
 +              break;
        }
        spec.flags |= SMALL;
        if (spec.field_width == -1) {
@@@ -1134,6 -1283,7 +1138,7 @@@ qualifier
   * %ps output the name of a text symbol without offset
   * %pF output the name of a function pointer with its offset
   * %pf output the name of a function pointer without its offset
+  * %pB output the name of a backtrace symbol with its offset
   * %pR output the address range in a struct resource with decoded flags
   * %pr output the address range in a struct resource with raw flags
   * %pM output a 6-byte MAC address with colons