Merge branch 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Sep 2009 17:13:54 +0000 (10:13 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 26 Sep 2009 17:13:54 +0000 (10:13 -0700)
* 'tracing-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  modules, tracing: Remove stale struct marker signature from module_layout()
  tracing/workqueue: Use %pf in workqueue trace events
  tracing: Fix a comment and a trivial format issue in tracepoint.h
  tracing: Fix failure path in ftrace_regex_open()
  tracing: Fix failure path in ftrace_graph_write()
  tracing: Check the return value of trace_get_user()
  tracing: Fix off-by-one in trace_get_user()

1  2 
kernel/module.c
kernel/trace/ftrace.c
kernel/trace/trace.c

diff --combined kernel/module.c
@@@ -47,7 -47,6 +47,7 @@@
  #include <linux/rculist.h>
  #include <asm/uaccess.h>
  #include <asm/cacheflush.h>
 +#include <asm/mmu_context.h>
  #include <linux/license.h>
  #include <asm/sections.h>
  #include <linux/tracepoint.h>
@@@ -1536,10 -1535,6 +1536,10 @@@ static void free_module(struct module *
  
        /* Finally, free the core (containing the module structure) */
        module_free(mod, mod->module_core);
 +
 +#ifdef CONFIG_MPU
 +      update_protections(current->mm);
 +#endif
  }
  
  void *__symbol_get(const char *symbol)
@@@ -1797,17 -1792,6 +1797,17 @@@ static void setup_modinfo(struct modul
        }
  }
  
 +static void free_modinfo(struct module *mod)
 +{
 +      struct module_attribute *attr;
 +      int i;
 +
 +      for (i = 0; (attr = modinfo_attrs[i]); i++) {
 +              if (attr->free)
 +                      attr->free(mod);
 +      }
 +}
 +
  #ifdef CONFIG_KALLSYMS
  
  /* lookup symbol in given range of kernel_symbols */
