Commit 5e458cc0f4770eea45d3c07110f01b3a94c72aa5

Authored by Rusty Russell
1 parent 2515ddc6db

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>

Showing 2 changed files with 100 additions and 137 deletions Side-by-side Diff

include/linux/module.h
... ... @@ -277,7 +277,7 @@
277 277  
278 278 /* Exception table */
279 279 unsigned int num_exentries;
280   - const struct exception_table_entry *extable;
  280 + struct exception_table_entry *extable;
281 281  
282 282 /* Startup function. */
283 283 int (*init)(void);
... ... @@ -132,6 +132,29 @@
132 132 return 0;
133 133 }
134 134  
  135 +/* Find a module section, or NULL. */
  136 +static 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. */
  144 +static 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 158 /* Provided by the linker */
136 159 extern const struct kernel_symbol __start___ksymtab[];
137 160 extern const struct kernel_symbol __stop___ksymtab[];
138 161  
139 162  
140 163  
141 164  
... ... @@ -1789,32 +1812,20 @@
1789 1812 }
1790 1813 #endif /* CONFIG_KALLSYMS */
1791 1814  
1792   -#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
1793   -static void dynamic_printk_setup(Elf_Shdr *sechdrs, unsigned int verboseindex)
  1815 +static void dynamic_printk_setup(struct mod_debug *debug, unsigned int num)
1794 1816 {
1795   - struct mod_debug *debug_info;
1796   - unsigned long pos, end;
1797   - unsigned int num_verbose;
  1817 +#ifdef CONFIG_DYNAMIC_PRINTK_DEBUG
  1818 + unsigned int i;
1798 1819  
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   -
1804   - for (; pos < end; pos += sizeof(struct mod_debug)) {
1805   - debug_info = (struct mod_debug *)pos;
1806   - register_dynamic_debug_module(debug_info->modname,
1807   - debug_info->type, debug_info->logical_modname,
1808   - debug_info->flag_names, debug_info->hash,
1809   - debug_info->hash2);
  1820 + for (i = 0; i < num; i++) {
  1821 + register_dynamic_debug_module(debug[i].modname,
  1822 + debug[i].type,
  1823 + debug[i].logical_modname,
  1824 + debug[i].flag_names,
  1825 + debug[i].hash, debug[i].hash2);
1810 1826 }
1811   -}
1812   -#else
1813   -static inline void dynamic_printk_setup(Elf_Shdr *sechdrs,
1814   - unsigned int verboseindex)
1815   -{
1816   -}
1817 1827 #endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */
  1828 +}
1818 1829  
1819 1830 static void *module_alloc_update_bounds(unsigned long size)
1820 1831 {
1821 1832  
1822 1833  
... ... @@ -1843,37 +1854,14 @@
1843 1854 unsigned int i;
1844 1855 unsigned int symindex = 0;
1845 1856 unsigned int strindex = 0;
1846   - unsigned int setupindex;
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;
  1857 + unsigned int modindex, versindex, infoindex, pcpuindex;
1859 1858 unsigned int unwindex = 0;
1860   -#ifdef CONFIG_UNUSED_SYMBOLS
1861   - unsigned int unusedindex;
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;
  1859 + unsigned int num_kp, num_mcount;
  1860 + struct kernel_param *kp;
1872 1861 struct module *mod;
1873 1862 long err = 0;
1874 1863 void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
1875   - void *mseg;
1876   - struct exception_table_entry *extable;
  1864 + unsigned long *mseg;
1877 1865 mm_segment_t old_fs;
1878 1866  
1879 1867 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
... ... @@ -1937,6 +1925,7 @@
1937 1925 err = -ENOEXEC;
1938 1926 goto free_hdr;
1939 1927 }
  1928 + /* This is temporary: point mod into copy of data. */
