lkml.org 
[lkml]   [2018]   [Jul]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3/6] modpost: add support for checking symbol namespaces.
    Date
    Emits a warning whenever a module refers to an exported symbol without
    explicitly importing the namespace that it is defined in.

    Example:

    WARNING: module ums-usbat uses symbol usb_stor_resume from namespace
    USB_STORAGE_NS, but does not import it.

    Signed-off-by: Martijn Coenen <maco@android.com>
    ---
    scripts/mod/modpost.c | 70 +++++++++++++++++++++++++++++++++++++++----
    scripts/mod/modpost.h | 7 +++++
    2 files changed, 72 insertions(+), 5 deletions(-)

    diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
    index 1663fb19343a..a56a8461a96a 100644
    --- a/scripts/mod/modpost.c
    +++ b/scripts/mod/modpost.c
    @@ -165,6 +165,7 @@ struct symbol {
    struct module *module;
    unsigned int crc;
    int crc_valid;
    + const char *ns; /* namespace */
    unsigned int weak:1;
    unsigned int vmlinux:1; /* 1 if symbol is defined in vmlinux */
    unsigned int kernel:1; /* 1 if symbol is from kernel
    @@ -234,6 +235,35 @@ static struct symbol *find_symbol(const char *name)
    return NULL;
    }

    +static bool contains_namespace(struct namespace_list *list, const char *ns)
    +{
    + struct namespace_list *ns_entry;
    +
    + for (ns_entry = list; ns_entry != NULL; ns_entry = ns_entry->next) {
    + if (strcmp(ns_entry->namespace, ns) == 0)
    + return true;
    + }
    +
    + return false;
    +}
    +
    +static void add_namespace(struct namespace_list **list, const char *ns)
    +{
    + struct namespace_list *ns_entry;
    +
    + if (!contains_namespace(*list, ns)) {
    + ns_entry = NOFAIL(malloc(sizeof(struct namespace_list)));
    + strcpy(ns_entry->namespace, ns);
    + ns_entry->next = *list;
    + *list = ns_entry;
    + }
    +}
    +
    +static bool module_imports_namespace(struct module *module, const char *ns)
    +{
    + return contains_namespace(module->imported_namespaces, ns);
    +}
    +
    static const struct {
    const char *str;
    enum export export;
    @@ -313,21 +343,40 @@ static enum export export_from_sec(struct elf_info *elf, unsigned int sec)
    return export_unknown;
    }

    +static const char *sym_extract_ns(const char **symname)
    +{
    + size_t n;
    +
    + n = strcspn(*symname, ".");
    + if (n < strlen(*symname) - 1) {
    + char *dupsymname = NOFAIL(strdup(*symname));
    +
    + dupsymname[n] = '\0';
    + *symname = dupsymname;
    + return dupsymname + n + 1;
    + } else {
    + return NULL;
    + }
    +}
    +
    /**
    * Add an exported symbol - it may have already been added without a
    * CRC, in this case just update the CRC
    **/
    -static struct symbol *sym_add_exported(const char *name, struct module *mod,
    - enum export export)
    +static struct symbol *sym_add_exported(const char *name,
    + struct module *mod, enum export export)
    {
    - struct symbol *s = find_symbol(name);
    + const char *extract_name = name;
    + const char *ns = sym_extract_ns(&extract_name);
    + struct symbol *s = find_symbol(extract_name);

    if (!s) {
    - s = new_symbol(name, mod, export);
    + s = new_symbol(extract_name, mod, export);
    + s->ns = ns;
    } else {
    if (!s->preloaded) {
    warn("%s: '%s' exported twice. Previous export "
    - "was in %s%s\n", mod->name, name,
    + "was in %s%s\n", mod->name, extract_name,
    s->module->name,
    is_vmlinux(s->module->name) ?"":".ko");
    } else {
    @@ -697,6 +746,10 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
    }
    if (strcmp(symname, "init_module") == 0)
    mod->has_init = 1;
    + if (strstarts(symname, "__knsimport_")) {
    + const char *name = symname + strlen("__knsimport_");
    + add_namespace(&mod->imported_namespaces, name);
    + }
    if (strcmp(symname, "cleanup_module") == 0)
    mod->has_cleanup = 1;
    break;
    @@ -2097,6 +2150,13 @@ static void check_exports(struct module *mod)
    basename++;
    else
    basename = mod->name;
    +
    + if (exp->ns && !module_imports_namespace(mod, exp->ns)) {
    + warn("module %s uses symbol %s from namespace %s, "
    + "but does not import it.\n",
    + basename, exp->name, exp->ns);
    + }
    +
    if (!mod->gpl_compatible)
    check_for_gpl_usage(exp->export, basename, exp->name);
    check_for_unused(exp->export, basename, exp->name);
    diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
    index 8453d6ac2f77..9626bf3e7424 100644
    --- a/scripts/mod/modpost.h
    +++ b/scripts/mod/modpost.h
    @@ -109,6 +109,11 @@ buf_printf(struct buffer *buf, const char *fmt, ...);
    void
    buf_write(struct buffer *buf, const char *s, int len);

    +struct namespace_list {
    + struct namespace_list *next;
    + char namespace[0];
    +};
    +
    struct module {
    struct module *next;
    const char *name;
    @@ -121,6 +126,8 @@ struct module {
    struct buffer dev_table_buf;
    char srcversion[25];
    int is_dot_o;
    + // Actual imported namespaces
    + struct namespace_list *imported_namespaces;
    };

    struct elf_info {
    --
    2.18.0.203.gfac676dfb9-goog
    \
     
     \ /
      Last update: 2018-07-16 14:23    [W:4.078 / U:0.324 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site