Commit ea07890a680273b25127129fb555aac0d9324bea

Authored by Alexey Dobriyan
Committed by Linus Torvalds
1 parent ae84e32470

Fix race between rmmod and cat /proc/kallsyms

module_get_kallsym() leaks "struct module *" outside of module_mutex which is
no-no, because module can dissapear right after mutex unlock.

Copy all needed information from inside module_mutex into caller-supplied
space.

[bunk@stusta.de: is_exported() can now become static]
Signed-off-by: Alexey Dobriyan <adobriyan@sw.ru>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 3 changed files with 29 additions and 34 deletions Side-by-side Diff

include/linux/module.h
... ... @@ -370,16 +370,14 @@
370 370 struct module *__module_text_address(unsigned long addr);
371 371 int is_module_address(unsigned long addr);
372 372  
373   -/* Returns module and fills in value, defined and namebuf, or NULL if
  373 +/* Returns 0 and fills in value, defined and namebuf, or -ERANGE if
374 374 symnum out of range. */
375   -struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
376   - char *type, char *name);
  375 +int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
  376 + char *name, char *module_name, int *exported);
377 377  
378 378 /* Look for this name: can be of form module:name. */
379 379 unsigned long module_kallsyms_lookup_name(const char *name);
380 380  
381   -int is_exported(const char *name, const struct module *mod);
382   -
383 381 extern void __module_put_and_exit(struct module *mod, long code)
384 382 __attribute__((noreturn));
385 383 #define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code);
386 384  
387 385  
... ... @@ -527,19 +525,14 @@
527 525 return NULL;
528 526 }
529 527  
530   -static inline struct module *module_get_kallsym(unsigned int symnum,
531   - unsigned long *value,
532   - char *type, char *name)
  528 +static inline int module_get_kallsym(unsigned int symnum, unsigned long *value,
  529 + char *type, char *name,
  530 + char *module_name, int *exported)
533 531 {
534   - return NULL;
  532 + return -ERANGE;
535 533 }
536 534  
537 535 static inline unsigned long module_kallsyms_lookup_name(const char *name)
538   -{
539   - return 0;
540   -}
541   -
542   -static inline int is_exported(const char *name, const struct module *mod)
543 536 {
544 537 return 0;
545 538 }
... ... @@ -301,25 +301,20 @@
301 301 struct kallsym_iter
302 302 {
303 303 loff_t pos;
304   - struct module *owner;
305 304 unsigned long value;
306 305 unsigned int nameoff; /* If iterating in core kernel symbols */
307 306 char type;
308 307 char name[KSYM_NAME_LEN+1];
  308 + char module_name[MODULE_NAME_LEN + 1];
  309 + int exported;
309 310 };
310 311  
311 312 static int get_ksymbol_mod(struct kallsym_iter *iter)
312 313 {
313   - iter->owner = module_get_kallsym(iter->pos - kallsyms_num_syms,
314   - &iter->value, &iter->type,
315   - iter->name);
316   - if (iter->owner == NULL)
  314 + if (module_get_kallsym(iter->pos - kallsyms_num_syms, &iter->value,
  315 + &iter->type, iter->name, iter->module_name,
  316 + &iter->exported) < 0)
317 317 return 0;
318   -
319   - /* Label it "global" if it is exported, "local" if not exported. */
320   - iter->type = is_exported(iter->name, iter->owner)
321   - ? toupper(iter->type) : tolower(iter->type);
322   -
323 318 return 1;
324 319 }
325 320  
... ... @@ -328,7 +323,7 @@
328 323 {
329 324 unsigned off = iter->nameoff;
330 325  
331   - iter->owner = NULL;
  326 + iter->module_name[0] = '\0';
332 327 iter->value = kallsyms_addresses[iter->pos];
333 328  
334 329 iter->type = kallsyms_get_symbol_type(off);
335 330  
... ... @@ -392,12 +387,17 @@
392 387 if (!iter->name[0])
393 388 return 0;
394 389  
395   - if (iter->owner)
  390 + if (iter->module_name[0]) {
  391 + char type;
  392 +
  393 + /* Label it "global" if it is exported,
  394 + * "local" if not exported. */
  395 + type = iter->exported ? toupper(iter->type) :
  396 + tolower(iter->type);
396 397 seq_printf(m, "%0*lx %c %s\t[%s]\n",
397 398 (int)(2*sizeof(void*)),
398   - iter->value, iter->type, iter->name,
399   - module_name(iter->owner));
400   - else
  399 + iter->value, type, iter->name, iter->module_name);
  400 + } else
401 401 seq_printf(m, "%0*lx %c %s\n",
402 402 (int)(2*sizeof(void*)),
403 403 iter->value, iter->type, iter->name);
... ... @@ -1472,7 +1472,7 @@
1472 1472 }
1473 1473  
1474 1474 #ifdef CONFIG_KALLSYMS
1475   -int is_exported(const char *name, const struct module *mod)
  1475 +static int is_exported(const char *name, const struct module *mod)
1476 1476 {
1477 1477 if (!mod && lookup_symbol(name, __start___ksymtab, __stop___ksymtab))
1478 1478 return 1;
... ... @@ -2124,8 +2124,8 @@
2124 2124 return NULL;
2125 2125 }
2126 2126  
2127   -struct module *module_get_kallsym(unsigned int symnum, unsigned long *value,
2128   - char *type, char *name)
  2127 +int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
  2128 + char *name, char *module_name, int *exported)
2129 2129 {
2130 2130 struct module *mod;
2131 2131  
2132 2132  
2133 2133  
... ... @@ -2136,13 +2136,15 @@
2136 2136 *type = mod->symtab[symnum].st_info;
2137 2137 strlcpy(name, mod->strtab + mod->symtab[symnum].st_name,
2138 2138 KSYM_NAME_LEN + 1);
  2139 + strlcpy(module_name, mod->name, MODULE_NAME_LEN + 1);
  2140 + *exported = is_exported(name, mod);
2139 2141 mutex_unlock(&module_mutex);
2140   - return mod;
  2142 + return 0;
2141 2143 }
2142 2144 symnum -= mod->num_symtab;
2143 2145 }
2144 2146 mutex_unlock(&module_mutex);
2145   - return NULL;
  2147 + return -ERANGE;
2146 2148 }
2147 2149  
2148 2150 static unsigned long mod_find_symname(struct module *mod, const char *name)