1940 1929 mod = (void *)sechdrs[modindex].sh_addr;
1941 1930  
1942 1931 if (symindex == 0) {
... ... @@ -1946,22 +1935,6 @@
1946 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 1938 versindex = find_sec(hdr, sechdrs, secstrings, "__versions");
1966 1939 infoindex = find_sec(hdr, sechdrs, secstrings, ".modinfo");
1967 1940 pcpuindex = find_pcpusec(hdr, sechdrs, secstrings);
1968 1941  
1969 1942  
1970 1943  
1971 1944  
... ... @@ -2117,42 +2090,57 @@
2117 2090 if (err < 0)
2118 2091 goto cleanup;
2119 2092  
2120   - /* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */
2121   - mod->num_syms = sechdrs[exportindex].sh_size / sizeof(*mod->syms);
2122   - mod->syms = (void *)sechdrs[exportindex].sh_addr;
2123   - if (crcindex)
2124   - mod->crcs = (void *)sechdrs[crcindex].sh_addr;
2125   - mod->num_gpl_syms = sechdrs[gplindex].sh_size / sizeof(*mod->gpl_syms);
2126   - mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr;
2127   - if (gplcrcindex)
2128   - mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
2129   - mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
2130   - sizeof(*mod->gpl_future_syms);
2131   - mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
2132   - if (gplfuturecrcindex)
2133   - mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
  2093 + /* Now we've got everything in the final locations, we can
  2094 + * find optional sections. */
  2095 + kp = section_objs(hdr, sechdrs, secstrings, "__param", sizeof(*kp),
  2096 + &num_kp);
  2097 + mod->syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab",
  2098 + sizeof(*mod->syms), &mod->num_syms);
  2099 + mod->crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab");
  2100 + mod->gpl_syms = section_objs(hdr, sechdrs, secstrings, "__ksymtab_gpl",
  2101 + sizeof(*mod->gpl_syms),
  2102 + &mod->num_gpl_syms);
  2103 + mod->gpl_crcs = section_addr(hdr, sechdrs, secstrings, "__kcrctab_gpl");
  2104 + mod->gpl_future_syms = section_objs(hdr, sechdrs, secstrings,
  2105 + "__ksymtab_gpl_future",
  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 2111 #ifdef CONFIG_UNUSED_SYMBOLS
2136   - mod->num_unused_syms = sechdrs[unusedindex].sh_size /
2137   - sizeof(*mod->unused_syms);
2138   - mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
2139   - sizeof(*mod->unused_gpl_syms);
2140   - mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;
2141   - if (unusedcrcindex)
2142   - mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
2143   - mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;
2144   - if (unusedgplcrcindex)
2145   - mod->unused_gpl_crcs
2146   - = (void *)sechdrs[unusedgplcrcindex].sh_addr;
  2112 + mod->unused_syms = section_objs(hdr, sechdrs, secstrings,
  2113 + "__ksymtab_unused",
  2114 + sizeof(*mod->unused_syms),
  2115 + &mod->num_unused_syms);
  2116 + mod->unused_crcs = section_addr(hdr, sechdrs, secstrings,
  2117 + "__kcrctab_unused");
  2118 + mod->unused_gpl_syms = section_objs(hdr, sechdrs, secstrings,
  2119 + "__ksymtab_unused_gpl",
  2120 + sizeof(*mod->unused_gpl_syms),
  2121 + &mod->num_unused_gpl_syms);
  2122 + mod->unused_gpl_crcs = section_addr(hdr, sechdrs, secstrings,
  2123 + "__kcrctab_unused_gpl");
2147 2124 #endif
2148 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);
  2135 +#endif
  2136 +
