diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2012-10-24 20:19:25 -0400 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-10-30 23:26:37 -0400 |
| commit | 59ef28b1f14899b10d6b2682c7057ca00a9a3f47 (patch) | |
| tree | 68ad548001fb24c0e63e1758d368a746998feb05 | |
| parent | bc909421a9c7083fcde795846d22b36a51a7be54 (diff) | |
module: fix out-by-one error in kallsyms
Masaki found and patched a kallsyms issue: the last symbol in a
module's symtab wasn't transferred. This is because we manually copy
the zero'th entry (which is always empty) then copy the rest in a loop
starting at 1, though from src[0]. His fix was minimal, I prefer to
rewrite the loops in more standard form.
There are two loops: one to get the size, and one to copy. Make these
identical: always count entry 0 and any defined symbol in an allocated
non-init section.
This bug exists since the following commit was introduced.
module: reduce symbol table for loaded modules (v2)
commit: 4a4962263f07d14660849ec134ee42b63e95ea9a
LKML: http://lkml.org/lkml/2012/10/24/27
Reported-by: Masaki Kimura <masaki.kimura.kz@hitachi.com>
Cc: stable@kernel.org
| -rw-r--r-- | kernel/module.c | 27 |
1 files changed, 16 insertions, 11 deletions
diff --git a/kernel/module.c b/kernel/module.c index 6085f5ef88ea..6e48c3a43599 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
| @@ -2293,12 +2293,17 @@ static void layout_symtab(struct module *mod, struct load_info *info) | |||
| 2293 | src = (void *)info->hdr + symsect->sh_offset; | 2293 | src = (void *)info->hdr + symsect->sh_offset; |
| 2294 | nsrc = symsect->sh_size / sizeof(*src); | 2294 | nsrc = symsect->sh_size / sizeof(*src); |
| 2295 | 2295 | ||
| 2296 | /* strtab always starts with a nul, so offset 0 is the empty string. */ | ||
| 2297 | strtab_size = 1; | ||
| 2298 | |||
| 2296 | /* Compute total space required for the core symbols' strtab. */ | 2299 | /* Compute total space required for the core symbols' strtab. */ |
| 2297 | for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) | 2300 | for (ndst = i = 0; i < nsrc; i++) { |
| 2298 | if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { | 2301 | if (i == 0 || |
| 2299 | strtab_size += strlen(&info->strtab[src->st_name]) + 1; | 2302 | is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { |
| 2303 | strtab_size += strlen(&info->strtab[src[i].st_name])+1; | ||
| 2300 | ndst++; | 2304 | ndst++; |
| 2301 | } | 2305 | } |
| 2306 | } | ||
| 2302 | 2307 | ||
| 2303 | /* Append room for core symbols at end of core part. */ | 2308 | /* Append room for core symbols at end of core part. */ |
| 2304 | info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); | 2309 | info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); |
| @@ -2332,15 +2337,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) | |||
| 2332 | mod->core_symtab = dst = mod->module_core + info->symoffs; | 2337 | mod->core_symtab = dst = mod->module_core + info->symoffs; |
| 2333 | mod->core_strtab = s = mod->module_core + info->stroffs; | 2338 | mod->core_strtab = s = mod->module_core + info->stroffs; |
| 2334 | src = mod->symtab; | 2339 | src = mod->symtab; |
| 2335 | *dst = *src; | ||
| 2336 | *s++ = 0; | 2340 | *s++ = 0; |
| 2337 | for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { | 2341 | for (ndst = i = 0; i < mod->num_symtab; i++) { |
| 2338 | if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) | 2342 | if (i == 0 || |
| 2339 | continue; | 2343 | is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { |
| 2340 | 2344 | dst[ndst] = src[i]; | |
| 2341 | dst[ndst] = *src; | 2345 | dst[ndst++].st_name = s - mod->core_strtab; |
| 2342 | dst[ndst++].st_name = s - mod->core_strtab; | 2346 | s += strlcpy(s, &mod->strtab[src[i].st_name], |
| 2343 | s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; | 2347 | KSYM_NAME_LEN) + 1; |
| 2348 | } | ||
| 2344 | } | 2349 | } |
| 2345 | mod->core_num_syms = ndst; | 2350 | mod->core_num_syms = ndst; |
| 2346 | } | 2351 | } |