@@@ -1873,93 -1857,13 +1873,93 @@@ static char elf_type(const Elf_Sym *sym
        return '?';
  }
  
 +static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
 +                           unsigned int shnum)
 +{
 +      const Elf_Shdr *sec;
 +
 +      if (src->st_shndx == SHN_UNDEF
 +          || src->st_shndx >= shnum
 +          || !src->st_name)
 +              return false;
 +
 +      sec = sechdrs + src->st_shndx;
 +      if (!(sec->sh_flags & SHF_ALLOC)
 +#ifndef CONFIG_KALLSYMS_ALL
 +          || !(sec->sh_flags & SHF_EXECINSTR)
 +#endif
 +          || (sec->sh_entsize & INIT_OFFSET_MASK))
 +              return false;
 +
 +      return true;
 +}
 +
 +static unsigned long layout_symtab(struct module *mod,
 +                                 Elf_Shdr *sechdrs,
 +                                 unsigned int symindex,
 +                                 unsigned int strindex,
 +                                 const Elf_Ehdr *hdr,
 +                                 const char *secstrings,
 +                                 unsigned long *pstroffs,
 +                                 unsigned long *strmap)
 +{
 +      unsigned long symoffs;
 +      Elf_Shdr *symsect = sechdrs + symindex;
 +      Elf_Shdr *strsect = sechdrs + strindex;
 +      const Elf_Sym *src;
 +      const char *strtab;
 +      unsigned int i, nsrc, ndst;
 +
 +      /* Put symbol section at end of init part of module. */
 +      symsect->sh_flags |= SHF_ALLOC;
 +      symsect->sh_entsize = get_offset(mod, &mod->init_size, symsect,
 +                                       symindex) | INIT_OFFSET_MASK;
 +      DEBUGP("\t%s\n", secstrings + symsect->sh_name);
 +
 +      src = (void *)hdr + symsect->sh_offset;
 +      nsrc = symsect->sh_size / sizeof(*src);
 +      strtab = (void *)hdr + strsect->sh_offset;
 +      for (ndst = i = 1; i < nsrc; ++i, ++src)
 +              if (is_core_symbol(src, sechdrs, hdr->e_shnum)) {
 +                      unsigned int j = src->st_name;
 +
 +                      while(!__test_and_set_bit(j, strmap) && strtab[j])
 +                              ++j;
 +                      ++ndst;
 +              }
 +
 +      /* Append room for core symbols at end of core part. */
 +      symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
 +      mod->core_size = symoffs + ndst * sizeof(Elf_Sym);
 +
 +      /* Put string table section at end of init part of module. */
 +      strsect->sh_flags |= SHF_ALLOC;
 +      strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
 +                                       strindex) | INIT_OFFSET_MASK;
 +      DEBUGP("\t%s\n", secstrings + strsect->sh_name);
 +
 +      /* Append room for core symbols' strings at end of core part. */
 +      *pstroffs = mod->core_size;
 +      __set_bit(0, strmap);
 +      mod->core_size += bitmap_weight(strmap, strsect->sh_size);
 +
 +      return symoffs;
 +}
 +
  static void add_kallsyms(struct module *mod,
                         Elf_Shdr *sechdrs,
 +                       unsigned int shnum,
                         unsigned int symindex,
                         unsigned int strindex,
 -                       const char *secstrings)
 +                       unsigned long symoffs,
 +                       unsigned long stroffs,
 +                       const char *secstrings,
 +                       unsigned long *strmap)
  {
 -      unsigned int i;
 +      unsigned int i, ndst;
 +      const Elf_Sym *src;
 +      Elf_Sym *dst;
 +      char *s;
  
        mod->symtab = (void *)sechdrs[symindex].sh_addr;
        mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
        for (i = 0; i < mod->num_symtab; i++)
                mod->symtab[i].st_info
                        = elf_type(&mod->symtab[i], sechdrs, secstrings, mod);
 +
 +      mod->core_symtab = dst = mod->module_core + symoffs;
 +      src = mod->symtab;
 +      *dst = *src;
 +      for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
 +              if (!is_core_symbol(src, sechdrs, shnum))
 +                      continue;
 +              dst[ndst] = *src;
 +              dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name);
 +              ++ndst;
 +      }
 +      mod->core_num_syms = ndst;
 +
 +      mod->core_strtab = s = mod->module_core + stroffs;
 +      for (*s = 0, i = 1; i < sechdrs[strindex].sh_size; ++i)
 +              if (test_bit(i, strmap))
 +                      *++s = mod->strtab[i];
  }
  #else
 +static inline unsigned long layout_symtab(struct module *mod,
 +                                        Elf_Shdr *sechdrs,
 +                                        unsigned int symindex,
 +                                        unsigned int strindex,
 +                                        const Elf_Hdr *hdr,
 +                                        const char *secstrings,
 +                                        unsigned long *pstroffs,
 +                                        unsigned long *strmap)
 +{
 +}
  static inline void add_kallsyms(struct module *mod,
                                Elf_Shdr *sechdrs,
 +                              unsigned int shnum,
                                unsigned int symindex,
                                unsigned int strindex,
 -                              const char *secstrings)
 +                              unsigned long symoffs,
 +                              unsigned long stroffs,
 +                              const char *secstrings,
 +                              const unsigned long *strmap)
  {
  }
  #endif /* CONFIG_KALLSYMS */
