Skip to content

Commit 3c5700a

Browse files
maurermcgrof
authored andcommitted
module: Factor out elf_validity_cache_secstrings
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 <[email protected]> Reviewed-by: Sami Tolvanen <[email protected]> Signed-off-by: Luis Chamberlain <[email protected]>
1 parent c92aab8 commit 3c5700a

File tree

1 file changed

+69
-37
lines changed

1 file changed

+69
-37
lines changed

kernel/module/main.c

Lines changed: 69 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1789,6 +1789,71 @@ static int elf_validity_cache_sechdrs(struct load_info *info)
17891789
return 0;
17901790
}
17911791

1792+
/**
1793+
* elf_validity_cache_secstrings() - Caches section names if valid
1794+
* @info: Load info to cache section names from. Must have valid sechdrs.
1795+
*
1796+
* Specifically checks:
1797+
*
1798+
* * Section name table index is inbounds of section headers
1799+
* * Section name table is not empty
1800+
* * Section name table is NUL terminated
1801+
* * All section name offsets are inbounds of the section
1802+
*
1803+
* Then updates @info with a &load_info->secstrings pointer if valid.
1804+
*
1805+
* Return: %0 if valid, negative error code if validation failed.
1806+
*/
1807+
static int elf_validity_cache_secstrings(struct load_info *info)
1808+
{
1809+
Elf_Shdr *strhdr, *shdr;
1810+
char *secstrings;
1811+
int i;
1812+
1813+
/*
1814+
* Verify if the section name table index is valid.
1815+
*/
1816+
if (info->hdr->e_shstrndx == SHN_UNDEF
1817+
|| info->hdr->e_shstrndx >= info->hdr->e_shnum) {
1818+
pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n",
1819+
info->hdr->e_shstrndx, info->hdr->e_shstrndx,
1820+
info->hdr->e_shnum);
1821+
return -ENOEXEC;
1822+
}
1823+
1824+
strhdr = &info->sechdrs[info->hdr->e_shstrndx];
1825+
1826+
/*
1827+
* The section name table must be NUL-terminated, as required
1828+
* by the spec. This makes strcmp and pr_* calls that access
1829+
* strings in the section safe.
1830+
*/
1831+
secstrings = (void *)info->hdr + strhdr->sh_offset;
1832+
if (strhdr->sh_size == 0) {
1833+
pr_err("empty section name table\n");
1834+
return -ENOEXEC;
1835+
}
1836+
if (secstrings[strhdr->sh_size - 1] != '\0') {
1837+
pr_err("ELF Spec violation: section name table isn't null terminated\n");
1838+
return -ENOEXEC;
1839+
}
1840+
1841+
for (i = 0; i < info->hdr->e_shnum; i++) {
1842+
shdr = &info->sechdrs[i];
1843+
/* SHT_NULL means sh_name has an undefined value */
1844+
if (shdr->sh_type == SHT_NULL)
1845+
continue;
1846+
if (shdr->sh_name >= strhdr->sh_size) {
1847+
pr_err("Invalid ELF section name in module (section %u type %u)\n",
1848+
i, shdr->sh_type);
1849+
return -ENOEXEC;
1850+
}
1851+
}
1852+
1853+
info->secstrings = secstrings;
1854+
return 0;
1855+
}
1856+
17921857
/*
17931858
* Check userspace passed ELF module against our expectations, and cache
17941859
* useful variables for further processing as we go.
@@ -1812,7 +1877,7 @@ static int elf_validity_cache_sechdrs(struct load_info *info)
18121877
static int elf_validity_cache_copy(struct load_info *info, int flags)
18131878
{
18141879
unsigned int i;
1815-
Elf_Shdr *shdr, *strhdr;
1880+
Elf_Shdr *shdr;
18161881
int err;
18171882
unsigned int num_mod_secs = 0, mod_idx;
18181883
unsigned int num_info_secs = 0, info_idx;
@@ -1821,34 +1886,9 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
18211886
err = elf_validity_cache_sechdrs(info);
18221887
if (err < 0)
18231888
return err;
1824-
1825-
/*
1826-
* Verify if the section name table index is valid.
1827-
*/
1828-
if (info->hdr->e_shstrndx == SHN_UNDEF
1829-
|| info->hdr->e_shstrndx >= info->hdr->e_shnum) {
1830-
pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n",
1831-
info->hdr->e_shstrndx, info->hdr->e_shstrndx,
1832-
info->hdr->e_shnum);
1833-
goto no_exec;
1834-
}
1835-
1836-
strhdr = &info->sechdrs[info->hdr->e_shstrndx];
1837-
1838-
/*
1839-
* The section name table must be NUL-terminated, as required
1840-
* by the spec. This makes strcmp and pr_* calls that access
1841-
* strings in the section safe.
1842-
*/
1843-
info->secstrings = (void *)info->hdr + strhdr->sh_offset;
1844-
if (strhdr->sh_size == 0) {
1845-
pr_err("empty section name table\n");
1846-
goto no_exec;
1847-
}
1848-
if (info->secstrings[strhdr->sh_size - 1] != '\0') {
1849-
pr_err("ELF Spec violation: section name table isn't null terminated\n");
1850-
goto no_exec;
1851-
}
1889+
err = elf_validity_cache_secstrings(info);
1890+
if (err < 0)
1891+
return err;
18521892

18531893
for (i = 1; i < info->hdr->e_shnum; i++) {
18541894
shdr = &info->sechdrs[i];
@@ -1877,14 +1917,6 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
18771917
num_info_secs++;
18781918
info_idx = i;
18791919
}
1880-
1881-
if (shdr->sh_flags & SHF_ALLOC) {
1882-
if (shdr->sh_name >= strhdr->sh_size) {
1883-
pr_err("Invalid ELF section name in module (section %u type %u)\n",
1884-
i, shdr->sh_type);
1885-
return -ENOEXEC;
1886-
}
1887-
}
18881920
break;
18891921
}
18901922
}

0 commit comments

Comments
 (0)