Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <mmaurer@google.com>
Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>

authored by

Matthew Maurer and committed by
Luis Chamberlain
3c5700ae c92aab81

+69 -37
+69 -37
kernel/module/main.c
··· 1789 1789 return 0; 1790 1790 } 1791 1791 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 + 1792 1857 /* 1793 1858 * Check userspace passed ELF module against our expectations, and cache 1794 1859 * useful variables for further processing as we go. ··· 1877 1812 static int elf_validity_cache_copy(struct load_info *info, int flags) 1878 1813 { 1879 1814 unsigned int i; 1880 - Elf_Shdr *shdr, *strhdr; 1815 + Elf_Shdr *shdr; 1881 1816 int err; 1882 1817 unsigned int num_mod_secs = 0, mod_idx; 1883 1818 unsigned int num_info_secs = 0, info_idx; ··· 1886 1821 err = elf_validity_cache_sechdrs(info); 1887 1822 if (err < 0) 1888 1823 return err; 1889 - 1890 - /* 1891 - * Verify if the section name table index is valid. 1892 - */ 1893 - if (info->hdr->e_shstrndx == SHN_UNDEF 1894 - || info->hdr->e_shstrndx >= info->hdr->e_shnum) { 1895 - pr_err("Invalid ELF section name index: %d || e_shstrndx (%d) >= e_shnum (%d)\n", 1896 - info->hdr->e_shstrndx, info->hdr->e_shstrndx, 1897 - info->hdr->e_shnum); 1898 - goto no_exec; 1899 - } 1900 - 1901 - strhdr = &info->sechdrs[info->hdr->e_shstrndx]; 1902 - 1903 - /* 1904 - * The section name table must be NUL-terminated, as required 1905 - * by the spec. This makes strcmp and pr_* calls that access 1906 - * strings in the section safe. 1907 - */ 1908 - info->secstrings = (void *)info->hdr + strhdr->sh_offset; 1909 - if (strhdr->sh_size == 0) { 1910 - pr_err("empty section name table\n"); 1911 - goto no_exec; 1912 - } 1913 - if (info->secstrings[strhdr->sh_size - 1] != '\0') { 1914 - pr_err("ELF Spec violation: section name table isn't null terminated\n"); 1915 - goto no_exec; 1916 - } 1824 + err = elf_validity_cache_secstrings(info); 1825 + if (err < 0) 1826 + return err; 1917 1827 1918 1828 for (i = 1; i < info->hdr->e_shnum; i++) { 1919 1829 shdr = &info->sechdrs[i]; ··· 1916 1876 ".modinfo") == 0) { 1917 1877 num_info_secs++; 1918 1878 info_idx = i; 1919 - } 1920 - 1921 - if (shdr->sh_flags & SHF_ALLOC) { 1922 - if (shdr->sh_name >= strhdr->sh_size) { 1923 - pr_err("Invalid ELF section name in module (section %u type %u)\n", 1924 - i, shdr->sh_type); 1925 - return -ENOEXEC; 1926 - } 1927 1879 } 1928 1880 break; 1929 1881 }