@@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name)
195
195
return 0 ;
196
196
}
197
197
198
+ /**
199
+ * find_any_unique_sec() - Find a unique section index by name
200
+ * @info: Load info for the module to scan
201
+ * @name: Name of the section we're looking for
202
+ *
203
+ * Locates a unique section by name. Ignores SHF_ALLOC.
204
+ *
205
+ * Return: Section index if found uniquely, zero if absent, negative count
206
+ * of total instances if multiple were found.
207
+ */
208
+ static int find_any_unique_sec (const struct load_info * info , const char * name )
209
+ {
210
+ unsigned int idx ;
211
+ unsigned int count = 0 ;
212
+ int i ;
213
+
214
+ for (i = 1 ; i < info -> hdr -> e_shnum ; i ++ ) {
215
+ if (strcmp (info -> secstrings + info -> sechdrs [i ].sh_name ,
216
+ name ) == 0 ) {
217
+ count ++ ;
218
+ idx = i ;
219
+ }
220
+ }
221
+ if (count == 1 ) {
222
+ return idx ;
223
+ } else if (count == 0 ) {
224
+ return 0 ;
225
+ } else {
226
+ return - count ;
227
+ }
228
+ }
229
+
198
230
/* Find a module section, or NULL. */
199
231
static void * section_addr (const struct load_info * info , const char * name )
200
232
{
@@ -1854,6 +1886,39 @@ static int elf_validity_cache_secstrings(struct load_info *info)
1854
1886
return 0 ;
1855
1887
}
1856
1888
1889
+ /**
1890
+ * elf_validity_cache_index_info() - Validate and cache modinfo section
1891
+ * @info: Load info to populate the modinfo index on.
1892
+ * Must have &load_info->sechdrs and &load_info->secstrings populated
1893
+ *
1894
+ * Checks that if there is a .modinfo section, it is unique.
1895
+ * Then, it caches its index in &load_info->index.info.
1896
+ * Finally, it tries to populate the name to improve error messages.
1897
+ *
1898
+ * Return: %0 if valid, %-ENOEXEC if multiple modinfo sections were found.
1899
+ */
1900
+ static int elf_validity_cache_index_info (struct load_info * info )
1901
+ {
1902
+ int info_idx ;
1903
+
1904
+ info_idx = find_any_unique_sec (info , ".modinfo" );
1905
+
1906
+ if (info_idx == 0 )
1907
+ /* Early return, no .modinfo */
1908
+ return 0 ;
1909
+
1910
+ if (info_idx < 0 ) {
1911
+ pr_err ("Only one .modinfo section must exist.\n" );
1912
+ return - ENOEXEC ;
1913
+ }
1914
+
1915
+ info -> index .info = info_idx ;
1916
+ /* Try to find a name early so we can log errors with a module name */
1917
+ info -> name = get_modinfo (info , "name" );
1918
+
1919
+ return 0 ;
1920
+ }
1921
+
1857
1922
/*
1858
1923
* Check userspace passed ELF module against our expectations, and cache
1859
1924
* useful variables for further processing as we go.
@@ -1880,13 +1945,15 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
1880
1945
Elf_Shdr * shdr ;
1881
1946
int err ;
1882
1947
unsigned int num_mod_secs = 0 , mod_idx ;
1883
- unsigned int num_info_secs = 0 , info_idx ;
1884
1948
unsigned int num_sym_secs = 0 , sym_idx ;
1885
1949
1886
1950
err = elf_validity_cache_sechdrs (info );
1887
1951
if (err < 0 )
1888
1952
return err ;
1889
1953
err = elf_validity_cache_secstrings (info );
1954
+ if (err < 0 )
1955
+ return err ;
1956
+ err = elf_validity_cache_index_info (info );
1890
1957
if (err < 0 )
1891
1958
return err ;
1892
1959
@@ -1912,24 +1979,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
1912
1979
".gnu.linkonce.this_module" ) == 0 ) {
1913
1980
num_mod_secs ++ ;
1914
1981
mod_idx = i ;
1915
- } else if (strcmp (info -> secstrings + shdr -> sh_name ,
1916
- ".modinfo" ) == 0 ) {
1917
- num_info_secs ++ ;
1918
- info_idx = i ;
1919
1982
}
1920
1983
break ;
1921
1984
}
1922
1985
}
1923
1986
1924
- if (num_info_secs > 1 ) {
1925
- pr_err ("Only one .modinfo section must exist.\n" );
1926
- goto no_exec ;
1927
- } else if (num_info_secs == 1 ) {
1928
- /* Try to find a name early so we can log errors with a module name */
1929
- info -> index .info = info_idx ;
1930
- info -> name = get_modinfo (info , "name" );
1931
- }
1932
-
1933
1987
if (num_sym_secs != 1 ) {
1934
1988
pr_warn ("%s: module has no symbols (stripped?)\n" ,
1935
1989
info -> name ?: "(missing .modinfo section or name field)" );
0 commit comments