aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/module.c70
1 files changed, 45 insertions, 25 deletions
diff --git a/kernel/module.c b/kernel/module.c
index cb40a4e64a0e..91f3ebe230e3 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2158,6 +2158,7 @@ struct load_info {
2158 } index; 2158 } index;
2159}; 2159};
2160 2160
2161/* Sets info->hdr and info->len. */
2161static int copy_and_check(struct load_info *info, const void __user *umod, unsigned long len) 2162static int copy_and_check(struct load_info *info, const void __user *umod, unsigned long len)
2162{ 2163{
2163 int err; 2164 int err;
@@ -2199,6 +2200,39 @@ free_hdr:
2199 return err; 2200 return err;
2200} 2201}
2201 2202
2203static int rewrite_section_headers(struct load_info *info)
2204{
2205 unsigned int i;
2206
2207 /* This should always be true, but let's be sure. */
2208 info->sechdrs[0].sh_addr = 0;
2209
2210 for (i = 1; i < info->hdr->e_shnum; i++) {
2211 Elf_Shdr *shdr = &info->sechdrs[i];
2212 if (shdr->sh_type != SHT_NOBITS
2213 && info->len < shdr->sh_offset + shdr->sh_size) {
2214 printk(KERN_ERR "Module len %lu truncated\n",
2215 info->len);
2216 return -ENOEXEC;
2217 }
2218
2219 /* Mark all sections sh_addr with their address in the
2220 temporary image. */
2221 shdr->sh_addr = (size_t)info->hdr + shdr->sh_offset;
2222
2223#ifndef CONFIG_MODULE_UNLOAD
2224 /* Don't load .exit sections */
2225 if (strstarts(info->secstrings+shdr->sh_name, ".exit"))
2226 shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;
2227#endif
2228 /* Don't keep modinfo and version sections. */
2229 if (!strcmp(info->secstrings+shdr->sh_name, "__versions")
2230 || !strcmp(info->secstrings+shdr->sh_name, ".modinfo"))
2231 shdr->sh_flags &= ~(unsigned long)SHF_ALLOC;
2232 }
2233 return 0;
2234}
2235
2202/* 2236/*
2203 * Set up our basic convenience variables (pointers to section headers, 2237 * Set up our basic convenience variables (pointers to section headers,
2204 * search for module section index etc), and do some basic section 2238 * search for module section index etc), and do some basic section
@@ -2210,33 +2244,27 @@ free_hdr:
2210static struct module *setup_load_info(struct load_info *info) 2244static struct module *setup_load_info(struct load_info *info)
2211{ 2245{
2212 unsigned int i; 2246 unsigned int i;
2247 int err;
2213 struct module *mod; 2248 struct module *mod;
2214 2249
2215 /* Set up the convenience variables */ 2250 /* Set up the convenience variables */
2216 info->sechdrs = (void *)info->hdr + info->hdr->e_shoff; 2251 info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
2217 info->secstrings = (void *)info->hdr + info->sechdrs[info->hdr->e_shstrndx].sh_offset; 2252 info->secstrings = (void *)info->hdr
2218 info->sechdrs[0].sh_addr = 0; 2253 + info->sechdrs[info->hdr->e_shstrndx].sh_offset;
2219
2220 for (i = 1; i < info->hdr->e_shnum; i++) {
2221 if (info->sechdrs[i].sh_type != SHT_NOBITS
2222 && info->len < info->sechdrs[i].sh_offset + info->sechdrs[i].sh_size)
2223 goto truncated;
2224 2254
2225 /* Mark all sections sh_addr with their address in the 2255 err = rewrite_section_headers(info);
2226 temporary image. */ 2256 if (err)
2227 info->sechdrs[i].sh_addr = (size_t)info->hdr + info->sechdrs[i].sh_offset; 2257 return ERR_PTR(err);
2228 2258
2229 /* Internal symbols and strings. */ 2259 /* Find internal symbols and strings. */
2260 for (i = 1; i < info->hdr->e_shnum; i++) {
2230 if (info->sechdrs[i].sh_type == SHT_SYMTAB) { 2261 if (info->sechdrs[i].sh_type == SHT_SYMTAB) {
2231 info->index.sym = i; 2262 info->index.sym = i;
2232 info->index.str = info->sechdrs[i].sh_link; 2263 info->index.str = info->sechdrs[i].sh_link;
2233 info->strtab = (char *)info->hdr + info->sechdrs[info->index.str].sh_offset; 2264 info->strtab = (char *)info->hdr
2265 + info->sechdrs[info->index.str].sh_offset;
2266 break;
2234 } 2267 }
2235#ifndef CONFIG_MODULE_UNLOAD
2236 /* Don't load .exit sections */
2237 if (strstarts(info->secstrings+info->sechdrs[i].sh_name, ".exit"))
2238 info->sechdrs[i].sh_flags &= ~(unsigned long)SHF_ALLOC;
2239#endif
2240 } 2268 }
2241 2269
2242 info->index.mod = find_sec(info->hdr, info->sechdrs, info->secstrings, 2270 info->index.mod = find_sec(info->hdr, info->sechdrs, info->secstrings,
@@ -2258,19 +2286,11 @@ static struct module *setup_load_info(struct load_info *info)
2258 info->index.info = find_sec(info->hdr, info->sechdrs, info->secstrings, ".modinfo"); 2286 info->index.info = find_sec(info->hdr, info->sechdrs, info->secstrings, ".modinfo");
2259 info->index.pcpu = find_pcpusec(info->hdr, info->sechdrs, info->secstrings); 2287 info->index.pcpu = find_pcpusec(info->hdr, info->sechdrs, info->secstrings);
2260 2288
2261 /* Don't keep modinfo and version sections. */
2262 info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
2263 info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
2264
2265 /* Check module struct version now, before we try to use module. */ 2289 /* Check module struct version now, before we try to use module. */
2266 if (!check_modstruct_version(info->sechdrs, info->index.vers, mod)) 2290 if (!check_modstruct_version(info->sechdrs, info->index.vers, mod))
2267 return ERR_PTR(-ENOEXEC); 2291 return ERR_PTR(-ENOEXEC);
2268 2292
2269 return mod; 2293 return mod;
2270
2271 truncated:
2272 printk(KERN_ERR "Module len %lu truncated\n", info->len);
2273 return ERR_PTR(-ENOEXEC);
2274} 2294}
2275 2295
2276static int check_modinfo(struct module *mod, 2296static int check_modinfo(struct module *mod,