From 7c0d52e7a2f9033b6828a3eab5e2880db65c2bbf Mon Sep 17 00:00:00 2001 From: Ian May Date: Tue, 3 Oct 2023 22:25:27 -0500 Subject: [PATCH] Revert "UBUNTU: SAUCE: modpost: support arbitrary symbol length in modversion" This reverts commit 47d27f27577742dc486a9ad8ce439ae6f7f40dbb. We need to revert this to avoid regressing any modules used in Jammy. Signed-off-by: Ian May --- arch/powerpc/kernel/module_64.c | 5 ++--- include/linux/module.h | 8 +++----- kernel/module/version.c | 22 +++++++++++---------- scripts/export_report.pl | 9 ++++----- scripts/mod/modpost.c | 35 ++++++++++----------------------- 5 files changed, 31 insertions(+), 48 deletions(-) diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 195714fc6e22f..7112adc597a80 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -347,13 +347,12 @@ static unsigned long get_got_size(const Elf64_Ehdr *hdr, static void dedotify_versions(struct modversion_info *vers, unsigned long size) { - struct modversion_info *end = (void *)vers + size; + struct modversion_info *end; - for (; vers < end && vers->next; vers = (void *)vers + vers->next) { + for (end = (void *)vers + size; vers < end; vers++) if (vers->name[0] == '.') { memmove(vers->name, vers->name+1, strlen(vers->name)); } - } } /* diff --git a/include/linux/module.h b/include/linux/module.h index 98637f99db5c2..d88703a443e56 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -35,11 +35,9 @@ #define MODULE_NAME_LEN MAX_PARAM_PREFIX_LEN struct modversion_info { - /* Offset of the next modversion entry in relation to this one. */ - u32 next; - u32 crc; - char name[]; /* Flexible array member */ -} __packed; + unsigned long crc; + char name[MODULE_NAME_LEN]; +}; struct module; struct exception_table_entry; diff --git a/kernel/module/version.c b/kernel/module/version.c index 5528f98c42dc2..53f43ac5a73e9 100644 --- a/kernel/module/version.c +++ b/kernel/module/version.c @@ -17,30 +17,32 @@ int check_version(const struct load_info *info, { Elf_Shdr *sechdrs = info->sechdrs; unsigned int versindex = info->index.vers; - struct modversion_info *versions, *end; - u32 crcval; + unsigned int i, num_versions; + struct modversion_info *versions; /* Exporting module didn't supply crcs? OK, we're already tainted. */ if (!crc) return 1; - crcval = *crc; /* No versions at all? modprobe --force does this. */ if (versindex == 0) return try_to_force_load(mod, symname) == 0; versions = (void *)sechdrs[versindex].sh_addr; - end = (void *)versions + sechdrs[versindex].sh_size; + num_versions = sechdrs[versindex].sh_size + / sizeof(struct modversion_info); - for (; versions < end && versions->next; - versions = (void *)versions + versions->next) { - if (strcmp(versions->name, symname) != 0) + for (i = 0; i < num_versions; i++) { + u32 crcval; + + if (strcmp(versions[i].name, symname) != 0) continue; - if (versions->crc == crcval) + crcval = *crc; + if (versions[i].crc == crcval) return 1; - pr_debug("Found checksum %X vs module %X\n", - crcval, versions->crc); + pr_debug("Found checksum %X vs module %lX\n", + crcval, versions[i].crc); goto bad_version; } diff --git a/scripts/export_report.pl b/scripts/export_report.pl index 1117646f3141b..feb3d5542a62d 100755 --- a/scripts/export_report.pl +++ b/scripts/export_report.pl @@ -116,19 +116,18 @@ sub collectcfiles { while ( <$module> ) { chomp; if ($state == 0) { - $state = 1 if ($_ =~ /static const char ____versions/); + $state = 1 if ($_ =~ /static const struct modversion_info/); next; } if ($state == 1) { - $state = 2 if ($_ =~ /__used __section\("__versions"\)/); + $state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/); next; } if ($state == 2) { - if ( $_ !~ /\\0"/ ) { - last if ($_ =~ /;/); + if ( $_ !~ /0x[0-9a-f]+,/ ) { next; } - my $sym = (split /(["\\])/,)[2]; + my $sym = (split /([,"])/,)[4]; my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}}; $SYMBOL{ $sym } = [ $module, $value+1, $symbol, $gpl]; push(@{$MODULE{$thismod}} , $sym); diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 00c464dd33c4a..34adcbb56cba9 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1906,17 +1906,13 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod) static void add_versions(struct buffer *b, struct module *mod) { struct symbol *s; - unsigned int name_len; - unsigned int name_len_padded; - unsigned int tmp; - unsigned char *tmp_view = (unsigned char *)&tmp; if (!modversions) return; buf_printf(b, "\n"); - buf_printf(b, "static const char ____versions[]\n"); - buf_printf(b, "__used __section(\"__versions\") =\n"); + buf_printf(b, "static const struct modversion_info ____versions[]\n"); + buf_printf(b, "__used __section(\"__versions\") = {\n"); list_for_each_entry(s, &mod->unresolved_symbols, list) { if (!s->module) @@ -1926,27 +1922,16 @@ static void add_versions(struct buffer *b, struct module *mod) s->name, mod->name); continue; } - name_len = strlen(s->name); - name_len_padded = (name_len + 1 + 3) & ~3; - - /* Offset to next entry */ - tmp = 8 + name_len_padded; - tmp = TO_NATIVE(tmp); - buf_printf(b, "\t\"\\x%02x\\x%02x\\x%02x\\x%02x", - tmp_view[0], tmp_view[1], tmp_view[2], tmp_view[3]); - - tmp = TO_NATIVE(s->crc); - buf_printf(b, "\\x%02x\\x%02x\\x%02x\\x%02x\"\n", - tmp_view[0], tmp_view[1], tmp_view[2], tmp_view[3]); - - buf_printf(b, "\t\"%s", s->name); - for (; name_len < name_len_padded; name_len++) - buf_printf(b, "\\0"); - buf_printf(b, "\"\n"); + if (strlen(s->name) >= MODULE_NAME_LEN) { + error("too long symbol \"%s\" [%s.ko]\n", + s->name, mod->name); + break; + } + buf_printf(b, "\t{ %#8x, \"%s\" },\n", + s->crc, s->name); } - /* Always end with a NULL entry */ - buf_printf(b, "\t\"\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\";\n"); + buf_printf(b, "};\n"); } static void add_depends(struct buffer *b, struct module *mod)