Merge tag 'selinux-pr-20190917' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / kernel / module.c
index 9ee9342..32873bc 100644 (file)
@@ -544,12 +544,20 @@ static const char *kernel_symbol_name(const struct kernel_symbol *sym)
 #endif
 }
 
-static int cmp_name(const void *va, const void *vb)
+static const char *kernel_symbol_namespace(const struct kernel_symbol *sym)
 {
-       const char *a;
-       const struct kernel_symbol *b;
-       a = va; b = vb;
-       return strcmp(a, kernel_symbol_name(b));
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+       if (!sym->namespace_offset)
+               return NULL;
+       return offset_to_ptr(&sym->namespace_offset);
+#else
+       return sym->namespace;
+#endif
+}
+
+static int cmp_name(const void *name, const void *sym)
+{
+       return strcmp(name, kernel_symbol_name(sym));
 }
 
 static bool find_exported_symbol_in_section(const struct symsearch *syms,
@@ -1379,6 +1387,41 @@ static inline int same_magic(const char *amagic, const char *bmagic,
 }
 #endif /* CONFIG_MODVERSIONS */
 
+static char *get_modinfo(const struct load_info *info, const char *tag);
+static char *get_next_modinfo(const struct load_info *info, const char *tag,
+                             char *prev);
+
+static int verify_namespace_is_imported(const struct load_info *info,
+                                       const struct kernel_symbol *sym,
+                                       struct module *mod)
+{
+       const char *namespace;
+       char *imported_namespace;
+
+       namespace = kernel_symbol_namespace(sym);
+       if (namespace) {
+               imported_namespace = get_modinfo(info, "import_ns");
+               while (imported_namespace) {
+                       if (strcmp(namespace, imported_namespace) == 0)
+                               return 0;
+                       imported_namespace = get_next_modinfo(
+                               info, "import_ns", imported_namespace);
+               }
+#ifdef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
+               pr_warn(
+#else
+               pr_err(
+#endif
+                       "%s: module uses symbol (%s) from namespace %s, but does not import it.\n",
+                       mod->name, kernel_symbol_name(sym), namespace);
+#ifndef CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
+               return -EINVAL;
+#endif
+       }
+       return 0;
+}
+
+
 /* Resolve a symbol for this module.  I.e. if we find one, record usage. */
 static const struct kernel_symbol *resolve_symbol(struct module *mod,
                                                  const struct load_info *info,
@@ -1407,6 +1450,12 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
                goto getname;
        }
 
+       err = verify_namespace_is_imported(info, sym, mod);
+       if (err) {
+               sym = ERR_PTR(err);
+               goto getname;
+       }
+
        err = ref_module(mod, owner);
        if (err) {
                sym = ERR_PTR(err);
@@ -2481,7 +2530,8 @@ static char *next_string(char *string, unsigned long *secsize)
        return string;
 }
 
-static char *get_modinfo(struct load_info *info, const char *tag)
+static char *get_next_modinfo(const struct load_info *info, const char *tag,
+                             char *prev)
 {
        char *p;
        unsigned int taglen = strlen(tag);
@@ -2492,13 +2542,25 @@ static char *get_modinfo(struct load_info *info, const char *tag)
         * get_modinfo() calls made before rewrite_section_headers()
         * must use sh_offset, as sh_addr isn't set!
         */
-       for (p = (char *)info->hdr + infosec->sh_offset; p; p = next_string(p, &size)) {
+       char *modinfo = (char *)info->hdr + infosec->sh_offset;
+
+       if (prev) {
+               size -= prev - modinfo;
+               modinfo = next_string(prev, &size);
+       }
+
+       for (p = modinfo; p; p = next_string(p, &size)) {
                if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=')
                        return p + taglen + 1;
        }
        return NULL;
 }
 
+static char *get_modinfo(const struct load_info *info, const char *tag)
+{
+       return get_next_modinfo(info, tag, NULL);
+}
+
 static void setup_modinfo(struct module *mod, struct load_info *info)
 {
        struct module_attribute *attr;