aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-09-24 12:01:05 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-24 12:01:05 -0400
commit2c9871de0ae89a0e2c365ea6e277135fe031d8b4 (patch)
tree1b5a05333f53c9eebb4d89924944201ec6e1f400 /kernel
parentdc2af6a6bcf3abdf44ac545759a6547dfe12070e (diff)
parentffa9f12a41ec117207e8d953f90b9c179546c8d7 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: module: don't call percpu_modfree on NULL pointer. module: fix memory leak when load fails after srcversion/version allocated module: preferred way to use MODULE_AUTHOR param: allow whitespace as kernel parameter separator module: reduce string table for loaded modules (v2) module: reduce symbol table for loaded modules (v2)
Diffstat (limited to 'kernel')
-rw-r--r--kernel/module.c159
-rw-r--r--kernel/params.c7
2 files changed, 153 insertions, 13 deletions
diff --git a/kernel/module.c b/kernel/module.c
index e6bc4b28aa62..5a29397ca4b6 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -1797,6 +1797,17 @@ static void setup_modinfo(struct module *mod, Elf_Shdr *sechdrs,
1797 } 1797 }
1798} 1798}
1799 1799
1800static void free_modinfo(struct module *mod)
1801{
1802 struct module_attribute *attr;
1803 int i;
1804
1805 for (i = 0; (attr = modinfo_attrs[i]); i++) {
1806 if (attr->free)
1807 attr->free(mod);
1808 }
1809}
1810
1800#ifdef CONFIG_KALLSYMS 1811#ifdef CONFIG_KALLSYMS
1801 1812
1802/* lookup symbol in given range of kernel_symbols */ 1813/* lookup symbol in given range of kernel_symbols */
@@ -1862,13 +1873,93 @@ static char elf_type(const Elf_Sym *sym,
1862 return '?'; 1873 return '?';
1863} 1874}
1864 1875
1876static bool is_core_symbol(const Elf_Sym *src, const Elf_Shdr *sechdrs,
1877 unsigned int shnum)
1878{
1879 const Elf_Shdr *sec;
1880
1881 if (src->st_shndx == SHN_UNDEF
1882 || src->st_shndx >= shnum
1883 || !src->st_name)
1884 return false;
1885
1886 sec = sechdrs + src->st_shndx;
1887 if (!(sec->sh_flags & SHF_ALLOC)
1888#ifndef CONFIG_KALLSYMS_ALL
1889 || !(sec->sh_flags & SHF_EXECINSTR)
1890#endif
1891 || (sec->sh_entsize & INIT_OFFSET_MASK))
1892 return false;
1893
1894 return true;
1895}
1896
1897static unsigned long layout_symtab(struct module *mod,
1898 Elf_Shdr *sechdrs,
1899 unsigned int symindex,
1900 unsigned int strindex,
1901 const Elf_Ehdr *hdr,
1902 const char *secstrings,
1903 unsigned long *pstroffs,
1904 unsigned long *strmap)
1905{
1906 unsigned long symoffs;
1907 Elf_Shdr *symsect = sechdrs + symindex;
1908 Elf_Shdr *strsect = sechdrs + strindex;
1909 const Elf_Sym *src;
1910 const char *strtab;
1911 unsigned int i, nsrc, ndst;
1912
1913 /* Put symbol section at end of init part of module. */
1914 symsect->sh_flags |= SHF_ALLOC;
1915 symsect->sh_entsize = get_offset(mod, &mod->init_size, symsect,
1916 symindex) | INIT_OFFSET_MASK;
1917 DEBUGP("\t%s\n", secstrings + symsect->sh_name);
1918
1919 src = (void *)hdr + symsect->sh_offset;
1920 nsrc = symsect->sh_size / sizeof(*src);
1921 strtab = (void *)hdr + strsect->sh_offset;
1922 for (ndst = i = 1; i < nsrc; ++i, ++src)
1923 if (is_core_symbol(src, sechdrs, hdr->e_shnum)) {
1924 unsigned int j = src->st_name;
1925
1926 while(!__test_and_set_bit(j, strmap) && strtab[j])
1927 ++j;
1928 ++ndst;
1929 }
1930
1931 /* Append room for core symbols at end of core part. */
1932 symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1);
1933 mod->core_size = symoffs + ndst * sizeof(Elf_Sym);
1934
1935 /* Put string table section at end of init part of module. */
1936 strsect->sh_flags |= SHF_ALLOC;
1937 strsect->sh_entsize = get_offset(mod, &mod->init_size, strsect,
1938 strindex) | INIT_OFFSET_MASK;
1939 DEBUGP("\t%s\n", secstrings + strsect->sh_name);
1940
1941 /* Append room for core symbols' strings at end of core part. */
1942 *pstroffs = mod->core_size;
1943 __set_bit(0, strmap);
1944 mod->core_size += bitmap_weight(strmap, strsect->sh_size);
1945
1946 return symoffs;
1947}
1948
1865static void add_kallsyms(struct module *mod, 1949static void add_kallsyms(struct module *mod,
1866 Elf_Shdr *sechdrs, 1950 Elf_Shdr *sechdrs,
1951 unsigned int shnum,
1867 unsigned int symindex, 1952 unsigned int symindex,
1868 unsigned int strindex, 1953 unsigned int strindex,
1869 const char *secstrings) 1954 unsigned long symoffs,
1955 unsigned long stroffs,
1956 const char *secstrings,
1957 unsigned long *strmap)
1870{ 1958{
1871 unsigned int i; 1959 unsigned int i, ndst;
1960 const Elf_Sym *src;
1961 Elf_Sym *dst;
1962 char *s;
1872 1963
1873 mod->symtab = (void *)sechdrs[symindex].sh_addr; 1964 mod->symtab = (void *)sechdrs[symindex].sh_addr;
1874 mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); 1965 mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
@@ -1878,13 +1969,44 @@ static void add_kallsyms(struct module *mod,
1878 for (i = 0; i < mod->num_symtab; i++) 1969 for (i = 0; i < mod->num_symtab; i++)
1879 mod->symtab[i].st_info 1970 mod->symtab[i].st_info
1880 = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); 1971 = elf_type(&mod->symtab[i], sechdrs, secstrings, mod);
1972
1973 mod->core_symtab = dst = mod->module_core + symoffs;
1974 src = mod->symtab;
1975 *dst = *src;
1976 for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) {
1977 if (!is_core_symbol(src, sechdrs, shnum))
1978 continue;
1979 dst[ndst] = *src;
1980 dst[ndst].st_name = bitmap_weight(strmap, dst[ndst].st_name);
1981 ++ndst;
1982 }
1983 mod->core_num_syms = ndst;
1984
1985 mod->core_strtab = s = mod->module_core + stroffs;
1986 for (*s = 0, i = 1; i < sechdrs[strindex].sh_size; ++i)
1987 if (test_bit(i, strmap))
1988 *++s = mod->strtab[i];
1881} 1989}
1882#else 1990#else
1991static inline unsigned long layout_symtab(struct module *mod,
1992 Elf_Shdr *sechdrs,
1993 unsigned int symindex,
1994 unsigned int strindex,
1995 const Elf_Hdr *hdr,
1996 const char *secstrings,
1997 unsigned long *pstroffs,
1998 unsigned long *strmap)
1999{
2000}
1883static inline void add_kallsyms(struct module *mod, 2001static inline void add_kallsyms(struct module *mod,
1884 Elf_Shdr *sechdrs, 2002 Elf_Shdr *sechdrs,
2003 unsigned int shnum,
1885 unsigned int symindex, 2004 unsigned int symindex,
1886 unsigned int strindex, 2005 unsigned int strindex,
1887 const char *secstrings) 2006 unsigned long symoffs,
2007 unsigned long stroffs,
2008 const char *secstrings,
2009 const unsigned long *strmap)
1888{ 2010{
1889} 2011}
1890#endif /* CONFIG_KALLSYMS */ 2012#endif /* CONFIG_KALLSYMS */
@@ -1959,6 +2081,9 @@ static noinline struct module *load_module(void __user *umod,
1959 struct module *mod; 2081 struct module *mod;
1960 long err = 0; 2082 long err = 0;
1961 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 2083 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
2084#ifdef CONFIG_KALLSYMS
2085 unsigned long symoffs, stroffs, *strmap;
2086#endif
1962 mm_segment_t old_fs; 2087 mm_segment_t old_fs;
1963 2088
1964 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", 2089 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
@@ -2040,11 +2165,6 @@ static noinline struct module *load_module(void __user *umod,
2040 /* Don't keep modinfo and version sections. */ 2165 /* Don't keep modinfo and version sections. */
2041 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2166 sechdrs[infoindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2042 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC; 2167 sechdrs[versindex].sh_flags &= ~(unsigned long)SHF_ALLOC;
2043#ifdef CONFIG_KALLSYMS
2044 /* Keep symbol and string tables for decoding later. */
2045 sechdrs[symindex].sh_flags |= SHF_ALLOC;
2046 sechdrs[strindex].sh_flags |= SHF_ALLOC;
2047#endif
2048 2168
2049 /* Check module struct version now, before we try to use module. */ 2169 /* Check module struct version now, before we try to use module. */
2050 if (!check_modstruct_version(sechdrs, versindex, mod)) { 2170 if (!check_modstruct_version(sechdrs, versindex, mod)) {
@@ -2080,6 +2200,13 @@ static noinline struct module *load_module(void __user *umod,
2080 goto free_hdr; 2200 goto free_hdr;
2081 } 2201 }
2082 2202
2203 strmap = kzalloc(BITS_TO_LONGS(sechdrs[strindex].sh_size)
2204 * sizeof(long), GFP_KERNEL);
2205 if (!strmap) {
2206 err = -ENOMEM;
2207 goto free_mod;
2208 }
2209
2083 if (find_module(mod->name)) { 2210 if (find_module(mod->name)) {
2084 err = -EEXIST; 2211 err = -EEXIST;
2085 goto free_mod; 2212 goto free_mod;
@@ -2109,6 +2236,8 @@ static noinline struct module *load_module(void __user *umod,
2109 this is done generically; there doesn't appear to be any 2236 this is done generically; there doesn't appear to be any
2110 special cases for the architectures. */ 2237 special cases for the architectures. */
2111 layout_sections(mod, hdr, sechdrs, secstrings); 2238 layout_sections(mod, hdr, sechdrs, secstrings);
2239 symoffs = layout_symtab(mod, sechdrs, symindex, strindex, hdr,
2240 secstrings, &stroffs, strmap);
2112 2241
2113 /* Do the allocs. */ 2242 /* Do the allocs. */
2114 ptr = module_alloc_update_bounds(mod->core_size); 2243 ptr = module_alloc_update_bounds(mod->core_size);
@@ -2313,7 +2442,10 @@ static noinline struct module *load_module(void __user *umod,
2313 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, 2442 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
2314 sechdrs[pcpuindex].sh_size); 2443 sechdrs[pcpuindex].sh_size);
2315 2444
2316 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); 2445 add_kallsyms(mod, sechdrs, hdr->e_shnum, symindex, strindex,
2446 symoffs, stroffs, secstrings, strmap);
2447 kfree(strmap);
2448 strmap = NULL;
2317 2449
2318 if (!mod->taints) { 2450 if (!mod->taints) {
2319 struct _ddebug *debug; 2451 struct _ddebug *debug;
@@ -2385,13 +2517,14 @@ static noinline struct module *load_module(void __user *umod,
2385 synchronize_sched(); 2517 synchronize_sched();
2386 module_arch_cleanup(mod); 2518 module_arch_cleanup(mod);
2387 cleanup: 2519 cleanup:
2520 free_modinfo(mod);
2388 kobject_del(&mod->mkobj.kobj); 2521 kobject_del(&mod->mkobj.kobj);
2389 kobject_put(&mod->mkobj.kobj); 2522 kobject_put(&mod->mkobj.kobj);
2390 free_unload: 2523 free_unload:
2391 module_unload_free(mod); 2524 module_unload_free(mod);
2392#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP) 2525#if defined(CONFIG_MODULE_UNLOAD) && defined(CONFIG_SMP)
2393 free_init:
2394 percpu_modfree(mod->refptr); 2526 percpu_modfree(mod->refptr);
2527 free_init:
2395#endif 2528#endif
2396 module_free(mod, mod->module_init); 2529 module_free(mod, mod->module_init);
2397 free_core: 2530 free_core:
@@ -2402,6 +2535,7 @@ static noinline struct module *load_module(void __user *umod,
2402 percpu_modfree(percpu); 2535 percpu_modfree(percpu);
2403 free_mod: 2536 free_mod:
2404 kfree(args); 2537 kfree(args);
2538 kfree(strmap);
2405 free_hdr: 2539 free_hdr:
2406 vfree(hdr); 2540 vfree(hdr);
2407 return ERR_PTR(err); 2541 return ERR_PTR(err);
@@ -2491,6 +2625,11 @@ SYSCALL_DEFINE3(init_module, void __user *, umod,
2491 /* Drop initial reference. */ 2625 /* Drop initial reference. */
2492 module_put(mod); 2626 module_put(mod);
2493 trim_init_extable(mod); 2627 trim_init_extable(mod);
2628#ifdef CONFIG_KALLSYMS
2629 mod->num_symtab = mod->core_num_syms;
2630 mod->symtab = mod->core_symtab;
2631 mod->strtab = mod->core_strtab;
2632#endif
2494 module_free(mod, mod->module_init); 2633 module_free(mod, mod->module_init);
2495 mod->module_init = NULL; 2634 mod->module_init = NULL;
2496 mod->init_size = 0; 2635 mod->init_size = 0;
diff --git a/kernel/params.c b/kernel/params.c
index 7f6912ced2ba..9da58eabdcb2 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -23,6 +23,7 @@
23#include <linux/device.h> 23#include <linux/device.h>
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/ctype.h>
26 27
27#if 0 28#if 0
28#define DEBUGP printk 29#define DEBUGP printk
@@ -87,7 +88,7 @@ static char *next_arg(char *args, char **param, char **val)
87 } 88 }
88 89
89 for (i = 0; args[i]; i++) { 90 for (i = 0; args[i]; i++) {
90 if (args[i] == ' ' && !in_quote) 91 if (isspace(args[i]) && !in_quote)
91 break; 92 break;
92 if (equals == 0) { 93 if (equals == 0) {
93 if (args[i] == '=') 94 if (args[i] == '=')
@@ -121,7 +122,7 @@ static char *next_arg(char *args, char **param, char **val)
121 next = args + i; 122 next = args + i;
122 123
123 /* Chew up trailing spaces. */ 124 /* Chew up trailing spaces. */
124 while (*next == ' ') 125 while (isspace(*next))
125 next++; 126 next++;
126 return next; 127 return next;
127} 128}
@@ -138,7 +139,7 @@ int parse_args(const char *name,
138 DEBUGP("Parsing ARGS: %s\n", args); 139 DEBUGP("Parsing ARGS: %s\n", args);
139 140
140 /* Chew leading spaces */ 141 /* Chew leading spaces */
141 while (*args == ' ') 142 while (isspace(*args))
142 args++; 143 args++;
143 144
144 while (*args) { 145 while (*args) {