Blob Blame History Raw
From: Jeff Mahoney <jeffm@suse.com>
Subject: kabi: create module private struct to hold btf size/data
Patch-mainline: Never, kabi only
References: jsc#SLE-24559

Upstream commit 5f9ae91f7c0d (kbuild: Build kernel module BTFs if BTF
is enabled and pahole supports it) added fields to the middle of struct
module, which would change the kABI.  This patch adds a new opaque struct
to hold new module fields and keep them out of the kABI definition.

Signed-off-by: Jeff Mahoney <jeffm@suse.com>
---
 include/linux/module.h |   17 +++++++++++++----
 kernel/bpf/btf.c       |    5 +++--
 kernel/module.c        |   47 +++++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 59 insertions(+), 10 deletions(-)

--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -458,10 +458,6 @@ struct module {
 	unsigned int num_bpf_raw_events;
 	struct bpf_raw_event_map *bpf_raw_events;
 #endif
-#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
-	unsigned int btf_data_size;
-	void *btf_data;
-#endif
 #ifdef CONFIG_JUMP_LABEL
 	struct jump_entry *jump_entries;
 	unsigned int num_jump_entries;
@@ -511,12 +507,25 @@ struct module {
 	struct error_injection_entry *ei_funcs;
 	unsigned int num_ei_funcs;
 #endif
+#ifdef __GENKSYMS__
 	void *suse_kabi_padding;
+#else
+	/* Opaque to anything outside of the module code */
+	struct module_kabi_data *kabi_data;
+#endif
 } ____cacheline_aligned __randomize_layout;
 #ifndef MODULE_ARCH_INIT
 #define MODULE_ARCH_INIT {}
 #endif
 
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+struct module_btf_info {
+	unsigned int btf_data_size;
+	void *btf_data;
+};
+struct module_btf_info *get_module_btf_info(struct module *mod);
+#endif
+
 #ifndef HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
 static inline unsigned long kallsyms_symbol_value(const Elf_Sym *sym)
 {
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -4759,10 +4759,11 @@ static int btf_module_notify(struct noti
 {
 	struct btf_module *btf_mod, *tmp;
 	struct module *mod = module;
+	struct module_btf_info *mbtfi = get_module_btf_info(mod);
 	struct btf *btf;
 	int err = 0;
 
-	if (mod->btf_data_size == 0 ||
+	if (mbtfi->btf_data_size == 0 ||
 	    (op != MODULE_STATE_COMING && op != MODULE_STATE_GOING))
 		goto out;
 
@@ -4773,7 +4774,7 @@ static int btf_module_notify(struct noti
 			err = -ENOMEM;
 			goto out;
 		}
-		btf = btf_parse_module(mod->name, mod->btf_data, mod->btf_data_size);
+		btf = btf_parse_module(mod->name, mbtfi->btf_data, mbtfi->btf_data_size);
 		if (IS_ERR(btf)) {
 			pr_warn("failed to validate module [%s] BTF: %ld\n",
 				mod->name, PTR_ERR(btf));
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -108,6 +108,36 @@ static void do_free_init(struct work_str
 static DECLARE_WORK(init_free_wq, do_free_init);
 static LLIST_HEAD(init_free_list);
 
+struct module_kabi_data {
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+	struct module_btf_info btf_info;
+#endif
+};
+
+#ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+struct module_btf_info *get_module_btf_info(struct module *mod)
+{
+	return &mod->kabi_data->btf_info;
+}
+#endif
+
+static int alloc_module_kabi(struct module *mod)
+{
+	if (sizeof(*mod->kabi_data)) {
+		mod->kabi_data = kzalloc(sizeof(*mod->kabi_data), GFP_KERNEL);
+		if (!mod->kabi_data)
+			return -ENOMEM;
+
+	}
+	return 0;
+}
+
+static void free_module_kabi(struct module *mod)
+{
+	kfree(mod->kabi_data);
+	mod->kabi_data = NULL;
+}
+
 #ifdef CONFIG_MODULES_TREE_LOOKUP
 
 /*
@@ -2355,6 +2385,8 @@ static void free_module(struct module *m
 	kfree(mod->args);
 	percpu_modfree(mod);
 
+	free_module_kabi(mod);
+
 	/* Free lock-classes; relies on the preceding sync_rcu(). */
 	lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size);
 
@@ -3335,7 +3367,8 @@ static int find_module_sections(struct m
 					   &mod->num_bpf_raw_events);
 #endif
 #ifdef CONFIG_DEBUG_INFO_BTF_MODULES
-	mod->btf_data = any_section_objs(info, ".BTF", 1, &mod->btf_data_size);
+	mod->kabi_data->btf_info.btf_data = any_section_objs(info, ".BTF", 1,
+				   &mod->kabi_data->btf_info.btf_data_size);
 #endif
 #ifdef CONFIG_JUMP_LABEL
 	mod->jump_entries = section_objs(info, "__jump_table",
@@ -3745,7 +3778,7 @@ static noinline int do_init_module(struc
 	mod->init_layout.text_size = 0;
 #ifdef CONFIG_DEBUG_INFO_BTF_MODULES
 	/* .BTF is not SHF_ALLOC and will get removed, so sanitize pointer */
-	mod->btf_data = NULL;
+	mod->kabi_data->btf_info.btf_data = NULL;
 #endif
 	/*
 	 * We want to free module_init, but be aware that kallsyms may be
@@ -3939,10 +3972,14 @@ static int load_module(struct load_info
 
 	audit_log_kern_module(mod->name);
 
+	err = alloc_module_kabi(mod);
+	if (err)
+		goto free_module;
+
 	/* Reserve our place in the list. */
 	err = add_unformed_module(mod);
 	if (err)
-		goto free_module;
+		goto free_kabi;
 
 #ifdef CONFIG_MODULE_SIG
 	mod->sig_ok = info->sig_ok;
@@ -4080,6 +4117,8 @@ static int load_module(struct load_info
 	/* Wait for RCU-sched synchronizing before releasing mod->list. */
 	synchronize_rcu();
 	mutex_unlock(&module_mutex);
+ free_kabi:
+	free_module_kabi(mod);
  free_module:
 	/* Free lock-classes; relies on the preceding sync_rcu() */
 	lockdep_free_key_range(mod->core_layout.base, mod->core_layout.size);