2149 2137 #ifdef CONFIG_MODVERSIONS
2150   - if ((mod->num_syms && !crcindex)
2151   - || (mod->num_gpl_syms && !gplcrcindex)
2152   - || (mod->num_gpl_future_syms && !gplfuturecrcindex)
  2138 + if ((mod->num_syms && !mod->crcs)
  2139 + || (mod->num_gpl_syms && !mod->gpl_crcs)
  2140 + || (mod->num_gpl_future_syms && !mod->gpl_future_crcs)
2153 2141 #ifdef CONFIG_UNUSED_SYMBOLS
2154   - || (mod->num_unused_syms && !unusedcrcindex)
2155   - || (mod->num_unused_gpl_syms && !unusedgplcrcindex)
  2142 + || (mod->num_unused_syms && !mod->unused_crcs)
  2143 + || (mod->num_unused_gpl_syms && !mod->unused_gpl_crcs)
2156 2144 #endif
2157 2145 ) {
2158 2146 printk(KERN_WARNING "%s: No versions for exported symbols.\n", mod->name);
2159 2147  
... ... @@ -2161,17 +2149,7 @@
2161 2149 goto cleanup;
2162 2150 }
2163 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 2152  
2172   - mcountindex = find_sec(hdr, sechdrs, secstrings,
2173   - "__mcount_loc");
2174   -
2175 2153 /* Now do relocations. */
2176 2154 for (i = 1; i < hdr->e_shnum; i++) {
2177 2155 const char *strtab = (char *)sechdrs[strindex].sh_addr;
2178 2156  
2179 2157  
2180 2158  
... ... @@ -2193,28 +2171,16 @@
2193 2171 if (err < 0)
2194 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 2174  
2207   -
2208 2175 /* Find duplicate symbols */
2209 2176 err = verify_export_symbols(mod);
2210   -
2211 2177 if (err < 0)
2212 2178 goto cleanup;
2213 2179  
2214 2180 /* Set up and sort exception table */
2215   - mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
2216   - mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
2217   - sort_extable(extable, extable + mod->num_exentries);
  2181 + mod->extable = section_objs(hdr, sechdrs, secstrings, "__ex_table",
  2182 + sizeof(*mod->extable), &mod->num_exentries);
  2183 + sort_extable(mod->extable, mod->extable + mod->num_exentries);
2218 2184  
2219 2185 /* Finally, copy percpu area over. */
2220 2186 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
2221 2187  
... ... @@ -2223,11 +2189,17 @@
2223 2189 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
2224 2190  
2225 2191 if (!mod->taints) {
  2192 + struct mod_debug *debug;
  2193 + unsigned int num_debug;
  2194 +
2226 2195 #ifdef CONFIG_MARKERS
2227 2196 marker_update_probe_range(mod->markers,
2228 2197 mod->markers + mod->num_markers);
2229 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 2203 #ifdef CONFIG_TRACEPOINTS
2232 2204 tracepoint_update_probe_range(mod->tracepoints,
2233 2205 mod->tracepoints + mod->num_tracepoints);
... ... @@ -2235,8 +2207,9 @@
2235 2207 }
2236 2208  
2237 2209 /* sechdrs[0].sh_size is always zero */
2238   - mseg = (void *)sechdrs[mcountindex].sh_addr;
2239   - ftrace_init_module(mseg, mseg + sechdrs[mcountindex].sh_size);
  2210 + mseg = section_objs(hdr, sechdrs, secstrings, "__mcount_loc",
  2211 + sizeof(*mseg), &num_mcount);
  2212 + ftrace_init_module(mseg, mseg + num_mcount);
2240 2213  
2241 2214 err = module_finalize(hdr, sechdrs, mod);
2242 2215 if (err < 0)
... ... @@ -2261,7 +2234,7 @@
2261 2234 set_fs(old_fs);
2262 2235  
2263 2236 mod->args = args;
2264   - if (obsparmindex)
  2237 + if (section_addr(hdr, sechdrs, secstrings, "__obsparm"))
2265 2238 printk(KERN_WARNING "%s: Ignoring obsolete parameters\n",
2266 2239 mod->name);
2267 2240  
2268 2241  
... ... @@ -2270,21 +2243,11 @@
2270 2243 * strong_try_module_get() will fail. */
2271 2244 stop_machine(__link_module, mod, NULL);
2272 2245  
2273   - /* Size of section 0 is 0, so this works well if no params */
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);
  2246 + err = parse_args(mod->name, mod->args, kp, num_kp, NULL);
2280 2247 if (err < 0)
2281 2248 goto unlink;
2282 2249  
2283   - err = mod_sysfs_setup(mod,
2284   - (struct kernel_param *)
2285   - sechdrs[setupindex].sh_addr,
2286   - sechdrs[setupindex].sh_size
2287   - / sizeof(struct kernel_param));
  2250 + err = mod_sysfs_setup(mod, kp, num_kp);
2288 2251 if (err < 0)
2289 2252 goto unlink;
2290 2253 add_sect_attrs(mod, hdr->e_shnum, secstrings, sechdrs);