Skip to content

Commit 5fdc7db

Browse files
author
Jessica Yu
committed
module: setup load info before module_sig_check()
We want to be able to log the module name in early error messages, such as when module signature verification fails. Previously, the module name is set in layout_and_allocate(), meaning that any error messages that happen before (such as those in module_sig_check()) won't be logged with a module name, which isn't terribly helpful. In order to do this, reshuffle the order in load_module() and set up load info earlier so that we can log the module name along with these error messages. This requires splitting rewrite_section_headers() out of setup_load_info(). While we're at it, clean up and split up the operations done in layout_and_allocate(), setup_load_info(), and rewrite_section_headers() more cleanly so these functions only perform what their names suggest. Signed-off-by: Jessica Yu <[email protected]>
1 parent 81a0abd commit 5fdc7db

File tree

1 file changed

+43
-34
lines changed

1 file changed

+43
-34
lines changed

kernel/module.c

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,7 +2488,11 @@ static char *get_modinfo(struct load_info *info, const char *tag)
24882488
Elf_Shdr *infosec = &info->sechdrs[info->index.info];
24892489
unsigned long size = infosec->sh_size;
24902490

2491-
for (p = (char *)infosec->sh_addr; p; p = next_string(p, &size)) {
2491+
/*
2492+
* get_modinfo() calls made before rewrite_section_headers()
2493+
* must use sh_offset, as sh_addr isn't set!
2494+
*/
2495+
for (p = (char *)info->hdr + infosec->sh_offset; p; p = next_string(p, &size)) {
24922496
if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
24932497
return p + taglen + 1;
24942498
}
@@ -2928,17 +2932,7 @@ static int rewrite_section_headers(struct load_info *info, int flags)
29282932
}
29292933

29302934
/* Track but don't keep modinfo and version sections. */
2931-
if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
2932-
info->index.vers = 0; /* Pretend no __versions section! */
2933-
else
2934-
info->index.vers = find_sec(info, "__versions");
29352935
info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
2936-
2937-
info->index.info = find_sec(info, ".modinfo");
2938-
if (!info->index.info)
2939-
info->name = "(missing .modinfo section)";
2940-
else
2941-
info->name = get_modinfo(info, "name");
29422936
info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
29432937

29442938
return 0;
@@ -2955,16 +2949,18 @@ static int rewrite_section_headers(struct load_info *info, int flags)
29552949
static int setup_load_info(struct load_info *info, int flags)
29562950
{
29572951
unsigned int i;
2958-
int err;
29592952

29602953
/* Set up the convenience variables */
29612954
info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
29622955
info->secstrings = (void *)info->hdr
29632956
+ info->sechdrs[info->hdr->e_shstrndx].sh_offset;
29642957

2965-
err = rewrite_section_headers(info, flags);
2966-
if (err)
2967-
return err;
2958+
/* Try to find a name early so we can log errors with a module name */
2959+
info->index.info = find_sec(info, ".modinfo");
2960+
if (!info->index.info)
2961+
info->name = "(missing .modinfo section)";
2962+
else
2963+
info->name = get_modinfo(info, "name");
29682964

29692965
/* Find internal symbols and strings. */
29702966
for (i = 1; i < info->hdr->e_shnum; i++) {
@@ -2977,33 +2973,34 @@ static int setup_load_info(struct load_info *info, int flags)
29772973
}
29782974
}
29792975

2976+
if (info->index.sym == 0) {
2977+
pr_warn("%s: module has no symbols (stripped?)\n", info->name);
2978+
return -ENOEXEC;
2979+
}
2980+
29802981
info->index.mod = find_sec(info, ".gnu.linkonce.this_module");
29812982
if (!info->index.mod) {
29822983
pr_warn("%s: No module found in object\n",
29832984
info->name ?: "(missing .modinfo name field)");
29842985
return -ENOEXEC;
29852986
}
29862987
/* This is temporary: point mod into copy of data. */
2987-
info->mod = (void *)info->sechdrs[info->index.mod].sh_addr;
2988+
info->mod = (void *)info->hdr + info->sechdrs[info->index.mod].sh_offset;
29882989

29892990
/*
2990-
* If we didn't load the .modinfo 'name' field, fall back to
2991+
* If we didn't load the .modinfo 'name' field earlier, fall back to
29912992
* on-disk struct mod 'name' field.
29922993
*/
29932994
if (!info->name)
29942995
info->name = info->mod->name;
29952996

2996-
if (info->index.sym == 0) {
2997-
pr_warn("%s: module has no symbols (stripped?)\n", info->name);
2998-
return -ENOEXEC;
2999-
}
2997+
if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
2998+
info->index.vers = 0; /* Pretend no __versions section! */
2999+
else
3000+
info->index.vers = find_sec(info, "__versions");
30003001

30013002
info->index.pcpu = find_pcpusec(info);
30023003

3003-
/* Check module struct version now, before we try to use module. */
3004-
if (!check_modstruct_version(info, info->mod))
3005-
return -ENOEXEC;
3006-
30073004
return 0;
30083005
}
30093006

@@ -3303,13 +3300,6 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
33033300
unsigned int ndx;
33043301
int err;
33053302

3306-
err = setup_load_info(info, flags);
3307-
if (err)
3308-
return ERR_PTR(err);
3309-
3310-
if (blacklisted(info->name))
3311-
return ERR_PTR(-EPERM);
3312-
33133303
err = check_modinfo(info->mod, info, flags);
33143304
if (err)
33153305
return ERR_PTR(err);
@@ -3657,17 +3647,36 @@ static int load_module(struct load_info *info, const char __user *uargs,
36573647
int flags)
36583648
{
36593649
struct module *mod;
3660-
long err;
3650+
long err = 0;
36613651
char *after_dashes;
36623652

3653+
err = elf_header_check(info);
3654+
if (err)
3655+
goto free_copy;
3656+
3657+
err = setup_load_info(info, flags);
3658+
if (err)
3659+
goto free_copy;
3660+
3661+
if (blacklisted(info->name)) {
3662+
err = -EPERM;
3663+
goto free_copy;
3664+
}
3665+
36633666
err = module_sig_check(info, flags);
36643667
if (err)
36653668
goto free_copy;
36663669

3667-
err = elf_header_check(info);
3670+
err = rewrite_section_headers(info, flags);
36683671
if (err)
36693672
goto free_copy;
36703673

3674+
/* Check module struct version now, before we try to use module. */
3675+
if (!check_modstruct_version(info, info->mod)) {
3676+
err = -ENOEXEC;
3677+
goto free_copy;
3678+
}
3679+
36713680
/* Figure out module layout, and allocate all the memory. */
36723681
mod = layout_and_allocate(info, flags);
36733682
if (IS_ERR(mod)) {

0 commit comments

Comments
 (0)