All of lore.kernel.org
 help / color / mirror / Atom feed
From: Luis Chamberlain <mcgrof@kernel.org>
To: linux-modules@vger.kernel.org, linux-kernel@vger.kernel.org,
	pmladek@suse.com, david@redhat.com, petr.pavlu@suse.com,
	prarit@redhat.com
Cc: christophe.leroy@csgroup.eu, song@kernel.org, mcgrof@kernel.org,
	torvalds@linux-foundation.org
Subject: [RFC 05/12] module: add debugging alias parsing support
Date: Fri, 10 Mar 2023 21:17:05 -0800	[thread overview]
Message-ID: <20230311051712.4095040-6-mcgrof@kernel.org> (raw)
In-Reply-To: <20230311051712.4095040-1-mcgrof@kernel.org>

We don't have in-kernel alias parsing support as aliases are all
dealt with in userspace. There has simply been no need to have
support for processing them in kernel. We have done this under
the assumption that userspace just Does The Right Thing (TM) about
aliases and loading modules and that there is no real gain of
processing aliases in-kernel.

Obviously userspace can be buggy though, and it can lie to us. We
currently have no easy way to determine this. Parsing aliases is
an example debugging facility we can use to help with these sorts
of problems.

But there are some possible optimizations that may also be possible
and enabling support let's folks experiment with these posibilities.

We disable this by default but folks can also enable this to
experiment with features which may use aliases in-kernel. Folks
should not enable this on production kernels. It'll bloat your
loaded kernel modules a tiny bit by the size of the aliases that
exist for them once loaded.

You can debug aliase by adding to your dynamic debug:

GRUB_CMDLINE_LINUX_DEFAULT="dyndbg=\"func module_process_aliases +p;\" "

Upon boot for example here a few entries:

module ext4 num_aliases: 5
alias[0] = fs-ext4
alias[1] = ext3
alias[2] = fs-ext3
alias[3] = ext2
alias[4] = fs-ext2

module xfs num_aliases: 1
alias[0] = fs-xfs

module floppy num_aliases: 3
alias[0] = block-major-2-*
alias[1] = acpi*:PNP0700:*
alias[2] = pnp:dPNP0700*

module ata_piix num_aliases: 89
alias[0] = pci:v00008086d00008C81sv*sd*bc*sc*i*
alias[1] = pci:v00008086d00008C80sv*sd*bc*sc*i*
alias[2] = pci:v00008086d00008C89sv*sd*bc*sc*i*
alias[3] = pci:v00008086d00008C88sv*sd*bc*sc*i*
... etc ...

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
---
 include/linux/module.h   |  4 ++
 kernel/module/Kconfig    | 19 +++++++++
 kernel/module/Makefile   |  1 +
 kernel/module/aliases.c  | 92 ++++++++++++++++++++++++++++++++++++++++
 kernel/module/internal.h | 15 +++++++
 kernel/module/main.c     | 17 ++++++--
 6 files changed, 145 insertions(+), 3 deletions(-)
 create mode 100644 kernel/module/aliases.c