@@@ -2081,9 -1954,6 +2081,9 @@@ static noinline struct module *load_mod
        struct module *mod;
        long err = 0;
        void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
 +#ifdef CONFIG_KALLSYMS
 +      unsigned long symoffs, stroffs, *strmap;
 +#endif
        mm_segment_t old_fs;
  
        DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
        /* Don't keep modinfo and version sections. */
        sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
        sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
 -#ifdef CONFIG_KALLSYMS
 -      /* Keep symbol and string tables for decoding later. */
 -      sechdrs[symindex].sh_flags |= SHF_ALLOC;
 -      sechdrs[strindex].sh_flags |= SHF_ALLOC;
 -#endif
  
        /* Check module struct version now, before we try to use module. */
        if (!check_modstruct_version(sechdrs, versindex, mod)) {
                goto free_hdr;
        }
  
 +      strmap = kzalloc(BITS_TO_LONGS(sechdrs[strindex].sh_size)
 +                       * sizeof(long), GFP_KERNEL);
 +      if (!strmap) {
 +              err = -ENOMEM;
 +              goto free_mod;
 +      }
 +
        if (find_module(mod->name)) {
                err = -EEXIST;
                goto free_mod;
           this is done generically; there doesn't appear to be any
           special cases for the architectures. */
        layout_sections(mod, hdr, sechdrs, secstrings);
 +      symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr,
 +                              secstrings, &stroffs, strmap);
  
        /* Do the allocs. */
        ptr = module_alloc_update_bounds(mod->core_size);
        percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
                       sechdrs[pcpuindex].sh_size);
  
 -      add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
 +      add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex,
 +                   symoffs, stroffs, secstrings, strmap);
 +      kfree(strmap);
 +      strmap = NULL;
  
        if (!mod->taints) {
                struct _ddebug *debug;
        synchronize_sched();
        module_arch_cleanup(mod);
   cleanup:
 +      free_modinfo(mod);
        kobject_del(&mod->mkobj.kobj);
        kobject_put(&mod->mkobj.kobj);
   free_unload:
        module_unload_free(mod);
  #if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
 - free_init:
        percpu_modfree(mod->refptr);
 + free_init:
  #endif
        module_free(mod, mod->module_init);
   free_core:
                percpu_modfree(percpu);
   free_mod:
        kfree(args);
 +      kfree(strmap);
   free_hdr:
        vfree(hdr);
        return ERR_PTR(err);
@@@ -2625,11 -2486,6 +2625,11 @@@ SYSCALL_DEFINE3(init_module, void __use
        /* Drop initial reference. */
        module_put(mod);
        trim_init_extable(mod);
 +#ifdef CONFIG_KALLSYMS
 +      mod->num_symtab = mod->core_num_syms;
 +      mod->symtab = mod->core_symtab;
 +      mod->strtab = mod->core_strtab;
 +#endif
        module_free(mod, mod->module_init);
        mod->module_init = NULL;
        mod->init_size = 0;
@@@ -3091,7 -2947,6 +3091,6 @@@ void module_layout(struct module *mod
                   struct modversion_info *ver,
                   struct kernel_param *kp,
                   struct kernel_symbol *ks,
-                  struct marker *marker,
                   struct tracepoint *tp)
  {
  }
diff --combined kernel/trace/ftrace.c
@@@ -1520,7 -1520,7 +1520,7 @@@ static int t_show(struct seq_file *m, v
        return 0;
  }
  
 -static struct seq_operations show_ftrace_seq_ops = {
 +static const struct seq_operations show_ftrace_seq_ops = {
        .start = t_start,
        .next = t_next,
        .stop = t_stop,
@@@ -1621,8 -1621,10 +1621,10 @@@ ftrace_regex_open(struct inode *inode, 
                if (!ret) {
                        struct seq_file *m = file->private_data;
                        m->private = iter;
-               } else
+               } else {
+                       trace_parser_put(&iter->parser);
                        kfree(iter);
+               }
        } else
                file->private_data = iter;
        mutex_unlock(&ftrace_regex_lock);
@@@ -2202,7 -2204,7 +2204,7 @@@ ftrace_regex_write(struct file *file, c
        struct trace_parser *parser;
        ssize_t ret, read;
  
-       if (!cnt || cnt < 0)
+       if (!cnt)
                return 0;
  
        mutex_lock(&ftrace_regex_lock);
        parser = &iter->parser;
        read = trace_get_user(parser, ubuf, cnt, ppos);
  
-       if (trace_parser_loaded(parser) &&
+       if (read >= 0 && trace_parser_loaded(parser) &&
            !trace_parser_cont(parser)) {
                ret = ftrace_process_regex(parser->buffer,
                                           parser->idx, enable);
@@@ -2459,7 -2461,7 +2461,7 @@@ static int g_show(struct seq_file *m, v
        return 0;
  }
  
 -static struct seq_operations ftrace_graph_seq_ops = {
 +static const struct seq_operations ftrace_graph_seq_ops = {
        .start = g_start,
        .next = g_next,
        .stop = g_stop,
@@@ -2552,8 -2554,7 +2554,7 @@@ ftrace_graph_write(struct file *file, c
                   size_t cnt, loff_t *ppos)
  {
        struct trace_parser parser;
-       size_t read = 0;
-       ssize_t ret;
+       ssize_t read, ret;
  
        if (!cnt || cnt < 0)
                return 0;
  
        if (ftrace_graph_count >= FTRACE_GRAPH_MAX_FUNCS) {
                ret = -EBUSY;
-               goto out;
+               goto out_unlock;
        }
  
        if (trace_parser_get_init(&parser, FTRACE_BUFF_MAX)) {
                ret = -ENOMEM;
-               goto out;
+               goto out_unlock;
        }
  
        read = trace_get_user(&parser, ubuf, cnt, ppos);
  
-       if (trace_parser_loaded((&parser))) {
+       if (read >= 0 && trace_parser_loaded((&parser))) {
                parser.buffer[parser.idx] = 0;
  
                /* we allow only one expression at a time */
                ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
                                        parser.buffer);
                if (ret)
-                       goto out;
+                       goto out_free;
        }
  
        ret = read;
-  out:
+ out_free:
        trace_parser_put(&parser);
+ out_unlock:
        mutex_unlock(&graph_lock);
  
        return ret;
@@@ -3015,7 -3018,7 +3018,7 @@@ int unregister_ftrace_function(struct f
  
  int
  ftrace_enable_sysctl(struct ctl_table *table, int write,
 -                   struct file *file, void __user *buffer, size_t *lenp,
 +                   void __user *buffer, size_t *lenp,
                     loff_t *ppos)
  {
        int ret;
  
        mutex_lock(&ftrace_lock);
  
 -      ret  = proc_dointvec(table, write, file, buffer, lenp, ppos);
 +      ret  = proc_dointvec(table, write, buffer, lenp, ppos);
  
        if (ret || !write || (last_ftrace_enabled == !!ftrace_enabled))
                goto out;
diff --combined kernel/trace/trace.c
@@@ -415,7 -415,7 +415,7 @@@ int trace_get_user(struct trace_parser 
  
        /* read the non-space input */
        while (cnt && !isspace(ch)) {
-               if (parser->idx < parser->size)
+               if (parser->idx < parser->size - 1)
                        parser->buffer[parser->idx++] = ch;
                else {
                        ret = -EINVAL;
@@@ -1949,7 -1949,7 +1949,7 @@@ static int s_show(struct seq_file *m, v
        return 0;
  }
  
 -static struct seq_operations tracer_seq_ops = {
 +static const struct seq_operations tracer_seq_ops = {
        .start          = s_start,
        .next           = s_next,
        .stop           = s_stop,
@@@ -1984,9 -1984,11 +1984,9 @@@ __tracing_open(struct inode *inode, str
        if (current_trace)
                *iter->trace = *current_trace;
  
 -      if (!alloc_cpumask_var(&iter->started, GFP_KERNEL))
 +      if (!zalloc_cpumask_var(&iter->started, GFP_KERNEL))
                goto fail;
  
 -      cpumask_clear(iter->started);
 -
        if (current_trace && current_trace->print_max)
                iter->tr = &max_tr;
        else
@@@ -2161,7 -2163,7 +2161,7 @@@ static int t_show(struct seq_file *m, v
        return 0;
  }
  
 -static struct seq_operations show_traces_seq_ops = {
 +static const struct seq_operations show_traces_seq_ops = {
        .start          = t_start,
        .next           = t_next,
        .stop           = t_stop,
@@@ -4387,7 -4389,7 +4387,7 @@@ __init static int tracer_alloc_buffers(
        if (!alloc_cpumask_var(&tracing_cpumask, GFP_KERNEL))
                goto out_free_buffer_mask;
  
 -      if (!alloc_cpumask_var(&tracing_reader_cpumask, GFP_KERNEL))
 +      if (!zalloc_cpumask_var(&tracing_reader_cpumask, GFP_KERNEL))
                goto out_free_tracing_cpumask;
  
        /* To save memory, keep the ring buffer size to its minimum */
  
        cpumask_copy(tracing_buffer_mask, cpu_possible_mask);
        cpumask_copy(tracing_cpumask, cpu_all_mask);
 -      cpumask_clear(tracing_reader_cpumask);
  
        /* TODO: make the number of buffers hot pluggable with CPUS */
        global_trace.buffer = ring_buffer_alloc(ring_buf_size,