* [PATCH v5 01/16] module: Take const arg in validate_section_offset
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 02/16] module: Factor out elf_validity_ehdr Matthew Maurer
` (16 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
`validate_section_offset` doesn't modify the info passed in. Make this
clear by adjusting the type signature.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 49b9bca9de12..1a2dd52147ba 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1645,7 +1645,7 @@ bool __weak module_exit_section(const char *name)
return strstarts(name, ".exit");
}
-static int validate_section_offset(struct load_info *info, Elf_Shdr *shdr)
+static int validate_section_offset(const struct load_info *info, Elf_Shdr *shdr)
{
#if defined(CONFIG_64BIT)
unsigned long long secend;
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 02/16] module: Factor out elf_validity_ehdr
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 01/16] module: Take const arg in validate_section_offset Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 03/16] module: Factor out elf_validity_cache_sechdrs Matthew Maurer
` (15 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Factor out verification of the ELF header and document what is checked.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 70 +++++++++++++++++++++++++++++---------------
1 file changed, 47 insertions(+), 23 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 1a2dd52147ba..59c977acfb44 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1664,6 +1664,50 @@ static int validate_section_offset(const struct load_info *info, Elf_Shdr *shdr)
return 0;
}
+/**
+ * elf_validity_ehdr() - Checks an ELF header for module validity
+ * @info: Load info containing the ELF header to check
+ *
+ * Checks whether an ELF header could belong to a valid module. Checks:
+ *
+ * * ELF header is within the data the user provided
+ * * ELF magic is present
+ * * It is relocatable (not final linked, not core file, etc.)
+ * * The header's machine type matches what the architecture expects.
+ * * Optional arch-specific hook for other properties
+ * - module_elf_check_arch() is currently only used by PPC to check
+ * ELF ABI version, but may be used by others in the future.
+ *
+ * Return: %0 if valid, %-ENOEXEC on failure.
+ */
+static int elf_validity_ehdr(const struct load_info *info)
+{
+ if (info->len < sizeof(*(info->hdr))) {
+ pr_err("Invalid ELF header len %lu\n", info->len);
+ return -ENOEXEC;
+ }
+ if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0) {
+ pr_err("Invalid ELF header magic: != %s\n", ELFMAG);
+ return -ENOEXEC;
+ }
+ if (info->hdr->e_type != ET_REL) {
+ pr_err("Invalid ELF header type: %u != %u\n",
+ info->hdr->e_type, ET_REL);
+ return -ENOEXEC;
+ }
+ if (!elf_check_arch(info->hdr)) {
+ pr_err("Invalid architecture in ELF header: %u\n",
+ info->hdr->e_machine);
+ return -ENOEXEC;
+ }
+ if (!module_elf_check_arch(info->hdr)) {
+ pr_err("Invalid module architecture in ELF header: %u\n",
+ info->hdr->e_machine);
+ return -ENOEXEC;
+ }
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -1693,30 +1737,10 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
unsigned int num_info_secs = 0, info_idx;
unsigned int num_sym_secs = 0, sym_idx;
- if (info->len < sizeof(*(info->hdr))) {
- pr_err("Invalid ELF header len %lu\n", info->len);
- goto no_exec;
- }
+ err = elf_validity_ehdr(info);
+ if (err < 0)
+ return err;
- if (memcmp(info->hdr->e_ident, ELFMAG, SELFMAG) != 0) {
- pr_err("Invalid ELF header magic: != %s\n", ELFMAG);
- goto no_exec;
- }
- if (info->hdr->e_type != ET_REL) {
- pr_err("Invalid ELF header type: %u != %u\n",
- info->hdr->e_type, ET_REL);
- goto no_exec;
- }
- if (!elf_check_arch(info->hdr)) {
- pr_err("Invalid architecture in ELF header: %u\n",
- info->hdr->e_machine);
- goto no_exec;
- }
- if (!module_elf_check_arch(info->hdr)) {
- pr_err("Invalid module architecture in ELF header: %u\n",
- info->hdr->e_machine);
- goto no_exec;
- }
if (info->hdr->e_shentsize != sizeof(Elf_Shdr)) {
pr_err("Invalid ELF section header size\n");
goto no_exec;
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 03/16] module: Factor out elf_validity_cache_sechdrs
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 01/16] module: Take const arg in validate_section_offset Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 02/16] module: Factor out elf_validity_ehdr Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 04/16] module: Factor out elf_validity_cache_secstrings Matthew Maurer
` (14 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Factor out and document the validation of section headers.
Because we now validate all section offsets and lengths before accessing
them, we can remove the ad-hoc checks.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 125 ++++++++++++++++++++++++++++---------------
1 file changed, 82 insertions(+), 43 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 59c977acfb44..1f3a07ee59c6 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1708,6 +1708,87 @@ static int elf_validity_ehdr(const struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_sechdrs() - Cache section headers if valid
+ * @info: Load info to compute section headers from
+ *
+ * Checks:
+ *
+ * * ELF header is valid (see elf_validity_ehdr())
+ * * Section headers are the size we expect
+ * * Section array fits in the user provided data
+ * * Section index 0 is NULL
+ * * Section contents are inbounds
+ *
+ * Then updates @info with a &load_info->sechdrs pointer if valid.
+ *
+ * Return: %0 if valid, negative error code if validation failed.
+ */
+static int elf_validity_cache_sechdrs(struct load_info *info)
+{
+ Elf_Shdr *sechdrs;
+ Elf_Shdr *shdr;
+ int i;
+ int err;
+
+ err = elf_validity_ehdr(info);
+ if (err < 0)
+ return err;
+
+ if (info->hdr->e_shentsize != sizeof(Elf_Shdr)) {
+ pr_err("Invalid ELF section header size\n");
+ return -ENOEXEC;
+ }
+
+ /*
+ * e_shnum is 16 bits, and sizeof(Elf_Shdr) is
+ * known and small. So e_shnum * sizeof(Elf_Shdr)
+ * will not overflow unsigned long on any platform.
+ */
+ if (info->hdr->e_shoff >= info->len
+ || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
+ info->len - info->hdr->e_shoff)) {
+ pr_err("Invalid ELF section header overflow\n");
+ return -ENOEXEC;
+ }
+
+ sechdrs = (void *)info->hdr + info->hdr->e_shoff;
+
+ /*
+ * The code assumes that section 0 has a length of zero and
+ * an addr of zero, so check for it.
+ */
+ if (sechdrs[0].sh_type != SHT_NULL
+ || sechdrs[0].sh_size != 0
+ || sechdrs[0].sh_addr != 0) {
+ pr_err("ELF Spec violation: section 0 type(%d)!=SH_NULL or non-zero len or addr\n",
+ sechdrs[0].sh_type);
+ return -ENOEXEC;
+ }
+
+ /* Validate contents are inbounds */
+ for (i = 1; i < info->hdr->e_shnum; i++) {
+ shdr = &sechdrs[i];
+ switch (shdr->sh_type) {
+ case SHT_NULL:
+ case SHT_NOBITS:
+ /* No contents, offset/size don't mean anything */
+ continue;
+ default:
+ err = validate_section_offset(info, shdr);
+ if (err < 0) {
+ pr_err("Invalid ELF section in module (section %u type %u)\n",
+ i, shdr->sh_type);
+ return err;
+ }
+ }
+ }
+
+ info->sechdrs = sechdrs;
+
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -1737,29 +1818,10 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
unsigned int num_info_secs = 0, info_idx;
unsigned int num_sym_secs = 0, sym_idx;
- err = elf_validity_ehdr(info);
+ err = elf_validity_cache_sechdrs(info);
if (err < 0)
return err;
- if (info->hdr->e_shentsize != sizeof(Elf_Shdr)) {
- pr_err("Invalid ELF section header size\n");
- goto no_exec;
- }
-
- /*
- * e_shnum is 16 bits, and sizeof(Elf_Shdr) is
- * known and small. So e_shnum * sizeof(Elf_Shdr)
- * will not overflow unsigned long on any platform.
- */
- if (info->hdr->e_shoff >= info->len
- || (info->hdr->e_shnum * sizeof(Elf_Shdr) >
- info->len - info->hdr->e_shoff)) {
- pr_err("Invalid ELF section header overflow\n");
- goto no_exec;
- }
-
- info->sechdrs = (void *)info->hdr + info->hdr->e_shoff;
-
/*
* Verify if the section name table index is valid.
*/
@@ -1772,11 +1834,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
}
strhdr = &info->sechdrs[info->hdr->e_shstrndx];
- err = validate_section_offset(info, strhdr);
- if (err < 0) {
- pr_err("Invalid ELF section hdr(type %u)\n", strhdr->sh_type);
- return err;
- }
/*
* The section name table must be NUL-terminated, as required
@@ -1793,18 +1850,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
goto no_exec;
}
- /*
- * The code assumes that section 0 has a length of zero and
- * an addr of zero, so check for it.
- */
- if (info->sechdrs[0].sh_type != SHT_NULL
- || info->sechdrs[0].sh_size != 0
- || info->sechdrs[0].sh_addr != 0) {
- pr_err("ELF Spec violation: section 0 type(%d)!=SH_NULL or non-zero len or addr\n",
- info->sechdrs[0].sh_type);
- goto no_exec;
- }
-
for (i = 1; i < info->hdr->e_shnum; i++) {
shdr = &info->sechdrs[i];
switch (shdr->sh_type) {
@@ -1823,12 +1868,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
sym_idx = i;
fallthrough;
default:
- err = validate_section_offset(info, shdr);
- if (err < 0) {
- pr_err("Invalid ELF section in module (section %u type %u)\n",
- i, shdr->sh_type);
- return err;
- }
if (strcmp(info->secstrings + shdr->sh_name,
".gnu.linkonce.this_module") == 0) {
num_mod_secs++;
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 04/16] module: Factor out elf_validity_cache_secstrings
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (2 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 03/16] module: Factor out elf_validity_cache_sechdrs Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 05/16] module: Factor out elf_validity_cache_index_info Matthew Maurer
` (13 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Factor out the validation of section names.
There are two behavioral changes:
1. Previously, we did not validate non-SHF_ALLOC sections.
This may have once been safe, as find_sec skips non-SHF_ALLOC
sections, but find_any_sec, which will be used to load BTF if that is
enabled, ignores the SHF_ALLOC flag. Since there's no need to support
invalid section names, validate all of them, not just SHF_ALLOC
sections.
2. Section names were validated *after* accessing them for the purposes
of detecting ".modinfo" and ".gnu.linkonce.this_module". They are now
checked prior to the access, which could avoid bad accesses with
malformed modules.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 106 ++++++++++++++++++++++++++++---------------
1 file changed, 69 insertions(+), 37 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 1f3a07ee59c6..6a9159afca02 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1789,6 +1789,71 @@ static int elf_validity_cache_sechdrs(struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_secstrings() - Caches section names if valid
+ * @info: Load info to cache section names from. Must have valid sechdrs.
+ *
+ * Specifically checks:
+ *
+ * * Section name table index is inbounds of section headers
+ * * Section name table is not empty
+ * * Section name table is NUL terminated
+ * * All section name offsets are inbounds of the section
+ *
+ * Then updates @info with a &load_info->secstrings pointer if valid.
+ *
+ * Return: %0 if valid, negative error code if validation failed.
+ */
+static int elf_validity_cache_secstrings(struct load_info *info)
+{
+ Elf_Shdr *strhdr, *shdr;
+ char *secstrings;
+ int i;
+
+ /*
+ * Verify if the section name table index is valid.
+ */
+ if (info->hdr->e_shstrndx == SHN_UNDEF
+ || info->hdr->e_shstrndx >= info->hdr->e_shnum) {
+ pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n",
+ info->hdr->e_shstrndx, info->hdr->e_shstrndx,
+ info->hdr->e_shnum);
+ return -ENOEXEC;
+ }
+
+ strhdr = &info->sechdrs[info->hdr->e_shstrndx];
+
+ /*
+ * The section name table must be NUL-terminated, as required
+ * by the spec. This makes strcmp and pr_* calls that access
+ * strings in the section safe.
+ */
+ secstrings = (void *)info->hdr + strhdr->sh_offset;
+ if (strhdr->sh_size == 0) {
+ pr_err("empty section name table\n");
+ return -ENOEXEC;
+ }
+ if (secstrings[strhdr->sh_size - 1] != '\0') {
+ pr_err("ELF Spec violation: section name table isn't null terminated\n");
+ return -ENOEXEC;
+ }
+
+ for (i = 0; i < info->hdr->e_shnum; i++) {
+ shdr = &info->sechdrs[i];
+ /* SHT_NULL means sh_name has an undefined value */
+ if (shdr->sh_type == SHT_NULL)
+ continue;
+ if (shdr->sh_name >= strhdr->sh_size) {
+ pr_err("Invalid ELF section name in module (section %u type %u)\n",
+ i, shdr->sh_type);
+ return -ENOEXEC;
+ }
+ }
+
+ info->secstrings = secstrings;
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -1812,7 +1877,7 @@ static int elf_validity_cache_sechdrs(struct load_info *info)
static int elf_validity_cache_copy(struct load_info *info, int flags)
{
unsigned int i;
- Elf_Shdr *shdr, *strhdr;
+ Elf_Shdr *shdr;
int err;
unsigned int num_mod_secs = 0, mod_idx;
unsigned int num_info_secs = 0, info_idx;
@@ -1821,34 +1886,9 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
err = elf_validity_cache_sechdrs(info);
if (err < 0)
return err;
-
- /*
- * Verify if the section name table index is valid.
- */
- if (info->hdr->e_shstrndx == SHN_UNDEF
- || info->hdr->e_shstrndx >= info->hdr->e_shnum) {
- pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n",
- info->hdr->e_shstrndx, info->hdr->e_shstrndx,
- info->hdr->e_shnum);
- goto no_exec;
- }
-
- strhdr = &info->sechdrs[info->hdr->e_shstrndx];
-
- /*
- * The section name table must be NUL-terminated, as required
- * by the spec. This makes strcmp and pr_* calls that access
- * strings in the section safe.
- */
- info->secstrings = (void *)info->hdr + strhdr->sh_offset;
- if (strhdr->sh_size == 0) {
- pr_err("empty section name table\n");
- goto no_exec;
- }
- if (info->secstrings[strhdr->sh_size - 1] != '\0') {
- pr_err("ELF Spec violation: section name table isn't null terminated\n");
- goto no_exec;
- }
+ err = elf_validity_cache_secstrings(info);
+ if (err < 0)
+ return err;
for (i = 1; i < info->hdr->e_shnum; i++) {
shdr = &info->sechdrs[i];
@@ -1877,14 +1917,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
num_info_secs++;
info_idx = i;
}
-
- if (shdr->sh_flags & SHF_ALLOC) {
- if (shdr->sh_name >= strhdr->sh_size) {
- pr_err("Invalid ELF section name in module (section %u type %u)\n",
- i, shdr->sh_type);
- return -ENOEXEC;
- }
- }
break;
}
}
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 05/16] module: Factor out elf_validity_cache_index_info
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (3 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 04/16] module: Factor out elf_validity_cache_secstrings Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 06/16] module: Factor out elf_validity_cache_index_mod Matthew Maurer
` (12 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Centralize .modinfo detection and property validation.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 82 ++++++++++++++++++++++++++++++++++++--------
1 file changed, 68 insertions(+), 14 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 6a9159afca02..511d645ac577 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name)
return 0;
}
+/**
+ * find_any_unique_sec() - Find a unique section index by name
+ * @info: Load info for the module to scan
+ * @name: Name of the section we're looking for
+ *
+ * Locates a unique section by name. Ignores SHF_ALLOC.
+ *
+ * Return: Section index if found uniquely, zero if absent, negative count
+ * of total instances if multiple were found.
+ */
+static int find_any_unique_sec(const struct load_info *info, const char *name)
+{
+ unsigned int idx;
+ unsigned int count = 0;
+ int i;
+
+ for (i = 1; i < info->hdr->e_shnum; i++) {
+ if (strcmp(info->secstrings + info->sechdrs[i].sh_name,
+ name) == 0) {
+ count++;
+ idx = i;
+ }
+ }
+ if (count == 1) {
+ return idx;
+ } else if (count == 0) {
+ return 0;
+ } else {
+ return -count;
+ }
+}
+
/* Find a module section, or NULL. */
static void *section_addr(const struct load_info *info, const char *name)
{
@@ -1854,6 +1886,39 @@ static int elf_validity_cache_secstrings(struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_index_info() - Validate and cache modinfo section
+ * @info: Load info to populate the modinfo index on.
+ * Must have &load_info->sechdrs and &load_info->secstrings populated
+ *
+ * Checks that if there is a .modinfo section, it is unique.
+ * Then, it caches its index in &load_info->index.info.
+ * Finally, it tries to populate the name to improve error messages.
+ *
+ * Return: %0 if valid, %-ENOEXEC if multiple modinfo sections were found.
+ */
+static int elf_validity_cache_index_info(struct load_info *info)
+{
+ int info_idx;
+
+ info_idx = find_any_unique_sec(info, ".modinfo");
+
+ if (info_idx == 0)
+ /* Early return, no .modinfo */
+ return 0;
+
+ if (info_idx < 0) {
+ pr_err("Only one .modinfo section must exist.\n");
+ return -ENOEXEC;
+ }
+
+ info->index.info = info_idx;
+ /* Try to find a name early so we can log errors with a module name */
+ info->name = get_modinfo(info, "name");
+
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -1880,13 +1945,15 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
Elf_Shdr *shdr;
int err;
unsigned int num_mod_secs = 0, mod_idx;
- unsigned int num_info_secs = 0, info_idx;
unsigned int num_sym_secs = 0, sym_idx;
err = elf_validity_cache_sechdrs(info);
if (err < 0)
return err;
err = elf_validity_cache_secstrings(info);
+ if (err < 0)
+ return err;
+ err = elf_validity_cache_index_info(info);
if (err < 0)
return err;
@@ -1912,24 +1979,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
".gnu.linkonce.this_module") == 0) {
num_mod_secs++;
mod_idx = i;
- } else if (strcmp(info->secstrings + shdr->sh_name,
- ".modinfo") == 0) {
- num_info_secs++;
- info_idx = i;
}
break;
}
}
- if (num_info_secs > 1) {
- pr_err("Only one .modinfo section must exist.\n");
- goto no_exec;
- } else if (num_info_secs == 1) {
- /* Try to find a name early so we can log errors with a module name */
- info->index.info = info_idx;
- info->name = get_modinfo(info, "name");
- }
-
if (num_sym_secs != 1) {
pr_warn("%s: module has no symbols (stripped?)\n",
info->name ?: "(missing .modinfo section or name field)");
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 06/16] module: Factor out elf_validity_cache_index_mod
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (4 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 05/16] module: Factor out elf_validity_cache_index_info Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 07/16] module: Factor out elf_validity_cache_index_sym Matthew Maurer
` (11 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Centralize .gnu.linkonce.this_module detection and property validation.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 129 ++++++++++++++++++++++---------------------
1 file changed, 67 insertions(+), 62 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 511d645ac577..ec638187ffcf 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1919,6 +1919,68 @@ static int elf_validity_cache_index_info(struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_index_mod() - Validates and caches this_module section
+ * @info: Load info to cache this_module on.
+ * Must have &load_info->sechdrs and &load_info->secstrings populated
+ *
+ * The ".gnu.linkonce.this_module" ELF section is special. It is what modpost
+ * uses to refer to __this_module and let's use rely on THIS_MODULE to point
+ * to &__this_module properly. The kernel's modpost declares it on each
+ * modules's *.mod.c file. If the struct module of the kernel changes a full
+ * kernel rebuild is required.
+ *
+ * We have a few expectations for this special section, this function
+ * validates all this for us:
+ *
+ * * The section has contents
+ * * The section is unique
+ * * We expect the kernel to always have to allocate it: SHF_ALLOC
+ * * The section size must match the kernel's run time's struct module
+ * size
+ *
+ * If all checks pass, the index will be cached in &load_info->index.mod
+ *
+ * Return: %0 on validation success, %-ENOEXEC on failure
+ */
+static int elf_validity_cache_index_mod(struct load_info *info)
+{
+ Elf_Shdr *shdr;
+ int mod_idx;
+
+ mod_idx = find_any_unique_sec(info, ".gnu.linkonce.this_module");
+ if (mod_idx <= 0) {
+ pr_err("module %s: Exactly one .gnu.linkonce.this_module section must exist.\n",
+ info->name ?: "(missing .modinfo section or name field)");
+ return -ENOEXEC;
+ }
+
+ shdr = &info->sechdrs[mod_idx];
+
+ if (shdr->sh_type == SHT_NOBITS) {
+ pr_err("module %s: .gnu.linkonce.this_module section must have a size set\n",
+ info->name ?: "(missing .modinfo section or name field)");
+ return -ENOEXEC;
+ }
+
+ if (!(shdr->sh_flags & SHF_ALLOC)) {
+ pr_err("module %s: .gnu.linkonce.this_module must occupy memory during process execution\n",
+ info->name ?: "(missing .modinfo section or name field)");
+ return -ENOEXEC;
+ }
+
+ if (shdr->sh_size != sizeof(struct module)) {
+ pr_err("module %s: .gnu.linkonce.this_module section size must match the kernel's built struct module size at run time\n",
+ info->name ?: "(missing .modinfo section or name field)");
+ return -ENOEXEC;
+ }
+
+ info->index.mod = mod_idx;
+
+ return 0;
+}
+
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -1944,7 +2006,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
unsigned int i;
Elf_Shdr *shdr;
int err;
- unsigned int num_mod_secs = 0, mod_idx;
unsigned int num_sym_secs = 0, sym_idx;
err = elf_validity_cache_sechdrs(info);
@@ -1954,16 +2015,15 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
if (err < 0)
return err;
err = elf_validity_cache_index_info(info);
+ if (err < 0)
+ return err;
+ err = elf_validity_cache_index_mod(info);
if (err < 0)
return err;
for (i = 1; i < info->hdr->e_shnum; i++) {
shdr = &info->sechdrs[i];
- switch (shdr->sh_type) {
- case SHT_NULL:
- case SHT_NOBITS:
- continue;
- case SHT_SYMTAB:
+ if (shdr->sh_type == SHT_SYMTAB) {
if (shdr->sh_link == SHN_UNDEF
|| shdr->sh_link >= info->hdr->e_shnum) {
pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n",
@@ -1973,14 +2033,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
}
num_sym_secs++;
sym_idx = i;
- fallthrough;
- default:
- if (strcmp(info->secstrings + shdr->sh_name,
- ".gnu.linkonce.this_module") == 0) {
- num_mod_secs++;
- mod_idx = i;
- }
- break;
}
}
@@ -1996,55 +2048,8 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
info->index.str = shdr->sh_link;
info->strtab = (char *)info->hdr + info->sechdrs[info->index.str].sh_offset;
- /*
- * The ".gnu.linkonce.this_module" ELF section is special. It is
- * what modpost uses to refer to __this_module and let's use rely
- * on THIS_MODULE to point to &__this_module properly. The kernel's
- * modpost declares it on each modules's *.mod.c file. If the struct
- * module of the kernel changes a full kernel rebuild is required.
- *
- * We have a few expectaions for this special section, the following
- * code validates all this for us:
- *
- * o Only one section must exist
- * o We expect the kernel to always have to allocate it: SHF_ALLOC
- * o The section size must match the kernel's run time's struct module
- * size
- */
- if (num_mod_secs != 1) {
- pr_err("module %s: Only one .gnu.linkonce.this_module section must exist.\n",
- info->name ?: "(missing .modinfo section or name field)");
- goto no_exec;
- }
-
- shdr = &info->sechdrs[mod_idx];
-
- /*
- * This is already implied on the switch above, however let's be
- * pedantic about it.
- */
- if (shdr->sh_type == SHT_NOBITS) {
- pr_err("module %s: .gnu.linkonce.this_module section must have a size set\n",
- info->name ?: "(missing .modinfo section or name field)");
- goto no_exec;
- }
-
- if (!(shdr->sh_flags & SHF_ALLOC)) {
- pr_err("module %s: .gnu.linkonce.this_module must occupy memory during process execution\n",
- info->name ?: "(missing .modinfo section or name field)");
- goto no_exec;
- }
-
- if (shdr->sh_size != sizeof(struct module)) {
- pr_err("module %s: .gnu.linkonce.this_module section size must match the kernel's built struct module size at run time\n",
- info->name ?: "(missing .modinfo section or name field)");
- goto no_exec;
- }
-
- info->index.mod = mod_idx;
-
/* This is temporary: point mod into copy of data. */
- info->mod = (void *)info->hdr + shdr->sh_offset;
+ info->mod = (void *)info->hdr + info->sechdrs[info->index.mod].sh_offset;
/*
* If we didn't load the .modinfo 'name' field earlier, fall back to
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 07/16] module: Factor out elf_validity_cache_index_sym
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (5 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 06/16] module: Factor out elf_validity_cache_index_mod Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 08/16] module: Factor out elf_validity_cache_index_str Matthew Maurer
` (10 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Centralize symbol table detection and property validation.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 73 ++++++++++++++++++++++++++------------------
1 file changed, 44 insertions(+), 29 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index ec638187ffcf..6be58b0a6468 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -1980,6 +1980,39 @@ static int elf_validity_cache_index_mod(struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_index_sym() - Validate and cache symtab index
+ * @info: Load info to cache symtab index in.
+ * Must have &load_info->sechdrs and &load_info->secstrings populated.
+ *
+ * Checks that there is exactly one symbol table, then caches its index in
+ * &load_info->index.sym.
+ *
+ * Return: %0 if valid, %-ENOEXEC on failure.
+ */
+static int elf_validity_cache_index_sym(struct load_info *info)
+{
+ unsigned int sym_idx;
+ unsigned int num_sym_secs = 0;
+ int i;
+
+ for (i = 1; i < info->hdr->e_shnum; i++) {
+ if (info->sechdrs[i].sh_type == SHT_SYMTAB) {
+ num_sym_secs++;
+ sym_idx = i;
+ }
+ }
+
+ if (num_sym_secs != 1) {
+ pr_warn("%s: module has no symbols (stripped?)\n",
+ info->name ?: "(missing .modinfo section or name field)");
+ return -ENOEXEC;
+ }
+
+ info->index.sym = sym_idx;
+
+ return 0;
+}
/*
* Check userspace passed ELF module against our expectations, and cache
@@ -2003,10 +2036,8 @@ static int elf_validity_cache_index_mod(struct load_info *info)
*/
static int elf_validity_cache_copy(struct load_info *info, int flags)
{
- unsigned int i;
- Elf_Shdr *shdr;
int err;
- unsigned int num_sym_secs = 0, sym_idx;
+ int str_idx;
err = elf_validity_cache_sechdrs(info);
if (err < 0)
@@ -2018,34 +2049,21 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
if (err < 0)
return err;
err = elf_validity_cache_index_mod(info);
+ if (err < 0)
+ return err;
+ err = elf_validity_cache_index_sym(info);
if (err < 0)
return err;
- for (i = 1; i < info->hdr->e_shnum; i++) {
- shdr = &info->sechdrs[i];
- if (shdr->sh_type == SHT_SYMTAB) {
- if (shdr->sh_link == SHN_UNDEF
- || shdr->sh_link >= info->hdr->e_shnum) {
- pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n",
- shdr->sh_link, shdr->sh_link,
- info->hdr->e_shnum);
- goto no_exec;
- }
- num_sym_secs++;
- sym_idx = i;
- }
- }
-
- if (num_sym_secs != 1) {
- pr_warn("%s: module has no symbols (stripped?)\n",
- info->name ?: "(missing .modinfo section or name field)");
- goto no_exec;
+ str_idx = info->sechdrs[info->index.sym].sh_link;
+ if (str_idx == SHN_UNDEF || str_idx >= info->hdr->e_shnum) {
+ pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n",
+ str_idx, str_idx, info->hdr->e_shnum);
+ return -ENOEXEC;
}
- /* Sets internal symbols and strings. */
- info->index.sym = sym_idx;
- shdr = &info->sechdrs[sym_idx];
- info->index.str = shdr->sh_link;
+ /* Sets internal strings. */
+ info->index.str = str_idx;
info->strtab = (char *)info->hdr + info->sechdrs[info->index.str].sh_offset;
/* This is temporary: point mod into copy of data. */
@@ -2066,9 +2084,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
info->index.pcpu = find_pcpusec(info);
return 0;
-
-no_exec:
- return -ENOEXEC;
}
#define COPY_CHUNK_SIZE (16*PAGE_SIZE)
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 08/16] module: Factor out elf_validity_cache_index_str
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (6 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 07/16] module: Factor out elf_validity_cache_index_sym Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 09/16] module: Group section index calculations together Matthew Maurer
` (9 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Pull out index validation for the symbol string section.
Note that this does not validate the *contents* of the string table,
only shape and presence of the section.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 37 ++++++++++++++++++++++++++++---------
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 6be58b0a6468..43140475aac0 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2014,6 +2014,31 @@ static int elf_validity_cache_index_sym(struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_index_str() - Validate and cache strtab index
+ * @info: Load info to cache strtab index in.
+ * Must have &load_info->sechdrs and &load_info->secstrings populated.
+ * Must have &load_info->index.sym populated.
+ *
+ * Looks at the symbol table's associated string table, makes sure it is
+ * in-bounds, and caches it.
+ *
+ * Return: %0 if valid, %-ENOEXEC on failure.
+ */
+static int elf_validity_cache_index_str(struct load_info *info)
+{
+ unsigned int str_idx = info->sechdrs[info->index.sym].sh_link;
+
+ if (str_idx == SHN_UNDEF || str_idx >= info->hdr->e_shnum) {
+ pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n",
+ str_idx, str_idx, info->hdr->e_shnum);
+ return -ENOEXEC;
+ }
+
+ info->index.str = str_idx;
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -2037,7 +2062,6 @@ static int elf_validity_cache_index_sym(struct load_info *info)
static int elf_validity_cache_copy(struct load_info *info, int flags)
{
int err;
- int str_idx;
err = elf_validity_cache_sechdrs(info);
if (err < 0)
@@ -2054,16 +2078,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
err = elf_validity_cache_index_sym(info);
if (err < 0)
return err;
-
- str_idx = info->sechdrs[info->index.sym].sh_link;
- if (str_idx == SHN_UNDEF || str_idx >= info->hdr->e_shnum) {
- pr_err("Invalid ELF sh_link!=SHN_UNDEF(%d) or (sh_link(%d) >= hdr->e_shnum(%d)\n",
- str_idx, str_idx, info->hdr->e_shnum);
- return -ENOEXEC;
- }
+ err = elf_validity_cache_index_str(info);
+ if (err < 0)
+ return err;
/* Sets internal strings. */
- info->index.str = str_idx;
info->strtab = (char *)info->hdr + info->sechdrs[info->index.str].sh_offset;
/* This is temporary: point mod into copy of data. */
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 09/16] module: Group section index calculations together
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (7 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 08/16] module: Factor out elf_validity_cache_index_str Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 10/16] module: Factor out elf_validity_cache_strtab Matthew Maurer
` (8 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Group all the index detection together to make the parent function
easier to read.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 68 +++++++++++++++++++++++++++++++++-----------
1 file changed, 51 insertions(+), 17 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 43140475aac0..e04a228c694a 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2039,6 +2039,56 @@ static int elf_validity_cache_index_str(struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_index() - Resolve, validate, cache section indices
+ * @info: Load info to read from and update.
+ * &load_info->sechdrs and &load_info->secstrings must be populated.
+ * @flags: Load flags, relevant to suppress version loading, see
+ * uapi/linux/module.h
+ *
+ * Populates &load_info->index, validating as it goes.
+ * See child functions for per-field validation:
+ *
+ * * elf_validity_cache_index_info()
+ * * elf_validity_cache_index_mod()
+ * * elf_validity_cache_index_sym()
+ * * elf_validity_cache_index_str()
+ *
+ * If versioning is not suppressed via flags, load the version index from
+ * a section called "__versions" with no validation.
+ *
+ * If CONFIG_SMP is enabled, load the percpu section by name with no
+ * validation.
+ *
+ * Return: 0 on success, negative error code if an index failed validation.
+ */
+static int elf_validity_cache_index(struct load_info *info, int flags)
+{
+ int err;
+
+ err = elf_validity_cache_index_info(info);
+ if (err < 0)
+ return err;
+ err = elf_validity_cache_index_mod(info);
+ if (err < 0)
+ return err;
+ err = elf_validity_cache_index_sym(info);
+ if (err < 0)
+ return err;
+ err = elf_validity_cache_index_str(info);
+ if (err < 0)
+ return err;
+
+ if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
+ info->index.vers = 0; /* Pretend no __versions section! */
+ else
+ info->index.vers = find_sec(info, "__versions");
+
+ info->index.pcpu = find_pcpusec(info);
+
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -2069,16 +2119,7 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
err = elf_validity_cache_secstrings(info);
if (err < 0)
return err;
- err = elf_validity_cache_index_info(info);
- if (err < 0)
- return err;
- err = elf_validity_cache_index_mod(info);
- if (err < 0)
- return err;
- err = elf_validity_cache_index_sym(info);
- if (err < 0)
- return err;
- err = elf_validity_cache_index_str(info);
+ err = elf_validity_cache_index(info, flags);
if (err < 0)
return err;
@@ -2095,13 +2136,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
if (!info->name)
info->name = info->mod->name;
- if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
- info->index.vers = 0; /* Pretend no __versions section! */
- else
- info->index.vers = find_sec(info, "__versions");
-
- info->index.pcpu = find_pcpusec(info);
-
return 0;
}
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 10/16] module: Factor out elf_validity_cache_strtab
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (8 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 09/16] module: Group section index calculations together Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 11/16] module: Additional validation in elf_validity_cache_strtab Matthew Maurer
` (7 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
This patch only moves the existing strtab population to a function.
Validation comes in a following patch, this is split out to make the new
validation checks more clearly separated.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index e04a228c694a..c082d5d41a8d 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2089,6 +2089,23 @@ static int elf_validity_cache_index(struct load_info *info, int flags)
return 0;
}
+/**
+ * elf_validity_cache_strtab() - Cache symbol string table
+ * @info: Load info to read from and update.
+ * Must have &load_info->sechdrs and &load_info->secstrings populated.
+ * Must have &load_info->index populated.
+ *
+ * Return: 0 on success, negative error code if a check failed.
+ */
+static int elf_validity_cache_strtab(struct load_info *info)
+{
+ Elf_Shdr *str_shdr = &info->sechdrs[info->index.str];
+ char *strtab = (char *)info->hdr + str_shdr->sh_offset;
+
+ info->strtab = strtab;
+ return 0;
+}
+
/*
* Check userspace passed ELF module against our expectations, and cache
* useful variables for further processing as we go.
@@ -2122,9 +2139,9 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
err = elf_validity_cache_index(info, flags);
if (err < 0)
return err;
-
- /* Sets internal strings. */
- info->strtab = (char *)info->hdr + info->sechdrs[info->index.str].sh_offset;
+ err = elf_validity_cache_strtab(info);
+ if (err < 0)
+ return err;
/* This is temporary: point mod into copy of data. */
info->mod = (void *)info->hdr + info->sechdrs[info->index.mod].sh_offset;
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 11/16] module: Additional validation in elf_validity_cache_strtab
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (9 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 10/16] module: Factor out elf_validity_cache_strtab Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 12/16] module: Reformat struct for code style Matthew Maurer
` (6 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Validate properties of the strtab that are depended on elsewhere, but
were previously unchecked:
* String table nonempty (offset 0 is valid)
* String table has a leading NUL (offset 0 corresponds to "")
* String table is NUL terminated (strfoo functions won't run out of the
table while reading).
* All symbols names are inbounds of the string table.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/main.c | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/kernel/module/main.c b/kernel/module/main.c
index c082d5d41a8d..b40b632f00a6 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2090,17 +2090,53 @@ static int elf_validity_cache_index(struct load_info *info, int flags)
}
/**
- * elf_validity_cache_strtab() - Cache symbol string table
+ * elf_validity_cache_strtab() - Validate and cache symbol string table
* @info: Load info to read from and update.
* Must have &load_info->sechdrs and &load_info->secstrings populated.
* Must have &load_info->index populated.
*
+ * Checks:
+ *
+ * * The string table is not empty.
+ * * The string table starts and ends with NUL (required by ELF spec).
+ * * Every &Elf_Sym->st_name offset in the symbol table is inbounds of the
+ * string table.
+ *
+ * And caches the pointer as &load_info->strtab in @info.
+ *
* Return: 0 on success, negative error code if a check failed.
*/
static int elf_validity_cache_strtab(struct load_info *info)
{
Elf_Shdr *str_shdr = &info->sechdrs[info->index.str];
+ Elf_Shdr *sym_shdr = &info->sechdrs[info->index.sym];
char *strtab = (char *)info->hdr + str_shdr->sh_offset;
+ Elf_Sym *syms = (void *)info->hdr + sym_shdr->sh_offset;
+ int i;
+
+ if (str_shdr->sh_size == 0) {
+ pr_err("empty symbol string table\n");
+ return -ENOEXEC;
+ }
+ if (strtab[0] != '\0') {
+ pr_err("symbol string table missing leading NUL\n");
+ return -ENOEXEC;
+ }
+ if (strtab[str_shdr->sh_size - 1] != '\0') {
+ pr_err("symbol string table isn't NUL terminated\n");
+ return -ENOEXEC;
+ }
+
+ /*
+ * Now that we know strtab is correctly structured, check symbol
+ * starts are inbounds before they're used later.
+ */
+ for (i = 0; i < sym_shdr->sh_size / sizeof(*syms); i++) {
+ if (syms[i].st_name >= str_shdr->sh_size) {
+ pr_err("symbol name out of bounds in string table");
+ return -ENOEXEC;
+ }
+ }
info->strtab = strtab;
return 0;
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 12/16] module: Reformat struct for code style
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (10 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 11/16] module: Additional validation in elf_validity_cache_strtab Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 13/16] export_report: Rehabilitate script Matthew Maurer
` (5 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Using commas to declare struct members makes adding new members to this
struct not as nice with patch management.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
kernel/module/internal.h | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 2ebece8a789f..daef2be83902 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -80,7 +80,12 @@ struct load_info {
unsigned int used_pages;
#endif
struct {
- unsigned int sym, str, mod, vers, info, pcpu;
+ unsigned int sym;
+ unsigned int str;
+ unsigned int mod;
+ unsigned int vers;
+ unsigned int info;
+ unsigned int pcpu;
} index;
};
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 13/16] export_report: Rehabilitate script
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (11 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 12/16] module: Reformat struct for code style Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-10-11 22:13 ` Luis Chamberlain
2024-09-25 23:38 ` [PATCH v5 14/16] modules: Support extended MODVERSIONS info Matthew Maurer
` (4 subsequent siblings)
17 siblings, 1 reply; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor,
Matthew Maurer
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross
* modules.order has .o files when in a build dir, support this
* .mod.c source layout has changed, update regexes to match
* Add a stage 3, to be more robust against additional .mod.c content
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
scripts/export_report.pl | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index feb3d5542a62..dcef915405f3 100755
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
@@ -55,6 +55,7 @@ sub collectcfiles {
open my $fh, '< modules.order' or die "cannot open modules.order: $!\n";
while (<$fh>) {
s/\.ko$/.mod.c/;
+ s/\.o$/.mod.c/;
push (@file, $_)
}
close($fh);
@@ -120,10 +121,14 @@ foreach my $thismod (@allcfiles) {
next;
}
if ($state == 1) {
- $state = 2 if ($_ =~ /__attribute__\(\(section\("__versions"\)\)\)/);
+ $state = 2 if ($_ =~ /__used __section\("__versions"\)/);
next;
}
if ($state == 2) {
+ if ( $_ =~ /};/ ) {
+ $state = 3;
+ next;
+ }
if ( $_ !~ /0x[0-9a-f]+,/ ) {
next;
}
@@ -133,7 +138,7 @@ foreach my $thismod (@allcfiles) {
push(@{$MODULE{$thismod}} , $sym);
}
}
- if ($state != 2) {
+ if ($state != 3) {
warn "WARNING:$thismod is not built with CONFIG_MODVERSIONS enabled\n";
$modversion_warnings++;
}
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v5 13/16] export_report: Rehabilitate script
2024-09-25 23:38 ` [PATCH v5 13/16] export_report: Rehabilitate script Matthew Maurer
@ 2024-10-11 22:13 ` Luis Chamberlain
2024-10-11 22:22 ` Matthew Maurer
0 siblings, 1 reply; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-11 22:13 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, Alex Gaynor, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross
On Wed, Sep 25, 2024 at 11:38:28PM +0000, Matthew Maurer wrote:
> * modules.order has .o files when in a build dir, support this
The commit log is not clear, is it that it's always had *.o files, and
you're adding them now, why? Why is the .ko search now removed?
> * .mod.c source layout has changed,
When, why did this change not happen at that time?
> update regexes to match
Why did this not break anything before ? Is this fixing something, or
is it prep work?
> * Add a stage 3, to be more robust against additional .mod.c content
Future .mod.c changes?
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 13/16] export_report: Rehabilitate script
2024-10-11 22:13 ` Luis Chamberlain
@ 2024-10-11 22:22 ` Matthew Maurer
2024-10-11 22:29 ` Luis Chamberlain
0 siblings, 1 reply; 35+ messages in thread
From: Matthew Maurer @ 2024-10-11 22:22 UTC (permalink / raw)
To: Luis Chamberlain
Cc: masahiroy, ndesaulniers, ojeda, gary, Alex Gaynor, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross
On Fri, Oct 11, 2024 at 3:13 PM Luis Chamberlain <mcgrof@kernel.org> wrote:
>
> On Wed, Sep 25, 2024 at 11:38:28PM +0000, Matthew Maurer wrote:
> > * modules.order has .o files when in a build dir, support this
>
> The commit log is not clear, is it that it's always had *.o files, and
> you're adding them now, why? Why is the .ko search now removed?
The script was broken when I found it, but it was a script that
analyzed MODVERSIONS, so I tried to ensure it would still work with my
changes. This necessitated rehabilitating it first. I did not touch
`.modules.order` files, but they contained `.o` and so this script
wouldn't run correctly.
>
> > * .mod.c source layout has changed,
>
> When, why did this change not happen at that time?
It was changed for readability [1] back in 2019. I assume the change
did not happen at that time because this script is rarely run. If we'd
prefer to discard this patch and ignore the script instead (or remove
it?), that's fine.
[1]: https://lore.kernel.org/all/20190909113423.2289-2-yamada.masahiro@socionext.com/
>
> > update regexes to match
>
> Why did this not break anything before ? Is this fixing something, or
> is it prep work?
>
> > * Add a stage 3, to be more robust against additional .mod.c content
>
> Future .mod.c changes?
The rest of this series adds additional `.mod.c` content to support
the string names. This stage 3 is intended to prevent that from
causing the script to choke.
>
> Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 13/16] export_report: Rehabilitate script
2024-10-11 22:22 ` Matthew Maurer
@ 2024-10-11 22:29 ` Luis Chamberlain
0 siblings, 0 replies; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-11 22:29 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, Alex Gaynor, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross
On Fri, Oct 11, 2024 at 03:22:54PM -0700, Matthew Maurer wrote:
> On Fri, Oct 11, 2024 at 3:13 PM Luis Chamberlain <mcgrof@kernel.org> wrote:
> >
> > On Wed, Sep 25, 2024 at 11:38:28PM +0000, Matthew Maurer wrote:
> > > * modules.order has .o files when in a build dir, support this
> >
> > The commit log is not clear, is it that it's always had *.o files, and
> > you're adding them now, why? Why is the .ko search now removed?
>
> The script was broken when I found it,
My point is that commit messages should describe all this.
> but it was a script that
> analyzed MODVERSIONS, so I tried to ensure it would still work with my
> changes.
OK yes please add this informaiton into the comit log.
Also expand on it as to to *why* this was not a critical issue.
> This necessitated rehabilitating it first. I did not touch
> `.modules.order` files, but they contained `.o` and so this script
> wouldn't run correctly.
Just elaborate on the commit log. We cannot guess what is happening, and
so bringing clarity into exactly what you are doing and *why* is helpful
to determine the impact of not applying this.
> > > * .mod.c source layout has changed,
> >
> > When, why did this change not happen at that time?
>
> It was changed for readability [1] back in 2019. I assume the change
> did not happen at that time because this script is rarely run.
This is crucial information to include in the commit log. When *would*
you use it? So that use case was broken since 2019? What negative
effects has this implicated?
> If we'd
> prefer to discard this patch and ignore the script instead (or remove
> it?), that's fine.
The feedback is for you to improve the commit logs, not to tell you to
not do something. We cannot read your mind, and this smelled like a fix,
but without a true evaluation and documentation of the impact of not
having this in place. These things need to be thought out and written
in the comit log.
>
> [1]: https://lore.kernel.org/all/20190909113423.2289-2-yamada.masahiro@socionext.com/
>
> >
> > > update regexes to match
> >
> > Why did this not break anything before ? Is this fixing something, or
> > is it prep work?
> >
> > > * Add a stage 3, to be more robust against additional .mod.c content
> >
> > Future .mod.c changes?
>
> The rest of this series adds additional `.mod.c` content to support
> the string names. This stage 3 is intended to prevent that from
> causing the script to choke.
The commit log should clarify all this.
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (12 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 13/16] export_report: Rehabilitate script Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-26 12:22 ` Christophe Leroy
2024-10-11 22:22 ` Luis Chamberlain
2024-09-25 23:38 ` [PATCH v5 15/16] modpost: Produce extended modversion information Matthew Maurer
` (3 subsequent siblings)
17 siblings, 2 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, Matthew Maurer
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Nicholas Piggin, Christophe Leroy,
Madhavan Srinivasan, Petr Pavlu, Sami Tolvanen, Daniel Gomez,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, linuxppc-dev
Adds a new format for MODVERSIONS which stores each field in a separate
ELF section. This initially adds support for variable length names, but
could later be used to add additional fields to MODVERSIONS in a
backwards compatible way if needed. Any new fields will be ignored by
old user tooling, unlike the current format where user tooling cannot
tolerate adjustments to the format (for example making the name field
longer).
Since PPC munges its version records to strip leading dots, we reproduce
the munging for the new format. Other architectures do not appear to
have architecture-specific usage of this information.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
arch/powerpc/kernel/module_64.c | 23 ++++++++-
kernel/module/internal.h | 11 ++++
kernel/module/main.c | 92 ++++++++++++++++++++++++++++++---
kernel/module/version.c | 45 ++++++++++++++++
4 files changed, 161 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index e9bab599d0c2..4e7b156dd8b2 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -355,6 +355,23 @@ static void dedotify_versions(struct modversion_info *vers,
}
}
+static void dedotify_ext_version_names(char *str_seq, unsigned long size)
+{
+ unsigned long out = 0;
+ unsigned long in;
+ char last = '\0';
+
+ for (in = 0; in < size; in++) {
+ /* Skip one leading dot */
+ if (last == '\0' && str_seq[in] == '.')
+ in++;
+ last = str_seq[in];
+ str_seq[out++] = last;
+ }
+ /* Zero the trailing portion of the names table for robustness */
+ memset(&str_seq[out], 0, size - out);
+}
+
/*
* Undefined symbols which refer to .funcname, hack to funcname. Make .TOC.
* seem to be defined (value set later).
@@ -424,10 +441,12 @@ int module_frob_arch_sections(Elf64_Ehdr *hdr,
me->arch.toc_section = i;
if (sechdrs[i].sh_addralign < 8)
sechdrs[i].sh_addralign = 8;
- }
- else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0)
+ } else if (strcmp(secstrings + sechdrs[i].sh_name, "__versions") == 0)
dedotify_versions((void *)hdr + sechdrs[i].sh_offset,
sechdrs[i].sh_size);
+ else if (strcmp(secstrings + sechdrs[i].sh_name, "__version_ext_names") == 0)
+ dedotify_ext_version_names((void *)hdr + sechdrs[i].sh_offset,
+ sechdrs[i].sh_size);
if (sechdrs[i].sh_type == SHT_SYMTAB)
dedotify((void *)hdr + sechdrs[i].sh_offset,
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index daef2be83902..59959c21b205 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -86,6 +86,8 @@ struct load_info {
unsigned int vers;
unsigned int info;
unsigned int pcpu;
+ unsigned int vers_ext_crc;
+ unsigned int vers_ext_name;
} index;
};
@@ -389,6 +391,15 @@ void module_layout(struct module *mod, struct modversion_info *ver, struct kerne
struct kernel_symbol *ks, struct tracepoint * const *tp);
int check_modstruct_version(const struct load_info *info, struct module *mod);
int same_magic(const char *amagic, const char *bmagic, bool has_crcs);
+struct modversion_info_ext {
+ size_t remaining;
+ const s32 *crc;
+ const char *name;
+};
+void modversion_ext_start(const struct load_info *info, struct modversion_info_ext *ver);
+void modversion_ext_advance(struct modversion_info_ext *ver);
+#define for_each_modversion_info_ext(ver, info) \
+ for (modversion_ext_start(info, &ver); ver.remaining > 0; modversion_ext_advance(&ver))
#else /* !CONFIG_MODVERSIONS */
static inline int check_version(const struct load_info *info,
const char *symname,
diff --git a/kernel/module/main.c b/kernel/module/main.c
index b40b632f00a6..9a9feca344f8 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2039,6 +2039,82 @@ static int elf_validity_cache_index_str(struct load_info *info)
return 0;
}
+/**
+ * elf_validity_cache_index_versions() - Validate and cache version indices
+ * @info: Load info to cache version indices in.
+ * Must have &load_info->sechdrs and &load_info->secstrings populated.
+ * @flags: Load flags, relevant to suppress version loading, see
+ * uapi/linux/module.h
+ *
+ * If we're ignoring modversions based on @flags, zero all version indices
+ * and return validity. Othewrise check:
+ *
+ * * If "__version_ext_crcs" is present, "__version_ext_names" is present
+ * * There is a name present for every crc
+ *
+ * Then populate:
+ *
+ * * &load_info->index.vers
+ * * &load_info->index.vers_ext_crc
+ * * &load_info->index.vers_ext_names
+ *
+ * if present.
+ *
+ * Return: %0 if valid, %-ENOEXEC on failure.
+ */
+static int elf_validity_cache_index_versions(struct load_info *info, int flags)
+{
+ unsigned int vers_ext_crc;
+ unsigned int vers_ext_name;
+ size_t crc_count;
+ size_t remaining_len;
+ size_t name_size;
+ char *name;
+
+ /* If modversions were suppressed, pretend we didn't find any */
+ if (flags & MODULE_INIT_IGNORE_MODVERSIONS) {
+ info->index.vers = 0;
+ info->index.vers_ext_crc = 0;
+ info->index.vers_ext_name = 0;
+ return 0;
+ }
+
+ vers_ext_crc = find_sec(info, "__version_ext_crcs");
+ vers_ext_name = find_sec(info, "__version_ext_names");
+
+ /* If we have one field, we must have the other */
+ if (!!vers_ext_crc != !!vers_ext_name) {
+ pr_err("extended version crc+name presence does not match");
+ return -ENOEXEC;
+ }
+
+ /*
+ * If we have extended version information, we should have the same
+ * number of entries in every section.
+ */
+ if (vers_ext_crc) {
+ crc_count = info->sechdrs[vers_ext_crc].sh_size / sizeof(s32);
+ name = (void *)info->hdr +
+ info->sechdrs[vers_ext_name].sh_offset;
+ remaining_len = info->sechdrs[vers_ext_name].sh_size;
+
+ while (crc_count--) {
+ name_size = strnlen(name, remaining_len) + 1;
+ if (name_size > remaining_len) {
+ pr_err("more extended version crcs than names");
+ return -ENOEXEC;
+ }
+ remaining_len -= name_size;
+ name += name_size;
+ }
+ }
+
+ info->index.vers = find_sec(info, "__versions");
+ info->index.vers_ext_crc = vers_ext_crc;
+ info->index.vers_ext_name = vers_ext_name;
+ return 0;
+}
+
/**
* elf_validity_cache_index() - Resolve, validate, cache section indices
* @info: Load info to read from and update.
@@ -2053,9 +2129,7 @@ static int elf_validity_cache_index_str(struct load_info *info)
* * elf_validity_cache_index_mod()
* * elf_validity_cache_index_sym()
* * elf_validity_cache_index_str()
- *
- * If versioning is not suppressed via flags, load the version index from
- * a section called "__versions" with no validation.
+ * * elf_validity_cache_index_versions()
*
* If CONFIG_SMP is enabled, load the percpu section by name with no
* validation.
@@ -2078,11 +2152,9 @@ static int elf_validity_cache_index(struct load_info *info, int flags)
err = elf_validity_cache_index_str(info);
if (err < 0)
return err;
-
- if (flags & MODULE_INIT_IGNORE_MODVERSIONS)
- info->index.vers = 0; /* Pretend no __versions section! */
- else
- info->index.vers = find_sec(info, "__versions");
+ err = elf_validity_cache_index_versions(info, flags);
+ if (err < 0)
+ return err;
info->index.pcpu = find_pcpusec(info);
@@ -2293,6 +2365,10 @@ static int rewrite_section_headers(struct load_info *info, int flags)
/* Track but don't keep modinfo and version sections. */
info->sechdrs[info->index.vers].sh_flags &= ~(unsigned long)SHF_ALLOC;
+ info->sechdrs[info->index.vers_ext_crc].sh_flags &=
+ ~(unsigned long)SHF_ALLOC;
+ info->sechdrs[info->index.vers_ext_name].sh_flags &=
+ ~(unsigned long)SHF_ALLOC;
info->sechdrs[info->index.info].sh_flags &= ~(unsigned long)SHF_ALLOC;
return 0;
diff --git a/kernel/module/version.c b/kernel/module/version.c
index 53f43ac5a73e..c246d4087970 100644
--- a/kernel/module/version.c
+++ b/kernel/module/version.c
@@ -19,11 +19,28 @@ int check_version(const struct load_info *info,
unsigned int versindex = info->index.vers;
unsigned int i, num_versions;
struct modversion_info *versions;
+ struct modversion_info_ext version_ext;
/* Exporting module didn't supply crcs? OK, we're already tainted. */
if (!crc)
return 1;
+ /* If we have extended version info, rely on it */
+ if (info->index.vers_ext_crc) {
+ for_each_modversion_info_ext(version_ext, info) {
+ if (strcmp(version_ext.name, symname) != 0)
+ continue;
+ if (*version_ext.crc == *crc)
+ return 1;
+ pr_debug("Found checksum %X vs module %X\n",
+ *crc, *version_ext.crc);
+ goto bad_version;
+ }
+ pr_warn_once("%s: no extended symbol version for %s\n",
+ info->name, symname);
+ return 1;
+ }
+
/* No versions at all? modprobe --force does this. */
if (versindex == 0)
return try_to_force_load(mod, symname) == 0;
@@ -87,6 +104,34 @@ int same_magic(const char *amagic, const char *bmagic,
return strcmp(amagic, bmagic) == 0;
}
+void modversion_ext_start(const struct load_info *info,
+ struct modversion_info_ext *start)
+{
+ unsigned int crc_idx = info->index.vers_ext_crc;
+ unsigned int name_idx = info->index.vers_ext_name;
+ Elf_Shdr *sechdrs = info->sechdrs;
+
+ /*
+ * Both of these fields are needed for this to be useful
+ * Any future fields should be initialized to NULL if absent.
+ */
+ if (crc_idx == 0 || name_idx == 0) {
+ start->remaining = 0;
+ return;
+ }
+
+ start->crc = (const s32 *)sechdrs[crc_idx].sh_addr;
+ start->name = (const char *)sechdrs[name_idx].sh_addr;
+ start->remaining = sechdrs[crc_idx].sh_size / sizeof(*start->crc);
+}
+
+void modversion_ext_advance(struct modversion_info_ext *vers)
+{
+ vers->remaining--;
+ vers->crc++;
+ vers->name += strlen(vers->name) + 1;
+}
+
/*
* Generate the signature for all relevant module structures here.
* If these change, we don't want to try to parse the module.
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-09-25 23:38 ` [PATCH v5 14/16] modules: Support extended MODVERSIONS info Matthew Maurer
@ 2024-09-26 12:22 ` Christophe Leroy
2024-09-26 18:36 ` Sami Tolvanen
2024-10-11 22:22 ` Luis Chamberlain
1 sibling, 1 reply; 35+ messages in thread
From: Christophe Leroy @ 2024-09-26 12:22 UTC (permalink / raw)
To: Matthew Maurer, masahiroy, ndesaulniers, ojeda, gary, mcgrof,
Michael Ellerman, Alex Gaynor, Benjamin Gray, Naveen N Rao
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Nicholas Piggin, Madhavan Srinivasan,
Petr Pavlu, Sami Tolvanen, Daniel Gomez, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
Le 26/09/2024 à 01:38, Matthew Maurer a écrit :
> Adds a new format for MODVERSIONS which stores each field in a separate
> ELF section. This initially adds support for variable length names, but
> could later be used to add additional fields to MODVERSIONS in a
> backwards compatible way if needed. Any new fields will be ignored by
> old user tooling, unlike the current format where user tooling cannot
> tolerate adjustments to the format (for example making the name field
> longer).
>
> Since PPC munges its version records to strip leading dots, we reproduce
> the munging for the new format. Other architectures do not appear to
> have architecture-specific usage of this information.
>
> Signed-off-by: Matthew Maurer <mmaurer@google.com>
> ---
> arch/powerpc/kernel/module_64.c | 23 ++++++++-
> kernel/module/internal.h | 11 ++++
> kernel/module/main.c | 92 ++++++++++++++++++++++++++++++---
> kernel/module/version.c | 45 ++++++++++++++++
> 4 files changed, 161 insertions(+), 10 deletions(-)
>
> diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
> index e9bab599d0c2..4e7b156dd8b2 100644
> --- a/arch/powerpc/kernel/module_64.c
> +++ b/arch/powerpc/kernel/module_64.c
> @@ -355,6 +355,23 @@ static void dedotify_versions(struct modversion_info *vers,
> }
> }
>
> +static void dedotify_ext_version_names(char *str_seq, unsigned long size)
> +{
> + unsigned long out = 0;
> + unsigned long in;
> + char last = '\0';
> +
> + for (in = 0; in < size; in++) {
> + /* Skip one leading dot */
> + if (last == '\0' && str_seq[in] == '.')
> + in++;
> + last = str_seq[in];
> + str_seq[out++] = last;
> + }
Why do you need a loop here ?
Can't you just do something like:
if (str_seq[0] == '.')
memmove(str_seq, str_seq + 1, size);
> + /* Zero the trailing portion of the names table for robustness */
> + memset(&str_seq[out], 0, size - out);
This seems unneeded.
> +}
> +
> /*
> * Undefined symbols which refer to .funcname, hack to funcname. Make .TOC.
> * seem to be defined (value set later).
Christophe
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-09-26 12:22 ` Christophe Leroy
@ 2024-09-26 18:36 ` Sami Tolvanen
0 siblings, 0 replies; 35+ messages in thread
From: Sami Tolvanen @ 2024-09-26 18:36 UTC (permalink / raw)
To: Christophe Leroy
Cc: Matthew Maurer, masahiroy, ndesaulniers, ojeda, gary, mcgrof,
Michael Ellerman, Alex Gaynor, Benjamin Gray, Naveen N Rao,
rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Nicholas Piggin, Madhavan Srinivasan,
Petr Pavlu, Daniel Gomez, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
linuxppc-dev
On Thu, Sep 26, 2024 at 5:22 AM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 26/09/2024 à 01:38, Matthew Maurer a écrit :
> > Adds a new format for MODVERSIONS which stores each field in a separate
> > ELF section. This initially adds support for variable length names, but
> > could later be used to add additional fields to MODVERSIONS in a
> > backwards compatible way if needed. Any new fields will be ignored by
> > old user tooling, unlike the current format where user tooling cannot
> > tolerate adjustments to the format (for example making the name field
> > longer).
> >
> > Since PPC munges its version records to strip leading dots, we reproduce
> > the munging for the new format. Other architectures do not appear to
> > have architecture-specific usage of this information.
> >
> > Signed-off-by: Matthew Maurer <mmaurer@google.com>
> > ---
> > arch/powerpc/kernel/module_64.c | 23 ++++++++-
> > kernel/module/internal.h | 11 ++++
> > kernel/module/main.c | 92 ++++++++++++++++++++++++++++++---
> > kernel/module/version.c | 45 ++++++++++++++++
> > 4 files changed, 161 insertions(+), 10 deletions(-)
> >
> > diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
> > index e9bab599d0c2..4e7b156dd8b2 100644
> > --- a/arch/powerpc/kernel/module_64.c
> > +++ b/arch/powerpc/kernel/module_64.c
> > @@ -355,6 +355,23 @@ static void dedotify_versions(struct modversion_info *vers,
> > }
> > }
> >
> > +static void dedotify_ext_version_names(char *str_seq, unsigned long size)
> > +{
> > + unsigned long out = 0;
> > + unsigned long in;
> > + char last = '\0';
> > +
> > + for (in = 0; in < size; in++) {
> > + /* Skip one leading dot */
> > + if (last == '\0' && str_seq[in] == '.')
> > + in++;
> > + last = str_seq[in];
> > + str_seq[out++] = last;
> > + }
>
> Why do you need a loop here ?
>
> Can't you just do something like:
>
> if (str_seq[0] == '.')
> memmove(str_seq, str_seq + 1, size);
I initially had the same thought, but it's because this is is a
sequence of multiple null-terminated strings, and we need to dedotify
all of them, not just the first one. Here's an example:
https://godbolt.org/z/avMGnd48M
> > + /* Zero the trailing portion of the names table for robustness */
> > + memset(&str_seq[out], 0, size - out);
>
> This seems unneeded.
Strictly speaking it shouldn't be needed, but I think it's still good
hygiene to not leave another null-terminated fragment at the end.
Sami
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-09-25 23:38 ` [PATCH v5 14/16] modules: Support extended MODVERSIONS info Matthew Maurer
2024-09-26 12:22 ` Christophe Leroy
@ 2024-10-11 22:22 ` Luis Chamberlain
2024-10-11 22:27 ` Matthew Maurer
1 sibling, 1 reply; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-11 22:22 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Petr Pavlu, Sami Tolvanen, Daniel Gomez, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
On Wed, Sep 25, 2024 at 11:38:29PM +0000, Matthew Maurer wrote:
> Adds a new format for MODVERSIONS which stores each field in a separate
> ELF section. This initially adds support for variable length names, but
> could later be used to add additional fields to MODVERSIONS in a
> backwards compatible way if needed. Any new fields will be ignored by
> old user tooling, unlike the current format where user tooling cannot
> tolerate adjustments to the format (for example making the name field
> longer).
>
> Since PPC munges its version records to strip leading dots, we reproduce
> the munging for the new format. Other architectures do not appear to
> have architecture-specific usage of this information.
>
> Signed-off-by: Matthew Maurer <mmaurer@google.com>
I'm all for the ELF validation work so far, all that was nice, thanks
for all that tidying up. This however is not considering when we really
need all this at all, and not making it specific to the build times when
such things are needed. That is, yes I'd like to see the need for this
clearly explicitly defined through Kconfig, a *select FOO_FEATURE* for
when this is needed. No need to extend a module with bloat if we don't
need it, likewise if a kernel was built without needing those things,
why bloat the modules with the extra information?
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-11 22:22 ` Luis Chamberlain
@ 2024-10-11 22:27 ` Matthew Maurer
2024-10-11 22:33 ` Luis Chamberlain
0 siblings, 1 reply; 35+ messages in thread
From: Matthew Maurer @ 2024-10-11 22:27 UTC (permalink / raw)
To: Luis Chamberlain
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Petr Pavlu, Sami Tolvanen, Daniel Gomez, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
On Fri, Oct 11, 2024 at 3:22 PM Luis Chamberlain <mcgrof@kernel.org> wrote:
>
> On Wed, Sep 25, 2024 at 11:38:29PM +0000, Matthew Maurer wrote:
> > Adds a new format for MODVERSIONS which stores each field in a separate
> > ELF section. This initially adds support for variable length names, but
> > could later be used to add additional fields to MODVERSIONS in a
> > backwards compatible way if needed. Any new fields will be ignored by
> > old user tooling, unlike the current format where user tooling cannot
> > tolerate adjustments to the format (for example making the name field
> > longer).
> >
> > Since PPC munges its version records to strip leading dots, we reproduce
> > the munging for the new format. Other architectures do not appear to
> > have architecture-specific usage of this information.
> >
> > Signed-off-by: Matthew Maurer <mmaurer@google.com>
>
> I'm all for the ELF validation work so far, all that was nice, thanks
> for all that tidying up. This however is not considering when we really
> need all this at all, and not making it specific to the build times when
> such things are needed. That is, yes I'd like to see the need for this
> clearly explicitly defined through Kconfig, a *select FOO_FEATURE* for
> when this is needed. No need to extend a module with bloat if we don't
> need it, likewise if a kernel was built without needing those things,
> why bloat the modules with the extra information?
To make sure I understand what you're asking for, are you suggesting:
1. A config flag for supporting parsing the extended format
2. A config flag for supporting parsing the existing format
3. A config flag for putting the extended format into produced modules
4. A config flag for putting the existing format into produced modules
or some combination of the above?
I'm currently reading this as #3, but figured I'd ask to be certain.
>
> Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-11 22:27 ` Matthew Maurer
@ 2024-10-11 22:33 ` Luis Chamberlain
2024-10-11 23:45 ` Luis Chamberlain
0 siblings, 1 reply; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-11 22:33 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Petr Pavlu, Sami Tolvanen, Daniel Gomez, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
On Fri, Oct 11, 2024 at 03:27:30PM -0700, Matthew Maurer wrote:
> On Fri, Oct 11, 2024 at 3:22 PM Luis Chamberlain <mcgrof@kernel.org> wrote:
> >
> > On Wed, Sep 25, 2024 at 11:38:29PM +0000, Matthew Maurer wrote:
> > > Adds a new format for MODVERSIONS which stores each field in a separate
> > > ELF section. This initially adds support for variable length names, but
> > > could later be used to add additional fields to MODVERSIONS in a
> > > backwards compatible way if needed. Any new fields will be ignored by
> > > old user tooling, unlike the current format where user tooling cannot
> > > tolerate adjustments to the format (for example making the name field
> > > longer).
> > >
> > > Since PPC munges its version records to strip leading dots, we reproduce
> > > the munging for the new format. Other architectures do not appear to
> > > have architecture-specific usage of this information.
> > >
> > > Signed-off-by: Matthew Maurer <mmaurer@google.com>
> >
> > I'm all for the ELF validation work so far, all that was nice, thanks
> > for all that tidying up. This however is not considering when we really
> > need all this at all, and not making it specific to the build times when
> > such things are needed. That is, yes I'd like to see the need for this
> > clearly explicitly defined through Kconfig, a *select FOO_FEATURE* for
> > when this is needed. No need to extend a module with bloat if we don't
> > need it, likewise if a kernel was built without needing those things,
> > why bloat the modules with the extra information?
>
> To make sure I understand what you're asking for, are you suggesting:
> 1. A config flag for supporting parsing the extended format
> 2. A config flag for supporting parsing the existing format
> 3. A config flag for putting the extended format into produced modules
> 4. A config flag for putting the existing format into produced modules
> or some combination of the above?
>
> I'm currently reading this as #3, but figured I'd ask to be certain.
3), but if your kernel build does not require these extra things, then
a simple if !(IS_ENABLED) sanity check could be put in place to avoid
processing the information if the kernel didn't need it. It's a one line
change. So at run time, we build the same kernel with all that code in,
but it makes no sense to be processing modules with that stuff if
kernels did not need it.
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-11 22:33 ` Luis Chamberlain
@ 2024-10-11 23:45 ` Luis Chamberlain
2024-10-11 23:46 ` Luis Chamberlain
0 siblings, 1 reply; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-11 23:45 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Petr Pavlu, Sami Tolvanen, Daniel Gomez, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
Also, just as I asked Sami, coould you split this up into patch sets?
One with all the cleanups and elf validation code shifts. And then the
other code. That will let me pick up quickly the first patch set.
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-11 23:45 ` Luis Chamberlain
@ 2024-10-11 23:46 ` Luis Chamberlain
2024-10-15 23:22 ` Matthew Maurer
0 siblings, 1 reply; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-11 23:46 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Petr Pavlu, Sami Tolvanen, Daniel Gomez, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
On Fri, Oct 11, 2024 at 04:45:25PM -0700, Luis Chamberlain wrote:
>
> Also, just as I asked Sami, coould you split this up into patch sets?
> One with all the cleanups and elf validation code shifts. And then the
> other code. That will let me pick up quickly the first patch set.
Oh and if you can think of ways to enhance our test covereage on all
this as I noted to Sami, it would be greatly appreciated.
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-11 23:46 ` Luis Chamberlain
@ 2024-10-15 23:22 ` Matthew Maurer
2024-10-16 23:21 ` Luis Chamberlain
0 siblings, 1 reply; 35+ messages in thread
From: Matthew Maurer @ 2024-10-15 23:22 UTC (permalink / raw)
To: Luis Chamberlain
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Petr Pavlu, Sami Tolvanen, Daniel Gomez, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
So, the basic things I can think of to test here are:
1. The kernel can still load the previous MODVERSIONS format
2. The kernel can load the new MODVERSIONS format
3. If we artificially tweak a CRC in the previous format, it will fail to load.
4. If we artificially tweak a CRC in the new format, it will fail to load.
5. With CONFIG_EXTENDED_MODVERSIONS enabled, the kernel will build and
load modules with long symbol names, with MODVERSIONS enabled.
Is there anything else you were thinking of here, or are those the
kinds of checks you were envisioning?
On Fri, Oct 11, 2024 at 4:46 PM Luis Chamberlain <mcgrof@kernel.org> wrote:
>
> On Fri, Oct 11, 2024 at 04:45:25PM -0700, Luis Chamberlain wrote:
> >
> > Also, just as I asked Sami, coould you split this up into patch sets?
> > One with all the cleanups and elf validation code shifts. And then the
> > other code. That will let me pick up quickly the first patch set.
>
> Oh and if you can think of ways to enhance our test covereage on all
> this as I noted to Sami, it would be greatly appreciated.
>
> Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-15 23:22 ` Matthew Maurer
@ 2024-10-16 23:21 ` Luis Chamberlain
2024-10-17 4:41 ` Christophe Leroy
2024-10-17 12:08 ` Helge Deller
0 siblings, 2 replies; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-16 23:21 UTC (permalink / raw)
To: Matthew Maurer, Lucas De Marchi, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, Helge Deller
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, linuxppc-dev
On Tue, Oct 15, 2024 at 04:22:22PM -0700, Matthew Maurer wrote:
> So, the basic things I can think of to test here are:
>
> 1. The kernel can still load the previous MODVERSIONS format
> 2. The kernel can load the new MODVERSIONS format
> 3. If we artificially tweak a CRC in the previous format, it will fail to load.
> 4. If we artificially tweak a CRC in the new format, it will fail to load.
> 5. With CONFIG_EXTENDED_MODVERSIONS enabled, the kernel will build and
> load modules with long symbol names, with MODVERSIONS enabled.
>
> Is there anything else you were thinking of here, or are those the
> kinds of checks you were envisioning?
That sounds great. Yeah, the above would be great to test. A while ago
I wrote a new modules selftests in order to test possible improvements
on find_symbol() but I also did this due to push the limits of the
numbers of symbols we could support. I wrote all this to also test the
possible 64-bit alignment benefits of __ksymtab_ sections on
architectures without CONFIG_HAVE_ARCH_PREL32_RELOCATIONS (e.g. ppc64,
ppc64le, parisc, s390x,...). But come to think of it, you might be
able to easily leverage this to also just test long symbols by self
generated symbols as another test case. In case its useful to you I've
put this in a rebased branch 20241016-modules-symtab branch. Feel free
to use as you see fit.
I forget what we concluded on Helge Deller's alignement patches, I think
there was an idea on how to address the alignment through other means.
[0] https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=20241016-modules-symtab
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-16 23:21 ` Luis Chamberlain
@ 2024-10-17 4:41 ` Christophe Leroy
2024-10-17 12:08 ` Helge Deller
1 sibling, 0 replies; 35+ messages in thread
From: Christophe Leroy @ 2024-10-17 4:41 UTC (permalink / raw)
To: Luis Chamberlain, Matthew Maurer, Lucas De Marchi, Petr Pavlu,
Sami Tolvanen, Daniel Gomez, Helge Deller
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Madhavan Srinivasan, Boqun Feng,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, linuxppc-dev
Le 17/10/2024 à 01:21, Luis Chamberlain a écrit :
> On Tue, Oct 15, 2024 at 04:22:22PM -0700, Matthew Maurer wrote:
>> So, the basic things I can think of to test here are:
>>
>> 1. The kernel can still load the previous MODVERSIONS format
>> 2. The kernel can load the new MODVERSIONS format
>> 3. If we artificially tweak a CRC in the previous format, it will fail to load.
>> 4. If we artificially tweak a CRC in the new format, it will fail to load.
>> 5. With CONFIG_EXTENDED_MODVERSIONS enabled, the kernel will build and
>> load modules with long symbol names, with MODVERSIONS enabled.
>>
>> Is there anything else you were thinking of here, or are those the
>> kinds of checks you were envisioning?
>
> That sounds great. Yeah, the above would be great to test. A while ago
> I wrote a new modules selftests in order to test possible improvements
> on find_symbol() but I also did this due to push the limits of the
> numbers of symbols we could support. I wrote all this to also test the
> possible 64-bit alignment benefits of __ksymtab_ sections on
> architectures without CONFIG_HAVE_ARCH_PREL32_RELOCATIONS (e.g. ppc64,
> ppc64le, parisc, s390x,...). But come to think of it, you might be
> able to easily leverage this to also just test long symbols by self
> generated symbols as another test case. In case its useful to you I've
> put this in a rebased branch 20241016-modules-symtab branch. Feel free
> to use as you see fit.
By reading this, I discovered that was initially added to powerpc by
commit 271ca788774a ("arch: enable relative relocations for arm64, power
and x86") and then removed due to problem with modules, see commit
ff69279a44e9 ("powerpc: disable support for relative ksymtab references")
Wouldn't it be better to try and fix modules and activate again
CONFIG_HAVE_ARCH_PREL32_RELOCATIONS on powerpc ?
Christophe
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-16 23:21 ` Luis Chamberlain
2024-10-17 4:41 ` Christophe Leroy
@ 2024-10-17 12:08 ` Helge Deller
2024-10-19 20:45 ` Luis Chamberlain
1 sibling, 1 reply; 35+ messages in thread
From: Helge Deller @ 2024-10-17 12:08 UTC (permalink / raw)
To: Luis Chamberlain, Matthew Maurer, Lucas De Marchi, Petr Pavlu,
Sami Tolvanen, Daniel Gomez
Cc: masahiroy, ndesaulniers, ojeda, gary, Michael Ellerman,
Alex Gaynor, Benjamin Gray, Naveen N Rao, rust-for-linux,
linux-kbuild, linux-kernel, neal, marcan, j, asahi, linux-modules,
Nicholas Piggin, Christophe Leroy, Madhavan Srinivasan,
Boqun Feng, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Alice Ryhl, Trevor Gross, linuxppc-dev
Hi Luis,
On 10/17/24 01:21, Luis Chamberlain wrote:
> That sounds great. Yeah, the above would be great to test. A while ago
> I wrote a new modules selftests in order to test possible improvements
> on find_symbol() but I also did this due to push the limits of the
> numbers of symbols we could support. I wrote all this to also test the
> possible 64-bit alignment benefits of __ksymtab_ sections on
> architectures without CONFIG_HAVE_ARCH_PREL32_RELOCATIONS (e.g. ppc64,
> ppc64le, parisc, s390x,...). [....]
>
> I forget what we concluded on Helge Deller's alignement patches, I think
> there was an idea on how to address the alignment through other means.
>
> [0] https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=20241016-modules-symtab
I stumbled upon the unaligned-memory-access.rst document [1].
Please read it, as it is a really good document, and the section
"Why unaligned access is bad" states:
It should be obvious from the above that if your code causes unaligned
memory accesses to happen, your code will not work correctly on certain
platforms and will cause performance problems on others.
With this in mind, you really should apply both of my alignment
patches which you currently carry in [0].
For parisc I partly solved the issue by fixing the arch-specific kernel unalignment
handler, but every time module sections are stored unaligned, it triggers
performance degregation on parisc (and other sensitive platforms).
I suggest you apply them unconditionally.
Helge
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/core-api/unaligned-memory-access.rst
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-17 12:08 ` Helge Deller
@ 2024-10-19 20:45 ` Luis Chamberlain
2024-10-21 19:35 ` Luis Chamberlain
0 siblings, 1 reply; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-19 20:45 UTC (permalink / raw)
To: Helge Deller
Cc: Matthew Maurer, Lucas De Marchi, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, masahiroy, ndesaulniers, ojeda, gary,
Michael Ellerman, Alex Gaynor, Benjamin Gray, Naveen N Rao,
rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Nicholas Piggin, Christophe Leroy,
Madhavan Srinivasan, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
linuxppc-dev
On Thu, Oct 17, 2024 at 02:08:19PM +0200, Helge Deller wrote:
> Hi Luis,
>
> On 10/17/24 01:21, Luis Chamberlain wrote:
> > That sounds great. Yeah, the above would be great to test. A while ago
> > I wrote a new modules selftests in order to test possible improvements
> > on find_symbol() but I also did this due to push the limits of the
> > numbers of symbols we could support. I wrote all this to also test the
> > possible 64-bit alignment benefits of __ksymtab_ sections on
> > architectures without CONFIG_HAVE_ARCH_PREL32_RELOCATIONS (e.g. ppc64,
> > ppc64le, parisc, s390x,...). [....]
> >
> > I forget what we concluded on Helge Deller's alignement patches, I think
> > there was an idea on how to address the alignment through other means.
> >
> > [0] https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=20241016-modules-symtab
>
> I stumbled upon the unaligned-memory-access.rst document [1].
> Please read it, as it is a really good document, and the section
> "Why unaligned access is bad" states:
> It should be obvious from the above that if your code causes unaligned
> memory accesses to happen, your code will not work correctly on certain
> platforms and will cause performance problems on others.
>
> With this in mind, you really should apply both of my alignment
> patches which you currently carry in [0].
>
> For parisc I partly solved the issue by fixing the arch-specific kernel unalignment
> handler, but every time module sections are stored unaligned, it triggers
> performance degregation on parisc (and other sensitive platforms).
>
> I suggest you apply them unconditionally.
>
> Helge
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/core-api/unaligned-memory-access.rst
You're right, I've just referred to that doc and pushed to the new
linux modules [2] modules-next branch. This is also great timing so
that the work that is ongoing for Rust will take this into
consideration as well. I'll just post the test I wrote as separate
thing but it surely can be used to help test some of this later.
[2] git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 14/16] modules: Support extended MODVERSIONS info
2024-10-19 20:45 ` Luis Chamberlain
@ 2024-10-21 19:35 ` Luis Chamberlain
0 siblings, 0 replies; 35+ messages in thread
From: Luis Chamberlain @ 2024-10-21 19:35 UTC (permalink / raw)
To: Helge Deller
Cc: Matthew Maurer, Lucas De Marchi, Petr Pavlu, Sami Tolvanen,
Daniel Gomez, masahiroy, ndesaulniers, ojeda, gary,
Michael Ellerman, Alex Gaynor, Benjamin Gray, Naveen N Rao,
rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Nicholas Piggin, Christophe Leroy,
Madhavan Srinivasan, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
linuxppc-dev
On Sat, Oct 19, 2024 at 01:45:35PM -0700, Luis Chamberlain wrote:
> On Thu, Oct 17, 2024 at 02:08:19PM +0200, Helge Deller wrote:
> > Hi Luis,
> >
> > On 10/17/24 01:21, Luis Chamberlain wrote:
> > > That sounds great. Yeah, the above would be great to test. A while ago
> > > I wrote a new modules selftests in order to test possible improvements
> > > on find_symbol() but I also did this due to push the limits of the
> > > numbers of symbols we could support. I wrote all this to also test the
> > > possible 64-bit alignment benefits of __ksymtab_ sections on
> > > architectures without CONFIG_HAVE_ARCH_PREL32_RELOCATIONS (e.g. ppc64,
> > > ppc64le, parisc, s390x,...). [....]
> > >
> > > I forget what we concluded on Helge Deller's alignement patches, I think
> > > there was an idea on how to address the alignment through other means.
> > >
> > > [0] https://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux.git/log/?h=20241016-modules-symtab
> >
> > I stumbled upon the unaligned-memory-access.rst document [1].
> > Please read it, as it is a really good document, and the section
> > "Why unaligned access is bad" states:
> > It should be obvious from the above that if your code causes unaligned
> > memory accesses to happen, your code will not work correctly on certain
> > platforms and will cause performance problems on others.
> >
> > With this in mind, you really should apply both of my alignment
> > patches which you currently carry in [0].
> >
> > For parisc I partly solved the issue by fixing the arch-specific kernel unalignment
> > handler, but every time module sections are stored unaligned, it triggers
> > performance degregation on parisc (and other sensitive platforms).
> >
> > I suggest you apply them unconditionally.
> >
> > Helge
> >
> > [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/core-api/unaligned-memory-access.rst
>
> You're right, I've just referred to that doc and pushed to the new
> linux modules [2] modules-next branch. This is also great timing so
> that the work that is ongoing for Rust will take this into
> consideration as well. I'll just post the test I wrote as separate
> thing but it surely can be used to help test some of this later.
>
> [2] git://git.kernel.org/pub/scm/linux/kernel/git/modules/linux.git
Helge,
I went down memory lane and noted Masahiro asked for this to be done
in asm so I droped your patches. Feel free to post a new iteration.
Luis
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH v5 15/16] modpost: Produce extended modversion information
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (13 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 14/16] modules: Support extended MODVERSIONS info Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-25 23:38 ` [PATCH v5 16/16] export_report: Use new version info format Matthew Maurer
` (2 subsequent siblings)
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Matthew Maurer, Nathan Chancellor,
Nicolas Schier, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
Generate both the existing modversions format and the new extended one
when running modpost.
We no longer generate an error on long symbols in modpost, as they can
now be appropriately encoded in the extended section. These symbols will
be skipped in the previous encoding.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
scripts/mod/modpost.c | 39 ++++++++++++++++++++++++++++++++++++---
1 file changed, 36 insertions(+), 3 deletions(-)
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 107393a8c48a..f8b7b793d2a2 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -1840,15 +1840,48 @@ static void add_versions(struct buffer *b, struct module *mod)
continue;
}
if (strlen(s->name) >= MODULE_NAME_LEN) {
- error("too long symbol \"%s\" [%s.ko]\n",
- s->name, mod->name);
- break;
+ /* this symbol will only be in the extended info */
+ continue;
}
buf_printf(b, "\t{ %#8x, \"%s\" },\n",
s->crc, s->name);
}
buf_printf(b, "};\n");
+
+ buf_printf(b, "static const s32 ____version_ext_crcs[]\n");
+ buf_printf(b, "__used __section(\"__version_ext_crcs\") = {\n");
+ list_for_each_entry(s, &mod->unresolved_symbols, list) {
+ if (!s->module)
+ continue;
+ if (!s->crc_valid) {
+ /*
+ * We already warned on this when producing the legacy
+ * modversions table.
+ */
+ continue;
+ }
+ buf_printf(b, "\t%#8x,\n", s->crc);
+ }
+ buf_printf(b, "};\n");
+
+ buf_printf(b, "static const char ____version_ext_names[]\n");
+ buf_printf(b, "__used __section(\"__version_ext_names\") =\n");
+ list_for_each_entry(s, &mod->unresolved_symbols, list) {
+ if (!s->module)
+ continue;
+ if (!s->crc_valid) {
+ /*
+ * We already warned on this when producing the legacy
+ * modversions table.
+ * We need to skip its name too, as the indexes in
+ * both tables need to align.
+ */
+ continue;
+ }
+ buf_printf(b, "\t\"%s\\0\"\n", s->name);
+ }
+ buf_printf(b, ";\n");
}
static void add_depends(struct buffer *b, struct module *mod)
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* [PATCH v5 16/16] export_report: Use new version info format
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (14 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 15/16] modpost: Produce extended modversion information Matthew Maurer
@ 2024-09-25 23:38 ` Matthew Maurer
2024-09-26 22:53 ` [PATCH v5 00/16] Extended MODVERSIONS Support Sami Tolvanen
2024-09-28 21:35 ` Neal Gompa
17 siblings, 0 replies; 35+ messages in thread
From: Matthew Maurer @ 2024-09-25 23:38 UTC (permalink / raw)
To: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor,
Matthew Maurer
Cc: rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross
The new version info format has a superset of symbols in the old format.
Since this is a tool for in-tree modules, we don't need to parse the old
one with this tool any longer.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
scripts/export_report.pl | 22 ++++++++++------------
1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/scripts/export_report.pl b/scripts/export_report.pl
index dcef915405f3..6a37df6f947f 100755
--- a/scripts/export_report.pl
+++ b/scripts/export_report.pl
@@ -114,31 +114,29 @@ foreach my $thismod (@allcfiles) {
}
my $state=0;
+ # State map:
+ # 0 - Looking for names
+ # 1 - Scanning names
+ # 2 - Done
while ( <$module> ) {
chomp;
if ($state == 0) {
- $state = 1 if ($_ =~ /static const struct modversion_info/);
+ $state = 1 if ($_ =~ /__used __section\("__version_ext_names"\)/);
next;
}
if ($state == 1) {
- $state = 2 if ($_ =~ /__used __section\("__versions"\)/);
- next;
- }
- if ($state == 2) {
- if ( $_ =~ /};/ ) {
- $state = 3;
- next;
- }
- if ( $_ !~ /0x[0-9a-f]+,/ ) {
+ if ( $_ =~ /;/ ) {
+ $state = 2;
next;
}
- my $sym = (split /([,"])/,)[4];
+ $_ =~ /"(.*)\\0"/;
+ my $sym = $1;
my ($module, $value, $symbol, $gpl) = @{$SYMBOL{$sym}};
$SYMBOL{ $sym } = [ $module, $value+1, $symbol, $gpl];
push(@{$MODULE{$thismod}} , $sym);
}
}
- if ($state != 3) {
+ if ($state != 2) {
warn "WARNING:$thismod is not built with CONFIG_MODVERSIONS enabled\n";
$modversion_warnings++;
}
--
2.46.1.824.gd892dcdcdd-goog
^ permalink raw reply related [flat|nested] 35+ messages in thread
* Re: [PATCH v5 00/16] Extended MODVERSIONS Support
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (15 preceding siblings ...)
2024-09-25 23:38 ` [PATCH v5 16/16] export_report: Use new version info format Matthew Maurer
@ 2024-09-26 22:53 ` Sami Tolvanen
2024-09-28 21:35 ` Neal Gompa
17 siblings, 0 replies; 35+ messages in thread
From: Sami Tolvanen @ 2024-09-26 22:53 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor,
rust-for-linux, linux-kbuild, linux-kernel, neal, marcan, j,
asahi, linux-modules, Boqun Feng, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross
Hi Matt,
On Wed, Sep 25, 2024 at 11:39 PM Matthew Maurer <mmaurer@google.com> wrote:
>
> This patch series is intended for use alongside the Implement
> MODVERSIONS for RUST [1] series as a replacement for the symbol name
> hashing approach used there to enable RUST and MODVERSIONS at the same
> time.
>
> Elsewhere, we've seen a desire for long symbol name support for LTO
> symbol names [2], and the previous series came up [3] as a possible
> solution rather than hashing, which some have objected [4] to.
>
> This series adds a MODVERSIONS format which uses a section per column.
> This avoids userspace tools breaking if we need to make a similar change
> to the format in the future - we would do so by adding a new section,
> rather than editing the struct definition. In the new format, the name
> section is formatted as a concatenated sequence of NUL-terminated
> strings, which allows for arbitrary length names.
>
> Currently, this series emits both the extended format and the current
> format on all modules, and prefers the extended format when checking if
> present. I'm open to various other policies via Kconfig knobs, but this
> seemed like a good initial default.
>
> The refactor to MODVERSIONS is prefixed to this series as result of an
> explicit request [5] by Luis in response to the original patchset.
>
> If you are testing this patch alongside RUST by manually removing the
> !MODVERSIONS restriction (this series doesn't remove it, because the
> CRCs don't mean what we'd want them to yet, we need the DWARF patch for
> that) and have kernel hardening enabled, you may need the CPU
> Mitigations [6] series. Without it, the foo.mod.o file produced by the
> C compiler will reference __x86_return_thunk, but foo.o will not.
> This means that the version table will not contain a version for
> __x86_return_thunk, but foo.ko will reference it, which will result
> in a version check failure.
>
> [1] https://lore.kernel.org/all/20240617175818.58219-17-samitolvanen@google.com/
> [2] https://lore.kernel.org/lkml/20240605032120.3179157-1-song@kernel.org/
> [3] https://lore.kernel.org/lkml/ZoxbEEsK40ASi1cY@bombadil.infradead.org/
> [4] https://lore.kernel.org/lkml/0b2697fd-7ab4-469f-83a6-ec9ebc701ba0@suse.com/
> [5] https://lore.kernel.org/lkml/ZVZNh%2FPA5HiVRkeb@bombadil.infradead.org/
> [6] https://lore.kernel.org/all/20240725183325.122827-1-ojeda@kernel.org/
>
> Changes in v5:
> - Addresses Sami's comments from v3 that I missed in v4 (missing early
> return, extra parens)
v5 looks good to me, thank you for fixing these issues. I tested this
with my latest Rust modversions patches [1] and everything seems to
work for me (on x86_64, arm64, and riscv64 w/ clang). For the series:
Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Sami Tolvanen <samitolvanen@google.com>
[1] https://github.com/samitolvanen/linux/commits/rustmodversions-v3
Sami
^ permalink raw reply [flat|nested] 35+ messages in thread
* Re: [PATCH v5 00/16] Extended MODVERSIONS Support
2024-09-25 23:38 [PATCH v5 00/16] Extended MODVERSIONS Support Matthew Maurer
` (16 preceding siblings ...)
2024-09-26 22:53 ` [PATCH v5 00/16] Extended MODVERSIONS Support Sami Tolvanen
@ 2024-09-28 21:35 ` Neal Gompa
17 siblings, 0 replies; 35+ messages in thread
From: Neal Gompa @ 2024-09-28 21:35 UTC (permalink / raw)
To: Matthew Maurer
Cc: masahiroy, ndesaulniers, ojeda, gary, mcgrof, Alex Gaynor,
rust-for-linux, linux-kbuild, linux-kernel, marcan, j, asahi,
linux-modules, Boqun Feng, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross
On Wed, Sep 25, 2024 at 7:39 PM Matthew Maurer <mmaurer@google.com> wrote:
>
> This patch series is intended for use alongside the Implement
> MODVERSIONS for RUST [1] series as a replacement for the symbol name
> hashing approach used there to enable RUST and MODVERSIONS at the same
> time.
>
> Elsewhere, we've seen a desire for long symbol name support for LTO
> symbol names [2], and the previous series came up [3] as a possible
> solution rather than hashing, which some have objected [4] to.
>
> This series adds a MODVERSIONS format which uses a section per column.
> This avoids userspace tools breaking if we need to make a similar change
> to the format in the future - we would do so by adding a new section,
> rather than editing the struct definition. In the new format, the name
> section is formatted as a concatenated sequence of NUL-terminated
> strings, which allows for arbitrary length names.
>
> Currently, this series emits both the extended format and the current
> format on all modules, and prefers the extended format when checking if
> present. I'm open to various other policies via Kconfig knobs, but this
> seemed like a good initial default.
>
> The refactor to MODVERSIONS is prefixed to this series as result of an
> explicit request [5] by Luis in response to the original patchset.
>
> If you are testing this patch alongside RUST by manually removing the
> !MODVERSIONS restriction (this series doesn't remove it, because the
> CRCs don't mean what we'd want them to yet, we need the DWARF patch for
> that) and have kernel hardening enabled, you may need the CPU
> Mitigations [6] series. Without it, the foo.mod.o file produced by the
> C compiler will reference __x86_return_thunk, but foo.o will not.
> This means that the version table will not contain a version for
> __x86_return_thunk, but foo.ko will reference it, which will result
> in a version check failure.
>
> [1] https://lore.kernel.org/all/20240617175818.58219-17-samitolvanen@google.com/
> [2] https://lore.kernel.org/lkml/20240605032120.3179157-1-song@kernel.org/
> [3] https://lore.kernel.org/lkml/ZoxbEEsK40ASi1cY@bombadil.infradead.org/
> [4] https://lore.kernel.org/lkml/0b2697fd-7ab4-469f-83a6-ec9ebc701ba0@suse.com/
> [5] https://lore.kernel.org/lkml/ZVZNh%2FPA5HiVRkeb@bombadil.infradead.org/
> [6] https://lore.kernel.org/all/20240725183325.122827-1-ojeda@kernel.org/
>
> Changes in v5:
> - Addresses Sami's comments from v3 that I missed in v4 (missing early
> return, extra parens)
>
> v4: https://lore.kernel.org/asahi/20240924212024.540574-1-mmaurer@google.com/
> - Fix incorrect dot munging in PPC
>
> v3: https://lore.kernel.org/lkml/87le0w2hop.fsf@mail.lhotse/T/
> - Split up the module verification refactor into smaller patches, per
> Greg K-H's suggestion.
>
> v2: https://lore.kernel.org/all/20231118025748.2778044-1-mmaurer@google.com/
> - Add loading/verification refactor before modifying, per Luis's request
>
> v1: https://lore.kernel.org/rust-for-linux/20231115185858.2110875-1-mmaurer@google.com/
>
> Matthew Maurer (16):
> module: Take const arg in validate_section_offset
> module: Factor out elf_validity_ehdr
> module: Factor out elf_validity_cache_sechdrs
> module: Factor out elf_validity_cache_secstrings
> module: Factor out elf_validity_cache_index_info
> module: Factor out elf_validity_cache_index_mod
> module: Factor out elf_validity_cache_index_sym
> module: Factor out elf_validity_cache_index_str
> module: Group section index calculations together
> module: Factor out elf_validity_cache_strtab
> module: Additional validation in elf_validity_cache_strtab
> module: Reformat struct for code style
> export_report: Rehabilitate script
> modules: Support extended MODVERSIONS info
> modpost: Produce extended modversion information
> export_report: Use new version info format
>
> arch/powerpc/kernel/module_64.c | 23 +-
> kernel/module/internal.h | 18 +-
> kernel/module/main.c | 647 ++++++++++++++++++++++++--------
> kernel/module/version.c | 45 +++
> scripts/export_report.pl | 17 +-
> scripts/mod/modpost.c | 39 +-
> 6 files changed, 628 insertions(+), 161 deletions(-)
>
> --
> 2.46.1.824.gd892dcdcdd-goog
>
>
The series looks straightforward and reasonable to me.
Acked-by: Neal Gompa <neal@gompa.dev>
--
真実はいつも一つ!/ Always, there's only one truth!
^ permalink raw reply [flat|nested] 35+ messages in thread