mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
module: use kflagstab instead of *_gpl sections
Read kflagstab section for vmlinux and modules to determine whether kernel symbols are GPL only. This patch eliminates the need for fragmenting the ksymtab for infering the value of GPL-only symbol flag, henceforth stop populating *_gpl versions of the ksymtab and kcrctab in modpost. Signed-off-by: Siddharth Nayyar <sidnayyar@google.com> Reviewed-by: Petr Pavlu <petr.pavlu@suse.com> Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
This commit is contained in:
committed by
Sami Tolvanen
parent
16d0e04f54
commit
55fcb926b6
@@ -57,6 +57,7 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
|
||||
extern const struct kernel_symbol __stop___ksymtab_gpl[];
|
||||
extern const u32 __start___kcrctab[];
|
||||
extern const u32 __start___kcrctab_gpl[];
|
||||
extern const u8 __start___kflagstab[];
|
||||
|
||||
#define KMOD_PATH_LEN 256
|
||||
extern char modprobe_path[];
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/extable.h>
|
||||
#include <linux/moduleloader.h>
|
||||
#include <linux/module_signature.h>
|
||||
#include <linux/module_symbol.h>
|
||||
#include <linux/trace_events.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kallsyms.h>
|
||||
@@ -87,7 +88,7 @@ struct mod_tree_root mod_tree __cacheline_aligned = {
|
||||
struct symsearch {
|
||||
const struct kernel_symbol *start, *stop;
|
||||
const u32 *crcs;
|
||||
enum mod_license license;
|
||||
const u8 *flagstab;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -364,19 +365,21 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms,
|
||||
struct find_symbol_arg *fsa)
|
||||
{
|
||||
struct kernel_symbol *sym;
|
||||
|
||||
if (!fsa->gplok && syms->license == GPL_ONLY)
|
||||
return false;
|
||||
u8 sym_flags;
|
||||
|
||||
sym = bsearch(fsa->name, syms->start, syms->stop - syms->start,
|
||||
sizeof(struct kernel_symbol), cmp_name);
|
||||
if (!sym)
|
||||
return false;
|
||||
|
||||
sym_flags = *(syms->flagstab + (sym - syms->start));
|
||||
if (!fsa->gplok && (sym_flags & KSYM_FLAG_GPL_ONLY))
|
||||
return false;
|
||||
|
||||
fsa->owner = owner;
|
||||
fsa->crc = symversion(syms->crcs, sym - syms->start);
|
||||
fsa->sym = sym;
|
||||
fsa->license = syms->license;
|
||||
fsa->license = (sym_flags & KSYM_FLAG_GPL_ONLY) ? GPL_ONLY : NOT_GPL_ONLY;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -387,36 +390,31 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms,
|
||||
*/
|
||||
bool find_symbol(struct find_symbol_arg *fsa)
|
||||
{
|
||||
static const struct symsearch arr[] = {
|
||||
{ __start___ksymtab, __stop___ksymtab, __start___kcrctab,
|
||||
NOT_GPL_ONLY },
|
||||
{ __start___ksymtab_gpl, __stop___ksymtab_gpl,
|
||||
__start___kcrctab_gpl,
|
||||
GPL_ONLY },
|
||||
const struct symsearch syms = {
|
||||
.start = __start___ksymtab,
|
||||
.stop = __stop___ksymtab,
|
||||
.crcs = __start___kcrctab,
|
||||
.flagstab = __start___kflagstab,
|
||||
};
|
||||
struct module *mod;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arr); i++)
|
||||
if (find_exported_symbol_in_section(&arr[i], NULL, fsa))
|
||||
return true;
|
||||
if (find_exported_symbol_in_section(&syms, NULL, fsa))
|
||||
return true;
|
||||
|
||||
list_for_each_entry_rcu(mod, &modules, list,
|
||||
lockdep_is_held(&module_mutex)) {
|
||||
struct symsearch arr[] = {
|
||||
{ mod->syms, mod->syms + mod->num_syms, mod->crcs,
|
||||
NOT_GPL_ONLY },
|
||||
{ mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms,
|
||||
mod->gpl_crcs,
|
||||
GPL_ONLY },
|
||||
const struct symsearch syms = {
|
||||
.start = mod->syms,
|
||||
.stop = mod->syms + mod->num_syms,
|
||||
.crcs = mod->crcs,
|
||||
.flagstab = mod->flagstab,
|
||||
};
|
||||
|
||||
if (mod->state == MODULE_STATE_UNFORMED)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(arr); i++)
|
||||
if (find_exported_symbol_in_section(&arr[i], mod, fsa))
|
||||
return true;
|
||||
if (find_exported_symbol_in_section(&syms, mod, fsa))
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
sizeof(*mod->gpl_syms),
|
||||
&mod->num_gpl_syms);
|
||||
mod->gpl_crcs = section_addr(info, "__kcrctab_gpl");
|
||||
mod->flagstab = section_addr(info, "__kflagstab");
|
||||
|
||||
#ifdef CONFIG_CONSTRUCTORS
|
||||
mod->ctors = section_objs(info, ".ctors",
|
||||
@@ -2884,8 +2883,12 @@ out_err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int check_export_symbol_versions(struct module *mod)
|
||||
static int check_export_symbol_sections(struct module *mod)
|
||||
{
|
||||
if (mod->num_syms && !mod->flagstab) {
|
||||
pr_err("%s: no flags for exported symbols\n", mod->name);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
#ifdef CONFIG_MODVERSIONS
|
||||
if ((mod->num_syms && !mod->crcs) ||
|
||||
(mod->num_gpl_syms && !mod->gpl_crcs)) {
|
||||
@@ -3501,7 +3504,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
|
||||
if (err)
|
||||
goto free_unload;
|
||||
|
||||
err = check_export_symbol_versions(mod);
|
||||
err = check_export_symbol_sections(mod);
|
||||
if (err)
|
||||
goto free_unload;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user