]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blobdiff - kernel/module.c
static_call: Add inline static call infrastructure
[mirror_ubuntu-jammy-kernel.git] / kernel / module.c
index 8fa2600bde6a39a62ba08c08cecbf2b054409635..c075a18103fbf66646baccabfe351c5e13b9573c 100644 (file)
@@ -422,7 +422,7 @@ static bool each_symbol_in_section(const struct symsearch *arr,
 }
 
 /* Returns true as soon as fn returns true, otherwise false. */
-bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
+static bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
                                    struct module *owner,
                                    void *data),
                         void *data)
@@ -484,7 +484,6 @@ bool each_symbol_section(bool (*fn)(const struct symsearch *arr,
        }
        return false;
 }
-EXPORT_SYMBOL_GPL(each_symbol_section);
 
 struct find_symbol_arg {
        /* Input */
@@ -496,6 +495,7 @@ struct find_symbol_arg {
        struct module *owner;
        const s32 *crc;
        const struct kernel_symbol *sym;
+       enum mod_license license;
 };
 
 static bool check_exported_symbol(const struct symsearch *syms,
@@ -505,9 +505,9 @@ static bool check_exported_symbol(const struct symsearch *syms,
        struct find_symbol_arg *fsa = data;
 
        if (!fsa->gplok) {
-               if (syms->licence == GPL_ONLY)
+               if (syms->license == GPL_ONLY)
                        return false;
-               if (syms->licence == WILL_BE_GPL_ONLY && fsa->warn) {
+               if (syms->license == WILL_BE_GPL_ONLY && fsa->warn) {
                        pr_warn("Symbol %s is being used by a non-GPL module, "
                                "which will not be allowed in the future\n",
                                fsa->name);
@@ -529,6 +529,7 @@ static bool check_exported_symbol(const struct symsearch *syms,
        fsa->owner = owner;
        fsa->crc = symversion(syms->crcs, symnum);
        fsa->sym = &syms->start[symnum];
+       fsa->license = syms->license;
        return true;
 }
 
@@ -585,9 +586,10 @@ static bool find_exported_symbol_in_section(const struct symsearch *syms,
 
 /* Find an exported symbol and return it, along with, (optional) crc and
  * (optional) module which owns it.  Needs preempt disabled or module_mutex. */
-const struct kernel_symbol *find_symbol(const char *name,
+static const struct kernel_symbol *find_symbol(const char *name,
                                        struct module **owner,
                                        const s32 **crc,
+                                       enum mod_license *license,
                                        bool gplok,
                                        bool warn)
 {
@@ -602,13 +604,14 @@ const struct kernel_symbol *find_symbol(const char *name,
                        *owner = fsa.owner;
                if (crc)
                        *crc = fsa.crc;
+               if (license)
+                       *license = fsa.license;
                return fsa.sym;
        }
 
        pr_debug("Failed to find symbol %s\n", name);
        return NULL;
 }
-EXPORT_SYMBOL_GPL(find_symbol);
 
 /*
  * Search for module by name: must hold module_mutex (or preempt disabled
@@ -869,7 +872,7 @@ static int add_module_usage(struct module *a, struct module *b)
 }
 
 /* Module a uses b: caller needs module_mutex() */
-int ref_module(struct module *a, struct module *b)
+static int ref_module(struct module *a, struct module *b)
 {
        int err;
 
@@ -888,7 +891,6 @@ int ref_module(struct module *a, struct module *b)
        }
        return 0;
 }
-EXPORT_SYMBOL_GPL(ref_module);
 
 /* Clear the unload stuff of the module. */
 static void module_unload_free(struct module *mod)
@@ -1077,7 +1079,7 @@ void __symbol_put(const char *symbol)
        struct module *owner;
 
        preempt_disable();
-       if (!find_symbol(symbol, &owner, NULL, true, false))
+       if (!find_symbol(symbol, &owner, NULL, NULL, true, false))
                BUG();
        module_put(owner);
        preempt_enable();
@@ -1169,11 +1171,10 @@ static inline void module_unload_free(struct module *mod)
 {
 }
 
-int ref_module(struct module *a, struct module *b)
+static int ref_module(struct module *a, struct module *b)
 {
        return strong_try_module_get(b);
 }
-EXPORT_SYMBOL_GPL(ref_module);
 
 static inline int module_unload_init(struct module *mod)
 {
@@ -1356,7 +1357,7 @@ static inline int check_modstruct_version(const struct load_info *info,
         * locking is necessary -- use preempt_disable() to placate lockdep.
         */
        preempt_disable();
-       if (!find_symbol("module_layout", NULL, &crc, true, false)) {
+       if (!find_symbol("module_layout", NULL, &crc, NULL, true, false)) {
                preempt_enable();
                BUG();
        }
@@ -1430,6 +1431,24 @@ static int verify_namespace_is_imported(const struct load_info *info,
        return 0;
 }
 
+static bool inherit_taint(struct module *mod, struct module *owner)
+{
+       if (!owner || !test_bit(TAINT_PROPRIETARY_MODULE, &owner->taints))
+               return true;
+
+       if (mod->using_gplonly_symbols) {
+               pr_err("%s: module using GPL-only symbols uses symbols from proprietary module %s.\n",
+                       mod->name, owner->name);
+               return false;
+       }
+
+       if (!test_bit(TAINT_PROPRIETARY_MODULE, &mod->taints)) {
+               pr_warn("%s: module uses symbols from proprietary module %s, inheriting taint.\n",
+                       mod->name, owner->name);
+               set_bit(TAINT_PROPRIETARY_MODULE, &mod->taints);
+       }
+       return true;
+}
 
 /* Resolve a symbol for this module.  I.e. if we find one, record usage. */
 static const struct kernel_symbol *resolve_symbol(struct module *mod,
@@ -1440,6 +1459,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
        struct module *owner;
        const struct kernel_symbol *sym;
        const s32 *crc;
+       enum mod_license license;
        int err;
 
        /*
@@ -1449,11 +1469,19 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
         */
        sched_annotate_sleep();
        mutex_lock(&module_mutex);
-       sym = find_symbol(name, &owner, &crc,
+       sym = find_symbol(name, &owner, &crc, &license,
                          !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
        if (!sym)
                goto unlock;
 
+       if (license == GPL_ONLY)
+               mod->using_gplonly_symbols = true;
+
+       if (!inherit_taint(mod, owner)) {
+               sym = NULL;
+               goto getname;
+       }
+
        if (!check_version(info, name, mod, crc)) {
                sym = ERR_PTR(-EINVAL);
                goto getname;
@@ -2236,7 +2264,7 @@ void *__symbol_get(const char *symbol)
        const struct kernel_symbol *sym;
 
        preempt_disable();
-       sym = find_symbol(symbol, &owner, NULL, true, true);
+       sym = find_symbol(symbol, &owner, NULL, NULL, true, true);
        if (sym && strong_try_module_get(owner))
                sym = NULL;
        preempt_enable();
@@ -2272,7 +2300,7 @@ static int verify_exported_symbols(struct module *mod)
        for (i = 0; i < ARRAY_SIZE(arr); i++) {
                for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
                        if (find_symbol(kernel_symbol_name(s), &owner, NULL,
-                                       true, false)) {
+                                       NULL, true, false)) {
                                pr_err("%s: exports duplicate symbol %s"
                                       " (owned by %s)\n",
                                       mod->name, kernel_symbol_name(s),
@@ -3246,6 +3274,11 @@ static int find_module_sections(struct module *mod, struct load_info *info)
        mod->kprobe_blacklist = section_objs(info, "_kprobe_blacklist",
                                                sizeof(unsigned long),
                                                &mod->num_kprobe_blacklist);
+#endif
+#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
+       mod->static_call_sites = section_objs(info, ".static_call_sites",
+                                             sizeof(*mod->static_call_sites),
+                                             &mod->num_static_call_sites);
 #endif
        mod->extable = section_objs(info, "__ex_table",
                                    sizeof(*mod->extable), &mod->num_exentries);
@@ -3764,9 +3797,13 @@ static int prepare_coming_module(struct module *mod)
        if (err)
                return err;
 
-       blocking_notifier_call_chain(&module_notify_list,
-                                    MODULE_STATE_COMING, mod);
-       return 0;
+       err = blocking_notifier_call_chain_robust(&module_notify_list,
+                       MODULE_STATE_COMING, MODULE_STATE_GOING, mod);
+       err = notifier_to_errno(err);
+       if (err)
+               klp_module_going(mod);
+
+       return err;
 }
 
 static int unknown_module_param_cb(char *param, char *val, const char *modname,
@@ -4489,7 +4526,6 @@ struct module *__module_address(unsigned long addr)
        }
        return mod;
 }
-EXPORT_SYMBOL_GPL(__module_address);
 
 /*
  * is_module_text_address - is this address inside module code?
@@ -4528,7 +4564,6 @@ struct module *__module_text_address(unsigned long addr)
        }
        return mod;
 }
-EXPORT_SYMBOL_GPL(__module_text_address);
 
 /* Don't grab lock, we're oopsing. */
 void print_modules(void)