#ifdef CONFIG_MODULES
 
+#define NS_SEPARATOR "."
+
 #if defined(__KERNEL__) && !defined(__GENKSYMS__)
 #ifdef CONFIG_MODVERSIONS
 /* Mark the CRC weak since genksyms apparently decides not to
        asm("   .section \"___kcrctab" sec "+" #sym "\", \"a\"  \n"     \
            "   .weak   __crc_" #sym "                          \n"     \
            "   .long   __crc_" #sym " - .                      \n"     \
-           "   .previous                                       \n");
+           "   .previous                                       \n")
 #else
 #define __CRC_SYMBOL(sym, sec)                                         \
        asm("   .section \"___kcrctab" sec "+" #sym "\", \"a\"  \n"     \
            "   .weak   __crc_" #sym "                          \n"     \
            "   .long   __crc_" #sym "                          \n"     \
-           "   .previous                                       \n");
+           "   .previous                                       \n")
 #endif
 #else
 #define __CRC_SYMBOL(sym, sec)
  * absolute relocations that require runtime processing on relocatable
  * kernels.
  */
+#define __KSYMTAB_ENTRY_NS(sym, sec, ns)                               \
+       __ADDRESSABLE(sym)                                              \
+       asm("   .section \"___ksymtab" sec "+" #sym "\", \"a\"  \n"     \
+           "   .balign 4                                       \n"     \
+           "__ksymtab_" #sym NS_SEPARATOR #ns ":               \n"     \
+           "   .long   " #sym "- .                             \n"     \
+           "   .long   __kstrtab_" #sym "- .                   \n"     \
+           "   .long   __kstrtab_ns_" #sym "- .                \n"     \
+           "   .previous                                       \n")
+
 #define __KSYMTAB_ENTRY(sym, sec)                                      \
        __ADDRESSABLE(sym)                                              \
        asm("   .section \"___ksymtab" sec "+" #sym "\", \"a\"  \n"     \
            "__ksymtab_" #sym ":                                \n"     \
            "   .long   " #sym "- .                             \n"     \
            "   .long   __kstrtab_" #sym "- .                   \n"     \
+           "   .long   0 - .                                   \n"     \
            "   .previous                                       \n")
 
 struct kernel_symbol {
        int value_offset;
        int name_offset;
+       int namespace_offset;
 };
 #else