diff --git a/include/linux/module.h b/include/linux/module.h
index c3b357196470..aed1b43edb55 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -420,6 +420,10 @@ struct module {
 	const char *srcversion;
 	struct kobject *holders_dir;
 
+#ifdef CONFIG_MODULE_KERNEL_ALIAS
+	unsigned int num_aliases;
+	const char **aliases;
+#endif
 	/* Exported symbols */
 	const struct kernel_symbol *syms;
 	const s32 *crcs;
diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
index 424b3bc58f3f..e4ba335fa279 100644
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig
@@ -22,6 +22,25 @@ menuconfig MODULES
 
 if MODULES
 
+config MODULE_DEBUG
+	bool "Enable debugging information for modules"
+	default n
+	help
+	  Enables debugging of the module infrastructure. Say no unless you
+	  are debugging the module framework. Don't enable this on production.
+	  This is only for experimentation and debugging.
+
+config MODULE_KERNEL_ALIAS
+	bool "Enable in-kernel alias processing for modules"
+	default n
+	depends on MODULE_DEBUG
+	help
+	  The kernel has historically not processed aliases in-kernel since
+	  we expect userspace can do all the proper work for us. Enable this
+	  if you want to experiment processing aliases in-kernel. This will
+	  bloat your kernel modules's memory by the number of aliases each
+	  module has once loaded into the kernel.
+
 config MODULE_FORCE_LOAD
 	bool "Forced module loading"
 	default n
diff --git a/kernel/module/Makefile b/kernel/module/Makefile
index 948efea81e85..34f0db0a016b 100644
--- a/kernel/module/Makefile
+++ b/kernel/module/Makefile
@@ -19,3 +19,4 @@ obj-$(CONFIG_SYSFS) += sysfs.o
 obj-$(CONFIG_KGDB_KDB) += kdb.o
 obj-$(CONFIG_MODVERSIONS) += version.o
 obj-$(CONFIG_MODULE_UNLOAD_TAINT_TRACKING) += tracking.o
+obj-$(CONFIG_MODULE_KERNEL_ALIAS) += aliases.o
diff --git a/kernel/module/aliases.c b/kernel/module/aliases.c
new file mode 100644
index 000000000000..2f30c9d4c765
--- /dev/null
+++ b/kernel/module/aliases.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Optional module in-kernel alias processing support.
+ *
+ * Copyright (C) 2023 Luis Chamberlain <mcgrof@kernel.org>
+ */
+
+#include <linux/module.h>
+#include "internal.h"
+
+void free_mod_aliases(struct module *mod)
+{
+	unsigned int i;
+
+	if (!mod->num_aliases)
+		return;
+
+	for (i=0; i < mod->num_aliases; i++) {
+		kfree(mod->aliases[i]);
+		mod->aliases[i] = NULL;
+	}
+
+	kfree(mod->aliases);
+	mod->aliases = NULL;
+}
+
+static int get_modinfo_tags(struct load_info *info,
+			    const char *tag,
+			    unsigned int *num_entries)
+{
+	char *p;
+	unsigned int taglen = strlen(tag);
+	Elf_Shdr *infosec = &info->sechdrs[info->index.info];
+	unsigned long size = infosec->sh_size;
+	const char *value;
+	unsigned int len, tags_size = 0;
+
+	for (p = (char *)infosec->sh_addr; p; p = module_next_tag_pair(p, &size)) {
+		if (strncmp(p, tag, taglen) == 0 && p[taglen] == '=') {
+			value = p + taglen + 1;
+			len = strlen(value);
+			if (len >=0 && len <= PAGE_SIZE) {
+				(*num_entries)++;
+				tags_size+=len;
+			}
+		}
+	}
+
+	return tags_size;
+}
+
+int module_process_aliases(struct module *mod, struct load_info *info)
+{
+	unsigned int size, i = 0, num_entries = 0;
+	char *alias;
+
+	size = get_modinfo_tags(info, "alias", &num_entries);
+	if (WARN_ON(!size))
+		return 0;
+
+	mod->aliases = kzalloc(num_entries * sizeof(char *), GFP_KERNEL);
+	if (!mod->aliases)
+		return -ENOMEM;
+
+	pr_debug("module %s num_aliases: %u\n", mod->name, num_entries);
+
+	for_each_modinfo_entry(alias, info, "alias") {
+		pr_debug("alias[%u] = %s\n", i, alias);
+		mod->aliases[i] = kasprintf(GFP_KERNEL, "%s", alias);
+		if (!mod->aliases[i])
+			goto err_free;
+		i++;
+	}
+
+	WARN_ON(i != num_entries);
+
+	mod->num_aliases = num_entries;
+
+	return 0;
+
+err_free:
+	while (i!=0) {
+		i--;
+		kfree(mod->aliases[i]);
+		mod->aliases[i] = NULL;
+	}
+
+	kfree(mod->aliases);
+	mod->aliases = NULL;
+
+	return -ENOMEM;
+}
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 6ae29bb8836f..40bb80ed21e2 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -96,6 +96,8 @@ long module_get_offset_and_type(struct module *mod, enum mod_mem_type type,
 char *module_flags(struct module *mod, char *buf, bool show_state);
 size_t module_flags_taint(unsigned long taints, char *buf);
 
+char *get_modinfo(const struct load_info *info, const char *tag);
+char *get_next_modinfo(const struct load_info *info, const char *tag, char *prev);
 char *module_next_tag_pair(char *string, unsigned long *secsize);
 
 #define for_each_modinfo_entry(entry, info, name) \
@@ -300,3 +302,16 @@ static inline int same_magic(const char *amagic, const char *bmagic, bool has_cr
 	return strcmp(amagic, bmagic) == 0;
 }
 #endif /* CONFIG_MODVERSIONS */
+
+#ifdef CONFIG_MODULE_KERNEL_ALIAS
+void free_mod_aliases(struct module *mod);
+int module_process_aliases(struct module *mod, struct load_info *info);
+#else
+static void free_mod_aliases(struct module *mod)
+{
+}
+static int module_process_aliases(struct module *mod, struct load_info *info)
+{
+	return 0;
+}
+#endif /* CONFIG_MODULE_KERNEL_ALIAS */
diff --git a/kernel/module/main.c b/kernel/module/main.c
index 3f7c8634cf06..16770942f33a 100644
--- a/kernel/module/main.c
+++ b/kernel/module/main.c
@@ -2,6 +2,7 @@
 /*
  * Copyright (C) 2002 Richard Henderson
  * Copyright (C) 2001 Rusty Russell, 2002, 2010 Rusty Russell IBM.
+ * Copyright (C) 2023 Luis Chamberlain <mcgrof@kernel.org>
  */
 
 #define INCLUDE_VERMAGIC
@@ -1035,8 +1036,7 @@ char *module_next_tag_pair(char *string, unsigned long *secsize)
 	return string;
 }
 
-static char *get_next_modinfo(const struct load_info *info, const char *tag,
-			      char *prev)
+char *get_next_modinfo(const struct load_info *info, const char *tag, char *prev)
 {
 	char *p;
 	unsigned int taglen = strlen(tag);
@@ -1061,7 +1061,7 @@ static char *get_next_modinfo(const struct load_info *info, const char *tag,
 	return NULL;
 }
 
-static char *get_modinfo(const struct load_info *info, const char *tag)
+char *get_modinfo(const struct load_info *info, const char *tag)
 {
 	return get_next_modinfo(info, tag, NULL);
 }
@@ -1289,6 +1289,7 @@ static void free_module(struct module *mod)
 	module_arch_freeing_init(mod);
 	kfree(mod->args);
 	percpu_modfree(mod);
+	free_mod_aliases(mod);
 
 	free_mod_mem(mod);
 }
@@ -1989,6 +1990,12 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
 			"is unknown, you have been warned.\n", mod->name);
 	}
 
