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);