+#define __KSYMTAB_ENTRY_NS(sym, sec, ns)                               \
+       static const struct kernel_symbol __ksymtab_##sym##__##ns       \
+       asm("__ksymtab_" #sym NS_SEPARATOR #ns)                         \
+       __attribute__((section("___ksymtab" sec "+" #sym), used))       \
+       __aligned(sizeof(void *))                                       \
+       = { (unsigned long)&sym, __kstrtab_##sym, __kstrtab_ns_##sym }
+
 #define __KSYMTAB_ENTRY(sym, sec)                                      \
        static const struct kernel_symbol __ksymtab_##sym               \
+       asm("__ksymtab_" #sym)                                          \
        __attribute__((section("___ksymtab" sec "+" #sym), used))       \
        __aligned(sizeof(void *))                                       \
-       = { (unsigned long)&sym, __kstrtab_##sym }
+       = { (unsigned long)&sym, __kstrtab_##sym, NULL }
 
 struct kernel_symbol {
        unsigned long value;
        const char *name;
+       const char *namespace;
 };
 #endif
 
-/* For every exported symbol, place a struct in the __ksymtab section */
-#define ___EXPORT_SYMBOL(sym, sec)                                     \
+#define ___export_symbol_common(sym, sec)                              \
        extern typeof(sym) sym;                                         \
-       __CRC_SYMBOL(sym, sec)                                          \
+       __CRC_SYMBOL(sym, sec);                                         \
        static const char __kstrtab_##sym[]                             \
        __attribute__((section("__ksymtab_strings"), used, aligned(1))) \
-       = #sym;                                                         \
+       = #sym                                                          \
+
+/* For every exported symbol, place a struct in the __ksymtab section */
+#define ___EXPORT_SYMBOL_NS(sym, sec, ns)                              \
+       ___export_symbol_common(sym, sec);                              \
+       static const char __kstrtab_ns_##sym[]                          \
+       __attribute__((section("__ksymtab_strings"), used, aligned(1))) \
+       = #ns;                                                          \
+       __KSYMTAB_ENTRY_NS(sym, sec, ns)
+
+#define ___EXPORT_SYMBOL(sym, sec)                                     \
+       ___export_symbol_common(sym, sec);                              \
        __KSYMTAB_ENTRY(sym, sec)
 
 #if defined(__DISABLE_EXPORTS)
  * be reused in other execution contexts such as the UEFI stub or the
  * decompressor.
  */
+#define __EXPORT_SYMBOL_NS(sym, sec, ns)
 #define __EXPORT_SYMBOL(sym, sec)
 
 #elif defined(CONFIG_TRIM_UNUSED_KSYMS)
 #define __cond_export_sym_1(sym, sec) ___EXPORT_SYMBOL(sym, sec)
 #define __cond_export_sym_0(sym, sec) /* nothing */
 
+#define __EXPORT_SYMBOL_NS(sym, sec, ns)                               \
+       __ksym_marker(sym);                                             \
+       __cond_export_ns_sym(sym, sec, ns, __is_defined(__KSYM_##sym))
+#define __cond_export_ns_sym(sym, sec, ns, conf)                       \
+       ___cond_export_ns_sym(sym, sec, ns, conf)
+#define ___cond_export_ns_sym(sym, sec, ns, enabled)                   \
+       __cond_export_ns_sym_##enabled(sym, sec, ns)
+#define __cond_export_ns_sym_1(sym, sec, ns) ___EXPORT_SYMBOL_NS(sym, sec, ns)
+#define __cond_export_ns_sym_0(sym, sec, ns) /* nothing */
+
 #else
+#define __EXPORT_SYMBOL_NS ___EXPORT_SYMBOL_NS
 #define __EXPORT_SYMBOL ___EXPORT_SYMBOL
 #endif
 
-#define EXPORT_SYMBOL(sym)                                     \
-       __EXPORT_SYMBOL(sym, "")
-
-#define EXPORT_SYMBOL_GPL(sym)                                 \
-       __EXPORT_SYMBOL(sym, "_gpl")
-
-#define EXPORT_SYMBOL_GPL_FUTURE(sym)                          \
-       __EXPORT_SYMBOL(sym, "_gpl_future")
+#define EXPORT_SYMBOL(sym) __EXPORT_SYMBOL(sym, "")
+#define EXPORT_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_gpl")
+#define EXPORT_SYMBOL_GPL_FUTURE(sym) __EXPORT_SYMBOL(sym, "_gpl_future")
+#define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL_NS(sym, "", ns)
+#define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL_NS(sym, "_gpl", ns)
 
 #ifdef CONFIG_UNUSED_SYMBOLS
 #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused")
 #define EXPORT_UNUSED_SYMBOL_GPL(sym)
 #endif
 
-#endif /* __GENKSYMS__ */
+#endif /* __KERNEL__ && !__GENKSYMS__ */
+
+#if defined(__GENKSYMS__)
+/*
+ * When we're running genksyms, ignore the namespace and make the _NS
+ * variants look like the normal ones. There are two reasons for this:
+ * 1) In the normal definition of EXPORT_SYMBOL_NS, the 'ns' macro
+ *    argument is itself not expanded because it's always tokenized or
+ *    concatenated; but when running genksyms, a blank definition of the
+ *    macro does allow the argument to be expanded; if a namespace
+ *    happens to collide with a #define, this can cause issues.
+ * 2) There's no need to modify genksyms to deal with the _NS variants
+ */
+#define EXPORT_SYMBOL_NS(sym, ns) EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_NS_GPL(sym, ns) EXPORT_SYMBOL_GPL(sym)
+#endif
 
 #else /* !CONFIG_MODULES... */
 
 #define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_NS(sym, ns)
+#define EXPORT_SYMBOL_NS_GPL(sym, ns)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_GPL_FUTURE(sym)
 #define EXPORT_UNUSED_SYMBOL(sym)
 
 #endif
 }
 
+static const char *kernel_symbol_namespace(const struct kernel_symbol *sym)
+{
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+       return offset_to_ptr(&sym->namespace_offset);
+#else
+       return sym->namespace;
+#endif
+}
+
 static int cmp_name(const void *va, const void *vb)
 {
        const char *a;
 }
 #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);
+               }
+               pr_err("%s: module uses symbol (%s) from namespace %s, but does not import it.\n",
+                      mod->name, kernel_symbol_name(sym), namespace);
+               return -EINVAL;
+       }
+       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,
                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);