aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2010-08-05 14:59:06 -0400
committerRusty Russell <rusty@rustcorp.com.au>2010-08-04 23:29:06 -0400
commit8b5f61a795fe37be090b0fd18b6b7271db9298e0 (patch)
tree4440e449af9207b25e62b4d8ad0dc16500720e65 /kernel/module.c
parent3264d3f9dd532ed9c3eb9491619e3f485b72747f (diff)
module: refactor out section header rewriting
Put all the "rewrite and check section headers" in one place. This adds another iteration over the sections, but it's far clearer. We iterate once for every find_section() so we already iterate over many times. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'kernel/module.c')
-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,