+	if (get_modinfo(info, "alias")) {
+		err = module_process_aliases(mod, info);
+		if (err)
+			goto err_out_skip_alloc;
+	}
+
 	err = check_modinfo_livepatch(mod, info);
 	if (err)
 		goto err_out;
@@ -2005,6 +2012,8 @@ static int check_modinfo(struct module *mod, struct load_info *info, int flags)
 
 	return 0;
 err_out:
+	free_mod_aliases(mod);
+err_out_skip_alloc:
 	return err;
 }
 
@@ -2329,6 +2338,7 @@ static struct module *layout_and_allocate(struct load_info *info, int flags)
 	kmemleak_load_module(mod, info);
 	return mod;
 err_out:
+	free_mod_aliases(mod);
 	return ERR_PTR(err);
 }
 
@@ -2890,6 +2900,7 @@ static int load_module(struct load_info *info, const char __user *uargs,
 	synchronize_rcu();
 	mutex_unlock(&module_mutex);
  free_module:
+	free_mod_aliases(mod);
 	/* Free lock-classes; relies on the preceding sync_rcu() */
 	for_class_mod_mem_type(type, core_data) {
 		lockdep_free_key_range(mod->mem[type].base,
-- 
2.39.1


  parent reply	other threads:[~2023-03-11  5:17 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-11  5:17 [RFC 00/12] module: avoid userspace pressure on unwanted allocations Luis Chamberlain
2023-03-11  5:17 ` [RFC 01/12] module: use goto errors on check_modinfo() and layout_and_allocate() Luis Chamberlain
2023-03-11  5:17 ` [RFC 02/12] module: move get_modinfo() helpers all above Luis Chamberlain
2023-03-11  5:17 ` [RFC 03/12] module: rename next_string() to module_next_tag_pair() Luis Chamberlain
2023-03-11  5:17 ` [RFC 04/12] module: add a for_each_modinfo_entry() Luis Chamberlain
2023-03-11  5:17 ` Luis Chamberlain [this message]
2023-03-11  5:17 ` [RFC 06/12] module: move early sanity checks into a helper Luis Chamberlain
2023-03-11  5:17 ` [RFC 07/12] module: move check_modinfo() early to early_mod_check() Luis Chamberlain
2023-03-11  5:17 ` [RFC 08/12] module: move finished_loading() Luis Chamberlain
2023-03-11  5:17 ` [RFC 09/12] module: extract patient module check into helper Luis Chamberlain
2023-03-11  5:17 ` [RFC 10/12] module: avoid allocation if module is already present and ready Luis Chamberlain
2023-03-11  5:17 ` [RFC 11/12] module: use list_add_tail_rcu() when adding module Luis Chamberlain
2023-03-11  5:17 ` [RFC 12/12] module: use aliases to find module on find_module_all() Luis Chamberlain
2023-03-11 13:12   ` kernel test robot
2023-03-11 17:06   ` kernel test robot
2023-03-15 14:43   ` Petr Pavlu
2023-03-15 16:12     ` Luis Chamberlain
2023-03-15 12:24 ` [RFC 00/12] module: avoid userspace pressure on unwanted allocations David Hildenbrand
2023-03-15 16:10   ` Luis Chamberlain
2023-03-15 16:41     ` David Hildenbrand
2023-03-16 23:55       ` Luis Chamberlain
2023-03-16 23:56         ` Luis Chamberlain
2023-03-18  0:11           ` Luis Chamberlain
2023-03-20  9:38             ` David Hildenbrand
2023-03-20 19:40               ` David Hildenbrand
2023-03-20 21:09                 ` Luis Chamberlain
2023-03-20 21:15                   ` David Hildenbrand
2023-03-20 21:23                     ` Luis Chamberlain
2023-03-20 21:27                       ` Luis Chamberlain
2023-03-21 19:32                         ` David Hildenbrand
2023-03-24  9:27                           ` David Hildenbrand
2023-03-24 17:54                             ` Luis Chamberlain
2023-03-24 19:11                               ` Linus Torvalds
2023-03-24 19:59                                 ` Luis Chamberlain
2023-03-24 20:28                                   ` Linus Torvalds
2023-03-24 21:14                                     ` Luis Chamberlain
2023-03-24 23:27                                       ` Luis Chamberlain
2023-03-24 23:41                                         ` Linus Torvalds
2023-03-28  3:44                               ` David Hildenbrand
2023-03-28  6:16                                 ` Luis Chamberlain
2023-03-28 21:02                                   ` David Hildenbrand
2023-03-29  5:31                                     ` Luis Chamberlain
2023-03-30  4:42                                       ` David Hildenbrand
2023-03-21 15:11                       ` David Hildenbrand
2023-03-21 16:52                         ` Luis Chamberlain
2023-03-21 17:01                           ` David Hildenbrand
2023-03-20  9:37           ` David Hildenbrand

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230311051712.4095040-6-mcgrof@kernel.org \
    --to=mcgrof@kernel.org \
    --cc=christophe.leroy@csgroup.eu \
    --cc=david@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=petr.pavlu@suse.com \
    --cc=pmladek@suse.com \
    --cc=prarit@redhat.com \
    --cc=song@kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.