aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2008-10-22 11:00:13 -0400
committerRusty Russell <rusty@rustcorp.com.au>2008-10-21 19:00:15 -0400
commit5e458cc0f4770eea45d3c07110f01b3a94c72aa5 (patch)
tree97966d9ac8f9621073fad39a88ed37765c959a9d
parent2515ddc6db8eb49a79f0fe5e67ff09ac7c81eab4 (diff)
module: simplify load_module.
Linus' recent catch of stack overflow in load_module lead me to look at the code. A couple of helpers to get a section address and get objects from a section can help clean things up a little. (And in case you're wondering, the stack size also dropped from 328 to 284 bytes). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--include/linux/module.h2
-rw-r--r--kernel/module.c235
2 files changed, 100 insertions, 137 deletions
diff --git a/include/linux/module.h b/include/linux/module.h
index 5d2970cdce9..eddf27db442 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -277,7 +277,7 @@ struct module
277 277
278 /* Exception table */ 278 /* Exception table */
279 unsigned int num_exentries; 279 unsigned int num_exentries;
280 const struct exception_table_entry *extable; 280 struct exception_table_entry *extable;
281 281
282 /* Startup function. */ 282 /* Startup function. */
283 int (*init)(void); 283 int (*init)(void);
diff --git a/kernel/module.c b/kernel/module.c
index 0d8d21ee792..3d256681ab6 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -132,6 +132,29 @@ static unsigned int find_sec(Elf_Ehdr *hdr,
132 return 0; 132 return 0;
133} 133}
134 134
135/* Find a module section, or NULL. */
136static void *section_addr(Elf_Ehdr *hdr, Elf_Shdr *shdrs,
137 const char *secstrings, const char *name)
138{
139 /* Section 0 has sh_addr 0. */
140 return (void *)shdrs[find_sec(hdr, shdrs, secstrings, name)].sh_addr;
141}
142
143/* Find a module section, or NULL. Fill in number of "objects" in section. */
144static void *section_objs(Elf_Ehdr *hdr,
145 Elf_Shdr *sechdrs,
146 const char *secstrings,
147 const char *name,
148 size_t object_size,
149 unsigned int *num)
150{
151 unsigned int sec = find_sec(hdr, sechdrs, secstrings, name);
152
153 /* Section 0 has sh_addr 0 and sh_size 0. */
154 *num = sechdrs[sec].sh_size / object_size;
155 return (void *)sechdrs[sec].sh_addr;
156}
157
135/* Provided by the linker */ 158/* Provided by the linker */
136extern const struct kernel_symbol __start___ksymtab[]; 159extern const struct kernel_symbol __start___ksymtab[];
137extern const struct kernel_symbol __stop___ksymtab[]; 160extern const struct kernel_symbol __stop___ksymtab[];
@@ -1789,32 +1812,20 @@ static inline void add_kallsyms(struct module *mod,
1789} 1812}
1790#endif /* CONFIG_KALLSYMS */ 1813#endif /* CONFIG_KALLSYMS */
1791 1814
1792#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG 1815static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num)
1793static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex)
1794{ 1816{
1795 struct mod_debug *debug_info; 1817#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
1796 unsigned long pos, end; 1818 unsigned int i;
1797 unsigned int num_verbose;
1798
1799 pos = sechdrs[verboseindex].sh_addr;
1800 num_verbose = sechdrs[verboseindex].sh_size /
1801 sizeof(struct mod_debug);
1802 end = pos + (num_verbose * sizeof(struct mod_debug));
1803 1819
1804 for (; pos < end; pos += sizeof(struct mod_debug)) { 1820 for (i = 0; i < num; i++) {
1805 debug_info = (struct mod_debug *)pos; 1821 register_dynamic_debug_module(debug[i].modname,
1806 register_dynamic_debug_module(debug_info->modname, 1822 debug[i].type,
1807 debug_info->type, debug_info->logical_modname, 1823 debug[i].logical_modname,
1808 debug_info->flag_names, debug_info->hash, 1824 debug[i].flag_names,
1809 debug_info->hash2); 1825 debug[i].hash, debug[i].hash2);
1810 } 1826 }
1811}
1812#else
1813static inline void dynamic_printk_setup(Elf_Shdr *sechdrs,
1814 unsigned int verboseindex)
1815{
1816}
1817#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ 1827#endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
1828}
1818 1829
1819static void *module_alloc_update_bounds(unsigned long size) 1830static void *module_alloc_update_bounds(unsigned long size)
1820{ 1831{
@@ -1843,37 +1854,14 @@ static noinline struct module *load_module(void __user *umod,
1843 unsigned int i; 1854 unsigned int i;
1844 unsigned int symindex = 0; 1855 unsigned int symindex = 0;
1845 unsigned int strindex = 0; 1856 unsigned int strindex = 0;
1846 unsigned int setupindex; 1857 unsigned int modindex, versindex, infoindex, pcpuindex;
1847 unsigned int exindex;
1848 unsigned int exportindex;
1849 unsigned int modindex;
1850 unsigned int obsparmindex;
1851 unsigned int infoindex;
1852 unsigned int gplindex;
1853 unsigned int crcindex;
1854 unsigned int gplcrcindex;
1855 unsigned int versindex;
1856 unsigned int pcpuindex;
1857 unsigned int gplfutureindex;
1858 unsigned int gplfuturecrcindex;
1859 unsigned int unwindex = 0; 1858 unsigned int unwindex = 0;
1860#ifdef CONFIG_UNUSED_SYMBOLS 1859 unsigned int num_kp, num_mcount;
1861 unsigned int unusedindex; 1860 struct kernel_param *kp;
1862 unsigned int unusedcrcindex;
1863 unsigned int unusedgplindex;
1864 unsigned int unusedgplcrcindex;
1865#endif
1866 unsigned int markersindex;
1867 unsigned int markersstringsindex;
1868 unsigned int verboseindex;
1869 unsigned int tracepointsindex;
1870 unsigned int tracepointsstringsindex;
1871 unsigned int mcountindex;
1872 struct module *mod; 1861 struct module *mod;
1873 long err = 0; 1862 long err = 0;
1874 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ 1863 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
1875 void *mseg; 1864 unsigned long *mseg;
1876 struct exception_table_entry *extable;
1877 mm_segment_t old_fs; 1865 mm_segment_t old_fs;
1878 1866
1879 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", 1867 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
@@ -1937,6 +1925,7 @@ static noinline struct module *load_module(void __user *umod,
1937 err = -ENOEXEC; 1925 err = -ENOEXEC;
1938 goto free_hdr; 1926 goto free_hdr;
1939 } 1927 }
1928 /* This is temporary: point mod into copy of data. */
1940 mod = (void *)sechdrs[modindex].sh_addr; 1929 mod = (void *)sechdrs[modindex].sh_addr;
1941 1930
1942 if (symindex == 0) { 1931 if (symindex == 0) {
@@ -1946,22 +1935,6 @@ static noinline struct module *load_module(void __user *umod,
1946 goto free_hdr; 1935 goto free_hdr;
1947 } 1936 }
1948 1937
1949 /* Optional sections */
1950 exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
1951 gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
1952 gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
1953 crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
1954 gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
1955 gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
1956#ifdef CONFIG_UNUSED_SYMBOLS
1957 unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
1958 unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
1959 unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");
1960 unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");
1961#endif
1962 setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
1963 exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
1964 obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
1965 versindex = find_sec(hdr, sechdrs, secstrings, "__versions"); 1938 versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
1966 infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo"); 1939 infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
1967 pcpuindex = find_pcpusec(hdr, sechdrs, secstrings); 1940 pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);
@@ -2117,42 +2090,57 @@ static noinline struct module *load_module(void __user *umod,
2117 if (err < 0) 2090 if (err < 0)
2118 goto cleanup; 2091 goto cleanup;
2119 2092
2120 /* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */ 2093 /* Now we've got everything in the final locations, we can
2121 mod->num_syms = sechdrs[exportindex].sh_size / sizeof(*mod->syms); 2094 * find optional sections. */
2122 mod->syms = (void *)sechdrs[exportindex].sh_addr; 2095 kp = section_objs(hdr, sechdrs, secstrings, "__param", sizeof(*kp),
2123 if (crcindex) 2096 &num_kp);
2124 mod->crcs = (void *)sechdrs[crcindex].sh_addr; 2097 mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab",
2125 mod->num_gpl_syms = sechdrs[gplindex].sh_size / sizeof(*mod->gpl_syms); 2098 sizeof(*mod->syms), &mod->num_syms);
2126 mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr; 2099 mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab");
2127 if (gplcrcindex) 2100 mod->gpl_syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab_gpl",
2128 mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; 2101 sizeof(*mod->gpl_syms),
2129 mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / 2102 &mod->num_gpl_syms);
2130 sizeof(*mod->gpl_future_syms); 2103 mod->gpl_crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab_gpl");
2131 mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; 2104 mod->gpl_future_syms = section_objs(hdr, sechdrs, secstrings,
2132 if (gplfuturecrcindex) 2105 "__ksymtab_gpl_future",
2133 mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; 2106 sizeof(*mod->gpl_future_syms),
2107 &mod->num_gpl_future_syms);
2108 mod->gpl_future_crcs = section_addr(hdr, sechdrs, secstrings,
2109 "__kcrctab_gpl_future");
2134 2110
2135#ifdef CONFIG_UNUSED_SYMBOLS 2111#ifdef CONFIG_UNUSED_SYMBOLS
2136 mod->num_unused_syms = sechdrs[unusedindex].sh_size / 2112 mod->unused_syms = section_objs(hdr, sechdrs, secstrings,
2137 sizeof(*mod->unused_syms); 2113 "__ksymtab_unused",
2138 mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size / 2114 sizeof(*mod->unused_syms),
2139 sizeof(*mod->unused_gpl_syms); 2115 &mod->num_unused_syms);
2140 mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; 2116 mod->unused_crcs = section_addr(hdr, sechdrs, secstrings,
2141 if (unusedcrcindex) 2117 "__kcrctab_unused");
2142 mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; 2118 mod->unused_gpl_syms = section_objs(hdr, sechdrs, secstrings,
2143 mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr; 2119 "__ksymtab_unused_gpl",
2144 if (unusedgplcrcindex) 2120 sizeof(*mod->unused_gpl_syms),
2145 mod->unused_gpl_crcs 2121 &mod->num_unused_gpl_syms);
2146 = (void *)sechdrs[unusedgplcrcindex].sh_addr; 2122 mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings,
2123 "__kcrctab_unused_gpl");
2124#endif
2125
2126#ifdef CONFIG_MARKERS
2127 mod->markers = section_objs(hdr, sechdrs, secstrings, "__markers",
2128 sizeof(*mod->markers), &mod->num_markers);
2129#endif
2130#ifdef CONFIG_TRACEPOINTS
2131 mod->tracepoints = section_objs(hdr, sechdrs, secstrings,
2132 "__tracepoints",
2133 sizeof(*mod->tracepoints),
2134 &mod->num_tracepoints);
2147#endif 2135#endif
2148 2136
2149#ifdef CONFIG_MODVERSIONS 2137#ifdef CONFIG_MODVERSIONS
2150 if ((mod->num_syms && !crcindex) 2138 if ((mod->num_syms && !mod->crcs)
2151 || (mod->num_gpl_syms && !gplcrcindex) 2139 || (mod->num_gpl_syms && !mod->gpl_crcs)
2152 || (mod->num_gpl_future_syms && !gplfuturecrcindex) 2140 || (mod->num_gpl_future_syms && !mod->gpl_future_crcs)
2153#ifdef CONFIG_UNUSED_SYMBOLS 2141#ifdef CONFIG_UNUSED_SYMBOLS
2154 || (mod->num_unused_syms && !unusedcrcindex) 2142 || (mod->num_unused_syms && !mod->unused_crcs)
2155 || (mod->num_unused_gpl_syms && !unusedgplcrcindex) 2143 || (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs)
2156#endif 2144#endif
2157 ) { 2145 ) {
2158 printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name); 2146 printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name);
@@ -2161,16 +2149,6 @@ static noinline struct module *load_module(void __user *umod,
2161 goto cleanup; 2149 goto cleanup;
2162 } 2150 }
2163#endif 2151#endif
2164 markersindex = find_sec(hdr, sechdrs, secstrings, "__markers");
2165 markersstringsindex = find_sec(hdr, sechdrs, secstrings,
2166 "__markers_strings");
2167 verboseindex = find_sec(hdr, sechdrs, secstrings, "__verbose");
2168 tracepointsindex = find_sec(hdr, sechdrs, secstrings, "__tracepoints");
2169 tracepointsstringsindex = find_sec(hdr, sechdrs, secstrings,
2170 "__tracepoints_strings");
2171
2172 mcountindex = find_sec(hdr, sechdrs, secstrings,
2173 "__mcount_loc");
2174 2152
2175 /* Now do relocations. */ 2153 /* Now do relocations. */
2176 for (i = 1; i < hdr->e_shnum; i++) { 2154 for (i = 1; i < hdr->e_shnum; i++) {
@@ -2193,28 +2171,16 @@ static noinline struct module *load_module(void __user *umod,
2193 if (err < 0) 2171 if (err < 0)
2194 goto cleanup; 2172 goto cleanup;
2195 } 2173 }
2196#ifdef CONFIG_MARKERS
2197 mod->markers = (void *)sechdrs[markersindex].sh_addr;
2198 mod->num_markers =
2199 sechdrs[markersindex].sh_size / sizeof(*mod->markers);
2200#endif
2201#ifdef CONFIG_TRACEPOINTS
2202 mod->tracepoints = (void *)sechdrs[tracepointsindex].sh_addr;
2203 mod->num_tracepoints =
2204 sechdrs[tracepointsindex].sh_size / sizeof(*mod->tracepoints);
2205#endif
2206
2207 2174
2208 /* Find duplicate symbols */ 2175 /* Find duplicate symbols */
2209 err = verify_export_symbols(mod); 2176 err = verify_export_symbols(mod);
2210
2211 if (err < 0) 2177 if (err < 0)
2212 goto cleanup; 2178 goto cleanup;
2213 2179
2214 /* Set up and sort exception table */ 2180 /* Set up and sort exception table */
2215 mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable); 2181 mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
2216 mod->extable = extable = (void *)sechdrs[exindex].sh_addr; 2182 sizeof(*mod->extable), &mod->num_exentries);
2217 sort_extable(extable, extable + mod->num_exentries); 2183 sort_extable(mod->extable, mod->extable + mod->num_exentries);
2218 2184
2219 /* Finally, copy percpu area over. */ 2185 /* Finally, copy percpu area over. */
2220 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr, 2186 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
@@ -2223,11 +2189,17 @@ static noinline struct module *load_module(void __user *umod,
2223 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings); 2189 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
2224 2190
2225 if (!mod->taints) { 2191 if (!mod->taints) {
2192 struct mod_debug *debug;
2193 unsigned int num_debug;
2194
2226#ifdef CONFIG_MARKERS 2195#ifdef CONFIG_MARKERS
2227 marker_update_probe_range(mod->markers, 2196 marker_update_probe_range(mod->markers,
2228 mod->markers + mod->num_markers); 2197 mod->markers + mod->num_markers);
2229#endif 2198#endif
2230 dynamic_printk_setup(sechdrs, verboseindex); 2199 debug = section_objs(hdr, sechdrs, secstrings, "__verbose",
2200 sizeof(*debug), &num_debug);
2201 dynamic_printk_setup(debug, num_debug);
2202
2231#ifdef CONFIG_TRACEPOINTS 2203#ifdef CONFIG_TRACEPOINTS
2232 tracepoint_update_probe_range(mod->tracepoints, 2204 tracepoint_update_probe_range(mod->tracepoints,
2233 mod->tracepoints + mod->num_tracepoints); 2205 mod->tracepoints + mod->num_tracepoints);
@@ -2235,8 +2207,9 @@ static noinline struct module *load_module(void __user *umod,
2235 } 2207 }
2236 2208
2237 /* sechdrs[0].sh_size is always zero */ 2209 /* sechdrs[0].sh_size is always zero */
2238 mseg = (void *)sechdrs[mcountindex].sh_addr; 2210 mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc",
2239 ftrace_init_module(mseg, mseg + sechdrs[mcountindex].sh_size); 2211 sizeof(*mseg), &num_mcount);
2212 ftrace_init_module(mseg, mseg + num_mcount);
2240 2213
2241 err = module_finalize(hdr, sechdrs, mod); 2214 err = module_finalize(hdr, sechdrs, mod);
2242 if (err < 0) 2215 if (err < 0)
@@ -2261,7 +2234,7 @@ static noinline struct module *load_module(void __user *umod,
2261 set_fs(old_fs); 2234 set_fs(old_fs);
2262 2235
2263 mod->args = args; 2236 mod->args = args;
2264 if (obsparmindex) 2237 if (section_addr(hdr, sechdrs, secstrings, "__obsparm"))
2265 printk(KERN_WARNING "%s: Ignoring obsolete parameters\n", 2238 printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
2266 mod->name); 2239 mod->name);
2267 2240
@@ -2270,21 +2243,11 @@ static noinline struct module *load_module(void __user *umod,
2270 * strong_try_module_get() will fail. */ 2243 * strong_try_module_get() will fail. */
2271 stop_machine(__link_module, mod, NULL); 2244 stop_machine(__link_module, mod, NULL);
2272 2245
2273 /* Size of section 0 is 0, so this works well if no params */ 2246 err = parse_args(mod->name, mod->args, kp, num_kp, NULL);
2274 err = parse_args(mod->name, mod->args,
2275 (struct kernel_param *)
2276 sechdrs[setupindex].sh_addr,
2277 sechdrs[setupindex].sh_size
2278 / sizeof(struct kernel_param),
2279 NULL);
2280 if (err < 0) 2247 if (err < 0)
2281 goto unlink; 2248 goto unlink;
2282 2249
2283 err = mod_sysfs_setup(mod, 2250 err = mod_sysfs_setup(mod, kp, num_kp);
2284 (struct kernel_param *)
2285 sechdrs[setupindex].sh_addr,
2286 sechdrs[setupindex].sh_size
2287 / sizeof(struct kernel_param));
2288 if (err < 0) 2251 if (err < 0)
2289 goto unlink; 2252 goto unlink;
2290 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs); 2253 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);