1111#include <linux/extable.h>
1212#include <linux/moduleloader.h>
1313#include <linux/module_signature.h>
14+ #include <linux/module_symbol.h>
1415#include <linux/trace_events.h>
1516#include <linux/init.h>
1617#include <linux/kallsyms.h>
@@ -87,7 +88,7 @@ struct mod_tree_root mod_tree __cacheline_aligned = {
8788struct symsearch {
8889 const struct kernel_symbol * start , * stop ;
8990 const u32 * crcs ;
90- enum mod_license license ;
91+ const u8 * flagstab ;
9192};
9293
9394/*
@@ -364,19 +365,21 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms,
364365 struct find_symbol_arg * fsa )
365366{
366367 struct kernel_symbol * sym ;
367-
368- if (!fsa -> gplok && syms -> license == GPL_ONLY )
369- return false;
368+ u8 sym_flags ;
370369
371370 sym = bsearch (fsa -> name , syms -> start , syms -> stop - syms -> start ,
372371 sizeof (struct kernel_symbol ), cmp_name );
373372 if (!sym )
374373 return false;
375374
375+ sym_flags = * (syms -> flagstab + (sym - syms -> start ));
376+ if (!fsa -> gplok && (sym_flags & KSYM_FLAG_GPL_ONLY ))
377+ return false;
378+
376379 fsa -> owner = owner ;
377380 fsa -> crc = symversion (syms -> crcs , sym - syms -> start );
378381 fsa -> sym = sym ;
379- fsa -> license = syms -> license ;
382+ fsa -> license = ( sym_flags & KSYM_FLAG_GPL_ONLY ) ? GPL_ONLY : NOT_GPL_ONLY ;
380383
381384 return true;
382385}
@@ -387,36 +390,31 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms,
387390 */
388391bool find_symbol (struct find_symbol_arg * fsa )
389392{
390- static const struct symsearch arr [] = {
391- { __start___ksymtab , __stop___ksymtab , __start___kcrctab ,
392- NOT_GPL_ONLY },
393- { __start___ksymtab_gpl , __stop___ksymtab_gpl ,
394- __start___kcrctab_gpl ,
395- GPL_ONLY },
393+ const struct symsearch syms = {
394+ .start = __start___ksymtab ,
395+ .stop = __stop___ksymtab ,
396+ .crcs = __start___kcrctab ,
397+ .flagstab = __start___kflagstab ,
396398 };
397399 struct module * mod ;
398- unsigned int i ;
399400
400- for (i = 0 ; i < ARRAY_SIZE (arr ); i ++ )
401- if (find_exported_symbol_in_section (& arr [i ], NULL , fsa ))
402- return true;
401+ if (find_exported_symbol_in_section (& syms , NULL , fsa ))
402+ return true;
403403
404404 list_for_each_entry_rcu (mod , & modules , list ,
405405 lockdep_is_held (& module_mutex )) {
406- struct symsearch arr [] = {
407- { mod -> syms , mod -> syms + mod -> num_syms , mod -> crcs ,
408- NOT_GPL_ONLY },
409- { mod -> gpl_syms , mod -> gpl_syms + mod -> num_gpl_syms ,
410- mod -> gpl_crcs ,
411- GPL_ONLY },
406+ const struct symsearch syms = {
407+ .start = mod -> syms ,
408+ .stop = mod -> syms + mod -> num_syms ,
409+ .crcs = mod -> crcs ,
410+ .flagstab = mod -> flagstab ,
412411 };
413412
414413 if (mod -> state == MODULE_STATE_UNFORMED )
415414 continue ;
416415
417- for (i = 0 ; i < ARRAY_SIZE (arr ); i ++ )
418- if (find_exported_symbol_in_section (& arr [i ], mod , fsa ))
419- return true;
416+ if (find_exported_symbol_in_section (& syms , mod , fsa ))
417+ return true;
420418 }
421419
422420 pr_debug ("Failed to find symbol %s\n" , fsa -> name );
@@ -2681,6 +2679,7 @@ static int find_module_sections(struct module *mod, struct load_info *info)
26812679 sizeof (* mod -> gpl_syms ),
26822680 & mod -> num_gpl_syms );
26832681 mod -> gpl_crcs = section_addr (info , "__kcrctab_gpl" );
2682+ mod -> flagstab = section_addr (info , "__kflagstab" );
26842683
26852684#ifdef CONFIG_CONSTRUCTORS
26862685 mod -> ctors = section_objs (info , ".ctors" ,
@@ -2884,8 +2883,12 @@ static int move_module(struct module *mod, struct load_info *info)
28842883 return ret ;
28852884}
28862885
2887- static int check_export_symbol_versions (struct module * mod )
2886+ static int check_export_symbol_sections (struct module * mod )
28882887{
2888+ if (mod -> num_syms && !mod -> flagstab ) {
2889+ pr_err ("%s: no flags for exported symbols\n" , mod -> name );
2890+ return - ENOEXEC ;
2891+ }
28892892#ifdef CONFIG_MODVERSIONS
28902893 if ((mod -> num_syms && !mod -> crcs ) ||
28912894 (mod -> num_gpl_syms && !mod -> gpl_crcs )) {
@@ -3501,7 +3504,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
35013504 if (err )
35023505 goto free_unload ;
35033506
3504- err = check_export_symbol_versions (mod );
3507+ err = check_export_symbol_sections (mod );
35053508 if (err )
35063509 goto free_unload ;
35073510
0 commit comments