2022-11-10 23:03:23

by Allen Webb

[permalink] [raw]
Subject: Patch to exposing modalias'es for built in kernel modules (USB)

My apologies for any process mistakes in submitting this as it is my
first ever attempt at a Linux kernel patch.

I have a somewhat rough patch that introduces a modalias sysfs
attribute to kernel modules (both builtin and loaded). The goal of
this patch is to expose the driver matching values from the modalias
to inform policy decisions in userspace for devices with the
authorized attribute in sysfs. In other words with this patch tools
like USBGuard could leverage not only modules.aliases, but also the
aliases for the builtin modules to match devices with drivers before
deciding to authorize a device or not. This is particularly useful in
cases when new devices shouldn't be allowed part of the time like for
lock screens.

One other approach I considered was generating a builtin.alias file at
build time which would be installed alongside modules.alias. I have a
patch for this I could post as an alternative or in addition if it is
preferred.

I don't really like that it has to walk all drivers for all buses each
time the modalias attribute is read, but it shouldn't be that often
and I didn't see a better way of doing it though I am not familiar
with the kernel data structures available.

There are some flaws with this design in that some modaliases are not
associated with a bus. However, the only modules that really benefit
from this are ones with drivers associated with buses that make use of
the authorized attribute (USB, PCI, maybe others).

I only implemented USB for the proof-of-concept, but if this looks
like a viable option I could go back and implement PCI and any other
buses that use the authorized attribute.

Additionally, I haven't refactored files2alias to not have duplicate
code, but I am not sure how feasible that is given we would need to
share code between build-time userspace and the kernel. I did keep the
code limited to a single file so that it could possibly be compiled in
both environments, but type sizing of structs will be tricky for
cross-compilation.

Here is the patch:
From fc8855454debb520a9d28031a825bc48852ccc1a Mon Sep 17 00:00:00 2001
From: Allen Webb <[email protected]>
Date: Thu, 20 Oct 2022 19:53:04 +0000
Subject: [PATCH] modules: add modalias file to sysfs for modules.

USB devices support the authorized attribute which can be used by
user-space to implement trust-based systems for enabling USB devices. It
would be helpful when building these systems to be able to know in
advance which kernel drivers (or modules) are reachable from a
particular USB device.

This information is readily available for external modules in
modules.alias. However, builtin kernel modules are not covered. This
patch adds a sys-fs attribute to both builtin and loaded modules
exposing the matching rules in the modalias format for integration
with tools like USBGuard.

BUG=chromium:1300574
TEST=cat /sys/modules/usb_storage/modalias

Change-Id: I83b6f0c30e06e65cbe223f1606187283fcb13215
Signed-off-by: Allen Webb <[email protected]>
---
drivers/base/Makefile | 2 +-
drivers/base/base.h | 8 ++
drivers/base/bus.c | 42 ++++++
drivers/base/mod_devicetable.c | 243 +++++++++++++++++++++++++++++++++
drivers/usb/core/driver.c | 2 +
include/linux/device/bus.h | 8 ++
include/linux/module.h | 1 +
kernel/module/internal.h | 2 +
kernel/module/sysfs.c | 100 ++++++++++++++
kernel/params.c | 2 +
10 files changed, 409 insertions(+), 1 deletion(-)
create mode 100644 drivers/base/mod_devicetable.c

diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 83217d243c25b..924d46ae987f4 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -15,7 +15,7 @@ obj-y += firmware_loader/
obj-$(CONFIG_NUMA) += node.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
ifeq ($(CONFIG_SYSFS),y)
-obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_MODULES) += mod_devicetable.o module.o
endif
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
obj-$(CONFIG_REGMAP) += regmap/
diff --git a/drivers/base/base.h b/drivers/base/base.h
index b3a43a164dcd1..7ac5f7a547be8 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -175,6 +175,14 @@ static inline void module_add_driver(struct module *mod,
static inline void module_remove_driver(struct device_driver *drv) { }
#endif

+#if defined(CONFIG_SYSFS)
+ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count);
+#else
+static inline ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count) { return -ENOSUP; }
+#endif
+
#ifdef CONFIG_DEVTMPFS
extern int devtmpfs_init(void);
#else
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7ca47e5b3c1f4..4e0c5925545e5 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -178,6 +178,48 @@ static const struct kset_uevent_ops bus_uevent_ops = {

static struct kset *bus_kset;

+/**
+ * bus_for_each - bus iterator.
+ * @start: bus to start iterating from.
+ * @data: data for the callback.
+ * @fn: function to be called for each device.
+ *
+ * Iterate over list of buses, and call @fn for each,
+ * passing it @data. If @start is not NULL, we use that bus to
+ * begin iterating from.
+ *
+ * We check the return of @fn each time. If it returns anything
+ * other than 0, we break out and return that value.
+ *
+ * NOTE: The bus that returns a non-zero value is not retained
+ * in any way, nor is its refcount incremented. If the caller needs
+ * to retain this data, it should do so, and increment the reference
+ * count in the supplied callback.
+ */
+int bus_for_each(void *data, int (*fn)(struct bus_type *, void *))
+{
+ int error = 0;
+ struct bus_type *bus;
+ struct subsys_private *bus_prv;
+ struct kset *subsys;
+ struct kobject *k;
+
+ spin_lock(&bus_kset->list_lock);
+
+ list_for_each_entry(k, &bus_kset->list, entry) {
+ subsys = container_of(k, struct kset, kobj);
+ bus_prv = container_of(subsys, struct subsys_private, subsys);
+ bus = bus_prv->bus;
+ error = fn(bus, data);
+ if (error)
+ break;
+ }
+
+ spin_unlock(&bus_kset->list_lock);
+ return error;
+}
+EXPORT_SYMBOL_GPL(bus_for_each);
+
/* Manually detach a device from its associated driver. */
static ssize_t unbind_store(struct device_driver *drv, const char *buf,
size_t count)
diff --git a/drivers/base/mod_devicetable.c b/drivers/base/mod_devicetable.c
new file mode 100644
index 0000000000000..0d98b3bf0d8d3
--- /dev/null
+++ b/drivers/base/mod_devicetable.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mod_devicetable.c - helpers for displaying modaliases through sysfs.
+ *
+ * This borrows a lot from file2alias.c
+ */
+
+#include <linux/device/bus.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+
+#include "../usb/core/usb.h"
+
+#define ADD(buf, count, len, sep, cond, field) \
+do { \
+ if (cond) \
+ len += scnprintf(&buf[len], \
+ count - len, \
+ sizeof(field) == 1 ? sep "%02X" : \
+ sizeof(field) == 2 ? sep "%04X" : \
+ sizeof(field) == 4 ? sep "%08X" : "", \
+ field); \
+ else \
+ len += scnprintf(&buf[len], count - len, sep "*"); \
+} while (0)
+
+/* USB related modaliases can be split because of device number matching, so
+ * this function handles individual modaliases for one segment of the range.
+ *
+ *
+ */
+static ssize_t usb_id_to_modalias(const struct usb_device_id *id,
+ unsigned int bcdDevice_initial,
+ int bcdDevice_initial_digits,
+ unsigned char range_lo,
+ unsigned char range_hi,
+ unsigned char max, const char *mod_name,
+ char *buf, size_t count)
+{
+ ssize_t len = 0;
+
+ ADD(buf, count, len, "alias usb:v",
+ id->match_flags & USB_DEVICE_ID_MATCH_VENDOR, id->idVendor);
+ ADD(buf, count, len, "p", id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT,
+ id->idProduct);
+
+ len += scnprintf(&buf[len], count - len, "d");
+ if (bcdDevice_initial_digits)
+ len += scnprintf(&buf[len], count - len, "%0*X",
+ bcdDevice_initial_digits, bcdDevice_initial);
+ if (range_lo == range_hi)
+ len += scnprintf(&buf[len], count - len, "%X", range_lo);
+ else if (range_lo > 0 || range_hi < max) {
+ if (range_lo > 0x9 || range_hi < 0xA)
+ len += scnprintf(&buf[len], count - len,
+ "[%X-%X]",
+ range_lo,
+ range_hi);
+ else {
+ len += scnprintf(&buf[len], count - len,
+ range_lo < 0x9 ? "[%X-9" : "[%X",
+ range_lo);
+ len += scnprintf(&buf[len], count - len,
+ range_hi > 0xA ? "A-%X]" : "%X]",
+ range_hi);
+ }
+ }
+ if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
+ len += scnprintf(&buf[len], count - len, "*");
+
+ ADD(buf, count, len, "dc",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS, id->bDeviceClass);
+ ADD(buf, count, len, "dsc",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+ id->bDeviceSubClass);
+ ADD(buf, count, len, "dp",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ id->bDeviceProtocol);
+ ADD(buf, count, len, "ic",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS,
+ id->bInterfaceClass);
+ ADD(buf, count, len, "isc",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ id->bInterfaceSubClass);
+ ADD(buf, count, len, "ip",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+ id->bInterfaceProtocol);
+ ADD(buf, count, len, "in",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER,
+ id->bInterfaceNumber);
+
+ len += scnprintf(&buf[len], count - len, " %s\n", mod_name);
+ return len;
+}
+
+/* Handles increment/decrement of BCD formatted integers */
+/* Returns the previous value, so it works like i++ or i-- */
+static unsigned int incbcd(unsigned int *bcd,
+ int inc,
+ unsigned char max,
+ size_t chars)
+{
+ unsigned int init = *bcd, i, j;
+ unsigned long long c, dec = 0;
+
+ /* If bcd is not in BCD format, just increment */
+ if (max > 0x9) {
+ *bcd += inc;
+ return init;
+ }
+
+ /* Convert BCD to Decimal */
+ for (i = 0 ; i < chars ; i++) {
+ c = (*bcd >> (i << 2)) & 0xf;
+ c = c > 9 ? 9 : c; /* force to bcd just in case */
+ for (j = 0 ; j < i ; j++)
+ c = c * 10;
+ dec += c;
+ }
+
+ /* Do our increment/decrement */
+ dec += inc;
+ *bcd = 0;
+
+ /* Convert back to BCD */
+ for (i = 0 ; i < chars ; i++) {
+ for (c = 1, j = 0 ; j < i ; j++)
+ c = c * 10;
+ c = (dec / c) % 10;
+ *bcd += c << (i << 2);
+ }
+ return init;
+}
+
+/* Print the modaliases for the specified struct usb_device_id.
+ */
+static ssize_t usb_id_to_modalias_multi(const struct usb_device_id *id,
+ const char *mod_name, char *buf,
+ size_t count)
+{
+ ssize_t len = 0;
+ unsigned int devlo, devhi;
+ unsigned char chi, clo, max;
+ int ndigits;
+
+ devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
+ id->bcdDevice_lo : 0x0U;
+ devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
+ id->bcdDevice_hi : ~0x0U;
+
+ /* Figure out if this entry is in bcd or hex format */
+ max = 0x9; /* Default to decimal format */
+ for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
+ clo = (devlo >> (ndigits << 2)) & 0xf;
+ chi = ((devhi > 0x9999 ? 0x9999 : devhi) >>
+ (ndigits << 2)) & 0xf;
+ if (clo > max || chi > max) {
+ max = 0xf;
+ break;
+ }
+ }
+
+ /*
+ * Some modules (visor) have empty slots as placeholder for
+ * run-time specification that results in catch-all alias
+ */
+ if (!(id->idVendor || id->idProduct || id->bDeviceClass ||
+ id->bInterfaceClass))
+ return len;
+
+ /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
+ for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi;
+ ndigits--) {
+ clo = devlo & 0xf;
+ chi = devhi & 0xf;
+ /* If we are in bcd mode, truncate if necessary */
+ if (chi > max)
+ chi = max;
+ devlo >>= 4;
+ devhi >>= 4;
+
+ if (devlo == devhi || !ndigits) {
+ len += usb_id_to_modalias(id, devlo, ndigits, clo, chi,
+ max, mod_name, buf + len,
+ count - len);
+ break;
+ }
+
+ if (clo > 0x0)
+ len += usb_id_to_modalias(id,
+ incbcd(&devlo, 1, max,
+ sizeof(id->bcdDevice_lo) * 2),
+ ndigits, clo, max, max, mod_name, buf + len,
+ count - len);
+
+ if (chi < max)
+ len += usb_id_to_modalias(id,
+ incbcd(&devhi, -1, max,
+ sizeof(id->bcdDevice_lo) * 2),
+ ndigits, 0x0, chi, max, mod_name, buf + len,
+ count - len);
+ }
+ return len;
+}
+
+/* Print the modaliases for the given driver assumed to be an usb_driver or
+ * usb_device_driver.
+ *
+ * "alias" is prepended and the module name is appended to each modalias to
+ * match the format in modules.aliases.
+ *
+ * The modaliases will be written out to @buf with @count being the maximum
+ * bytes to write. The return value is a negative errno on error or the number
+ * of bytes written to @buf on success.
+ */
+ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count)
+{
+ ssize_t len = 0;
+ const struct usb_device_id *id;
+ const char *mod_name;
+
+ if (drv->bus != &usb_bus_type)
+ return -EINVAL;
+
+ if (drv->owner)
+ mod_name = drv->owner->name;
+ else
+ mod_name = drv->mod_name;
+
+ if (is_usb_device_driver(drv))
+ id = to_usb_device_driver(drv)->id_table;
+ else
+ id = to_usb_driver(drv)->id_table;
+ if (!id)
+ return len;
+
+ for (; id->match_flags; id++) {
+ len += usb_id_to_modalias_multi(id, mod_name, buf + len,
+ count - len);
+ }
+ return len;
+}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7e7e119c253fb..fdbc197b64c9c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -32,6 +32,7 @@
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h>

+#include "../../base/base.h"
#include "usb.h"


@@ -2030,4 +2031,5 @@ struct bus_type usb_bus_type = {
.match = usb_device_match,
.uevent = usb_uevent,
.need_parent_lock = true,
+ .drv_to_modalias = usb_drv_to_modalias,
};
diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h
index d8b29ccd07e56..cce0bedec63d9 100644
--- a/include/linux/device/bus.h
+++ b/include/linux/device/bus.h
@@ -61,6 +61,10 @@ struct fwnode_handle;
* this bus.
* @dma_cleanup: Called to cleanup DMA configuration on a device on
* this bus.
+ * @drv_to_modalias: Called to convert the matching IDs in a
+ * struct device_driver to their corresponding modaliases.
+ * Note that the struct device_driver is
expected to belong
+ * to this bus.
* @pm: Power management operations of this bus, callback the specific
* device driver's pm-ops.
* @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU
@@ -107,6 +111,9 @@ struct bus_type {
int (*dma_configure)(struct device *dev);
void (*dma_cleanup)(struct device *dev);

+ ssize_t (*drv_to_modalias)(struct device_driver *drv, char *buf,
+ size_t count);
+
const struct dev_pm_ops *pm;

const struct iommu_ops *iommu_ops;
@@ -161,6 +168,7 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter,
struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
void subsys_dev_iter_exit(struct subsys_dev_iter *iter);

+int bus_for_each(void *data, int (*fn)(struct bus_type *, void *));
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
int (*fn)(struct device *dev, void *data));
struct device *bus_find_device(struct bus_type *bus, struct device *start,
diff --git a/include/linux/module.h b/include/linux/module.h
index 518296ea7f73a..68fe7bfc38683 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -48,6 +48,7 @@ struct module_kobject {
struct kobject *drivers_dir;
struct module_param_attrs *mp;
struct completion *kobj_completion;
+ struct bin_attribute modalias_attr;
} __randomize_layout;

struct module_attribute {
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 680d980a4fb29..63b794cd65df2 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -259,11 +259,13 @@ static inline void add_kallsyms(struct module
*mod, const struct load_info *info
#endif /* CONFIG_KALLSYMS */

#ifdef CONFIG_SYSFS
+void add_modalias_attr(struct module_kobject *mk);
int mod_sysfs_setup(struct module *mod, const struct load_info *info,
struct kernel_param *kparam, unsigned int num_params);
void mod_sysfs_teardown(struct module *mod);
void init_param_lock(struct module *mod);
#else /* !CONFIG_SYSFS */
+static inline void add_modalias_attr(struct module_kobject *mk) {}
static inline int mod_sysfs_setup(struct module *mod,
const struct load_info *info,
struct kernel_param *kparam,
diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index ce68f821dcd12..8696334dcaadc 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -5,6 +5,8 @@
* Copyright (C) 2008 Rusty Russell
*/

+#include <linux/device/bus.h>
+#include <linux/device/driver.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
@@ -240,6 +242,102 @@ static inline void add_notes_attrs(struct module
*mod, const struct load_info *i
static inline void remove_notes_attrs(struct module *mod) { }
#endif /* CONFIG_KALLSYMS */

+/* Track of the buffer and module identity in callbacks when walking
the list of
+ * drivers for each bus.
+ */
+struct modalias_bus_print_state {
+ struct module_kobject *mk;
+ char *buf;
+ size_t count;
+ ssize_t len;
+};
+
+static int print_modalias_for_drv(struct device_driver *drv, void *p)
+{
+ struct modalias_bus_print_state *s = p;
+ struct module_kobject *mk = s->mk;
+ ssize_t len;
+ /* Skip drivers that do not match this module. */
+ if (mk->mod) {
+ if (mk->mod != drv->owner)
+ return 0;
+ } else if (!mk->kobj.name || !drv->mod_name ||
+ strcmp(mk->kobj.name, drv->mod_name))
+ return 0;
+
+ if (drv->bus && drv->bus->drv_to_modalias) {
+ len = drv->bus->drv_to_modalias(drv, s->buf + s->len,
+ s->count - s->len);
+ if (len < 0)
+ return len;
+ s->len += len;
+ }
+
+ s->len += scnprintf(&s->buf[s->len], s->count - s->len, "driver %s\n",
+ drv->name);
+ return 0;
+}
+
+static int print_modalias_for_bus(struct bus_type *type, void *p)
+{
+ return bus_for_each_drv(type, NULL, p, print_modalias_for_drv);
+}
+
+static ssize_t module_modalias_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct module_kobject *mk = container_of(kobj, struct module_kobject,
+ kobj);
+ struct modalias_bus_print_state state = {mk, buf, count, 0};
+ int error = 0;
+
+ if (pos != 0)
+ return -EINVAL;
+
+ error = bus_for_each(&state, print_modalias_for_bus);
+ if (error)
+ return error;
+
+ if (mk->mod)
+ state.len += scnprintf(&buf[state.len], count - state.len,
+ "modalias %s %s\n", kobject_name(kobj),
+ mk->mod->name);
+ else
+ state.len += scnprintf(&buf[state.len], count - state.len,
+ "modalias %s NULL\n",
+ kobject_name(kobj));
+
+ /*
+ * The caller checked the pos and count against our size.
+ */
+ return state.len;
+}
+
+/* Used in kernel/params.c for builtin modules.
+ *
+ * `struct module_kobject` is used instead of `struct module` because for
+ * builtin modules, the `struct module` is not available when this is called.
+ */
+void add_modalias_attr(struct module_kobject *mk)
+{
+ sysfs_bin_attr_init(&mk->modalias_attr);
+ mk->modalias_attr.attr.name = "modalias";
+ mk->modalias_attr.attr.mode = 0444;
+ mk->modalias_attr.read = module_modalias_read;
+ if (sysfs_create_bin_file(&mk->kobj, &mk->modalias_attr)) {
+ /* We shouldn't ignore the return type, but there is nothing to
+ * do.
+ */
+ return;
+ }
+}
+
+static void remove_modalias_attr(struct module_kobject *mk)
+{
+ sysfs_remove_bin_file(&mk->kobj, &mk->modalias_attr);
+}
+
static void del_usage_links(struct module *mod)
{
#ifdef CONFIG_MODULE_UNLOAD
@@ -398,6 +496,7 @@ int mod_sysfs_setup(struct module *mod,

add_sect_attrs(mod, info);
add_notes_attrs(mod, info);
+ add_modalias_attr(&mod->mkobj);

return 0;

@@ -415,6 +514,7 @@ int mod_sysfs_setup(struct module *mod,

static void mod_sysfs_fini(struct module *mod)
{
+ remove_modalias_attr(&mod->mkobj);
remove_notes_attrs(mod);
remove_sect_attrs(mod);
mod_kobject_put(mod);
diff --git a/kernel/params.c b/kernel/params.c
index 5b92310425c50..111024196361a 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/security.h>
+#include "module/internal.h"

#ifdef CONFIG_SYSFS
/* Protects all built-in parameters, modules use their own param_lock */
@@ -815,6 +816,7 @@ static void __init kernel_add_sysfs_param(const char *name,
BUG_ON(err);
kobject_uevent(&mk->kobj, KOBJ_ADD);
kobject_put(&mk->kobj);
+ add_modalias_attr(mk);
}

/*
--
2.37.3


Allen


2022-11-11 06:23:25

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: Patch to exposing modalias'es for built in kernel modules (USB)

On Thu, Nov 10, 2022 at 04:21:30PM -0600, Allen Webb wrote:
> My apologies for any process mistakes in submitting this as it is my
> first ever attempt at a Linux kernel patch.
>


Hi,

This is the friendly patch-bot of Greg Kroah-Hartman. You have sent him
a patch that has triggered this response. He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created. Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- Your patch contains warnings and/or errors noticed by the
scripts/checkpatch.pl tool.

- Your patch is malformed (tabs converted to spaces, linewrapped, etc.)
and can not be applied. Please read the file,
Documentation/email-clients.txt in order to fix this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

2022-11-11 10:51:37

by Christophe Leroy

[permalink] [raw]
Subject: Re: Patch to exposing modalias'es for built in kernel modules (USB)

Le 10/11/2022 à 23:21, Allen Webb a écrit :
> [Vous ne recevez pas souvent de courriers de [email protected]. Découvrez pourquoi ceci est important à https://aka.ms/LearnAboutSenderIdentification ]
>
> My apologies for any process mistakes in submitting this as it is my
> first ever attempt at a Linux kernel patch.

First problem: your patch is corrupted, it doesn't apply. For instance,
some long line are wrapped. For instance line 514, the "expected to
belong", see
https://patchwork.kernel.org/project/linux-modules/patch/CAJzde042-M4UbpNYKw0eDVg4JqYmwmPYSsmgK+kCMTqsi+-2Yw@mail.gmail.com/

Maybe you can then start with the codiing style. See
https://docs.kernel.org/process/coding-style.html

Then there is a script call checkpatch.pl, located in script/ directory.
All you have to do is:

./scripts/checkpatch.pl -g HEAD

to check a patch in your git tree (replace HEAD by the patch sha if it
is not at the head of the current branch)

Or

./scripts/checkpatch.pl -f patch_file

patch_file being the result of 'git format-patch'


Using --strict option you get even more results, allthough some of the
reported checks may not always be relevant.

With your patch I get:
total: 9 errors, 284 warnings, 512 lines checked

See below the result on your patch:

ERROR: Remove Gerrit Change-Id's before submitting upstream
#135:
Change-Id: I83b6f0c30e06e65cbe223f1606187283fcb13215

WARNING: please, no spaces at the start of a line
#174: FILE: drivers/base/base.h:180:
+ size_t count);$

WARNING: please, no spaces at the start of a line
#177: FILE: drivers/base/base.h:183:
+ size_t count) { return -ENOSUP; }$

WARNING: please, no spaces at the start of a line
#211: FILE: drivers/base/bus.c:201:
+ int error = 0;$

WARNING: please, no spaces at the start of a line
#212: FILE: drivers/base/bus.c:202:
+ struct bus_type *bus;$

WARNING: please, no spaces at the start of a line
#213: FILE: drivers/base/bus.c:203:
+ struct subsys_private *bus_prv;$

WARNING: please, no spaces at the start of a line
#214: FILE: drivers/base/bus.c:204:
+ struct kset *subsys;$

WARNING: please, no spaces at the start of a line
#215: FILE: drivers/base/bus.c:205:
+ struct kobject *k;$

WARNING: please, no spaces at the start of a line
#217: FILE: drivers/base/bus.c:207:
+ spin_lock(&bus_kset->list_lock);$

WARNING: please, no spaces at the start of a line
#219: FILE: drivers/base/bus.c:209:
+ list_for_each_entry(k, &bus_kset->list, entry) {$

WARNING: suspect code indent for conditional statements (1, 1)
#219: FILE: drivers/base/bus.c:209:
+ list_for_each_entry(k, &bus_kset->list, entry) {
+ subsys = container_of(k, struct kset, kobj);

WARNING: please, no spaces at the start of a line
#220: FILE: drivers/base/bus.c:210:
+ subsys = container_of(k, struct kset, kobj);$

WARNING: please, no spaces at the start of a line
#221: FILE: drivers/base/bus.c:211:
+ bus_prv = container_of(subsys, struct subsys_private, subsys);$

WARNING: please, no spaces at the start of a line
#222: FILE: drivers/base/bus.c:212:
+ bus = bus_prv->bus;$

WARNING: please, no spaces at the start of a line
#223: FILE: drivers/base/bus.c:213:
+ error = fn(bus, data);$

WARNING: please, no spaces at the start of a line
#224: FILE: drivers/base/bus.c:214:
+ if (error)$

WARNING: suspect code indent for conditional statements (1, 1)
#224: FILE: drivers/base/bus.c:214:
+ if (error)
+ break;

WARNING: please, no spaces at the start of a line
#225: FILE: drivers/base/bus.c:215:
+ break;$

WARNING: please, no spaces at the start of a line
#226: FILE: drivers/base/bus.c:216:
+ }$

WARNING: please, no spaces at the start of a line
#228: FILE: drivers/base/bus.c:218:
+ spin_unlock(&bus_kset->list_lock);$

WARNING: please, no spaces at the start of a line
#229: FILE: drivers/base/bus.c:219:
+ return error;$

WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#237:
new file mode 100644

WARNING: suspect code indent for conditional statements (0, 1)
#256: FILE: drivers/base/mod_devicetable.c:15:
+do { \
+ if (cond) \

WARNING: please, no spaces at the start of a line
#257: FILE: drivers/base/mod_devicetable.c:16:
+ if (cond) \$

WARNING: suspect code indent for conditional statements (1, 1)
#257: FILE: drivers/base/mod_devicetable.c:16:
+ if (cond) \
+ len += scnprintf(&buf[len], \

WARNING: please, no spaces at the start of a line
#258: FILE: drivers/base/mod_devicetable.c:17:
+ len += scnprintf(&buf[len], \$

WARNING: please, no spaces at the start of a line
#259: FILE: drivers/base/mod_devicetable.c:18:
+ count - len, \$

WARNING: please, no spaces at the start of a line
#260: FILE: drivers/base/mod_devicetable.c:19:
+ sizeof(field) == 1 ? sep "%02X" : \$

WARNING: please, no spaces at the start of a line
#261: FILE: drivers/base/mod_devicetable.c:20:
+ sizeof(field) == 2 ? sep "%04X" : \$

WARNING: please, no spaces at the start of a line
#262: FILE: drivers/base/mod_devicetable.c:21:
+ sizeof(field) == 4 ? sep "%08X" : "", \$

WARNING: please, no spaces at the start of a line
#263: FILE: drivers/base/mod_devicetable.c:22:
+ field); \$

WARNING: please, no spaces at the start of a line
#264: FILE: drivers/base/mod_devicetable.c:23:
+ else \$

WARNING: suspect code indent for conditional statements (1, 1)
#264: FILE: drivers/base/mod_devicetable.c:23:
+ else \
+ len += scnprintf(&buf[len], count - len, sep "*"); \

WARNING: please, no spaces at the start of a line
#265: FILE: drivers/base/mod_devicetable.c:24:
+ len += scnprintf(&buf[len], count - len, sep "*"); \$

WARNING: please, no spaces at the start of a line
#274: FILE: drivers/base/mod_devicetable.c:33:
+ unsigned int bcdDevice_initial,$

WARNING: please, no spaces at the start of a line
#275: FILE: drivers/base/mod_devicetable.c:34:
+ int bcdDevice_initial_digits,$

WARNING: please, no spaces at the start of a line
#276: FILE: drivers/base/mod_devicetable.c:35:
+ unsigned char range_lo,$

WARNING: please, no spaces at the start of a line
#277: FILE: drivers/base/mod_devicetable.c:36:
+ unsigned char range_hi,$

WARNING: please, no spaces at the start of a line
#278: FILE: drivers/base/mod_devicetable.c:37:
+ unsigned char max, const char *mod_name,$

WARNING: please, no spaces at the start of a line
#279: FILE: drivers/base/mod_devicetable.c:38:
+ char *buf, size_t count)$

WARNING: please, no spaces at the start of a line
#281: FILE: drivers/base/mod_devicetable.c:40:
+ ssize_t len = 0;$

WARNING: please, no spaces at the start of a line
#283: FILE: drivers/base/mod_devicetable.c:42:
+ ADD(buf, count, len, "alias usb:v",$

WARNING: please, no spaces at the start of a line
#284: FILE: drivers/base/mod_devicetable.c:43:
+ id->match_flags & USB_DEVICE_ID_MATCH_VENDOR, id->idVendor);$

WARNING: please, no spaces at the start of a line
#285: FILE: drivers/base/mod_devicetable.c:44:
+ ADD(buf, count, len, "p", id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT,$

WARNING: please, no spaces at the start of a line
#286: FILE: drivers/base/mod_devicetable.c:45:
+ id->idProduct);$

WARNING: please, no spaces at the start of a line
#288: FILE: drivers/base/mod_devicetable.c:47:
+ len += scnprintf(&buf[len], count - len, "d");$

WARNING: please, no spaces at the start of a line
#289: FILE: drivers/base/mod_devicetable.c:48:
+ if (bcdDevice_initial_digits)$

WARNING: suspect code indent for conditional statements (1, 1)
#289: FILE: drivers/base/mod_devicetable.c:48:
+ if (bcdDevice_initial_digits)
+ len += scnprintf(&buf[len], count - len, "%0*X",

WARNING: please, no spaces at the start of a line
#290: FILE: drivers/base/mod_devicetable.c:49:
+ len += scnprintf(&buf[len], count - len, "%0*X",$

WARNING: please, no spaces at the start of a line
#291: FILE: drivers/base/mod_devicetable.c:50:
+ bcdDevice_initial_digits, bcdDevice_initial);$

WARNING: please, no spaces at the start of a line
#292: FILE: drivers/base/mod_devicetable.c:51:
+ if (range_lo == range_hi)$

WARNING: suspect code indent for conditional statements (1, 1)
#292: FILE: drivers/base/mod_devicetable.c:51:
+ if (range_lo == range_hi)
+ len += scnprintf(&buf[len], count - len, "%X", range_lo);

WARNING: please, no spaces at the start of a line
#293: FILE: drivers/base/mod_devicetable.c:52:
+ len += scnprintf(&buf[len], count - len, "%X", range_lo);$

WARNING: please, no spaces at the start of a line
#294: FILE: drivers/base/mod_devicetable.c:53:
+ else if (range_lo > 0 || range_hi < max) {$

WARNING: suspect code indent for conditional statements (1, 1)
#294: FILE: drivers/base/mod_devicetable.c:53:
+ else if (range_lo > 0 || range_hi < max) {
+ if (range_lo > 0x9 || range_hi < 0xA)

WARNING: please, no spaces at the start of a line
#295: FILE: drivers/base/mod_devicetable.c:54:
+ if (range_lo > 0x9 || range_hi < 0xA)$

WARNING: suspect code indent for conditional statements (1, 1)
#295: FILE: drivers/base/mod_devicetable.c:54:
+ if (range_lo > 0x9 || range_hi < 0xA)
+ len += scnprintf(&buf[len], count - len,

WARNING: please, no spaces at the start of a line
#296: FILE: drivers/base/mod_devicetable.c:55:
+ len += scnprintf(&buf[len], count - len,$

WARNING: please, no spaces at the start of a line
#297: FILE: drivers/base/mod_devicetable.c:56:
+ "[%X-%X]",$

WARNING: please, no spaces at the start of a line
#298: FILE: drivers/base/mod_devicetable.c:57:
+ range_lo,$

WARNING: please, no spaces at the start of a line
#299: FILE: drivers/base/mod_devicetable.c:58:
+ range_hi);$

WARNING: please, no spaces at the start of a line
#300: FILE: drivers/base/mod_devicetable.c:59:
+ else {$

WARNING: suspect code indent for conditional statements (1, 1)
#300: FILE: drivers/base/mod_devicetable.c:59:
+ else {
+ len += scnprintf(&buf[len], count - len,

WARNING: please, no spaces at the start of a line
#301: FILE: drivers/base/mod_devicetable.c:60:
+ len += scnprintf(&buf[len], count - len,$

WARNING: please, no spaces at the start of a line
#302: FILE: drivers/base/mod_devicetable.c:61:
+ range_lo < 0x9 ? "[%X-9" : "[%X",$

WARNING: please, no spaces at the start of a line
#303: FILE: drivers/base/mod_devicetable.c:62:
+ range_lo);$

WARNING: please, no spaces at the start of a line
#304: FILE: drivers/base/mod_devicetable.c:63:
+ len += scnprintf(&buf[len], count - len,$

WARNING: please, no spaces at the start of a line
#305: FILE: drivers/base/mod_devicetable.c:64:
+ range_hi > 0xA ? "A-%X]" : "%X]",$

WARNING: please, no spaces at the start of a line
#306: FILE: drivers/base/mod_devicetable.c:65:
+ range_hi);$

WARNING: please, no spaces at the start of a line
#307: FILE: drivers/base/mod_devicetable.c:66:
+ }$

WARNING: please, no spaces at the start of a line
#308: FILE: drivers/base/mod_devicetable.c:67:
+ }$

WARNING: please, no spaces at the start of a line
#309: FILE: drivers/base/mod_devicetable.c:68:
+ if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))$

WARNING: suspect code indent for conditional statements (1, 1)
#309: FILE: drivers/base/mod_devicetable.c:68:
+ if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
+ len += scnprintf(&buf[len], count - len, "*");

WARNING: please, no spaces at the start of a line
#310: FILE: drivers/base/mod_devicetable.c:69:
+ len += scnprintf(&buf[len], count - len, "*");$

WARNING: please, no spaces at the start of a line
#312: FILE: drivers/base/mod_devicetable.c:71:
+ ADD(buf, count, len, "dc",$

WARNING: please, no spaces at the start of a line
#313: FILE: drivers/base/mod_devicetable.c:72:
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS, id->bDeviceClass);$

WARNING: please, no spaces at the start of a line
#314: FILE: drivers/base/mod_devicetable.c:73:
+ ADD(buf, count, len, "dsc",$

WARNING: please, no spaces at the start of a line
#315: FILE: drivers/base/mod_devicetable.c:74:
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS,$

WARNING: please, no spaces at the start of a line
#316: FILE: drivers/base/mod_devicetable.c:75:
+ id->bDeviceSubClass);$

WARNING: please, no spaces at the start of a line
#317: FILE: drivers/base/mod_devicetable.c:76:
+ ADD(buf, count, len, "dp",$

WARNING: please, no spaces at the start of a line
#318: FILE: drivers/base/mod_devicetable.c:77:
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL,$

WARNING: please, no spaces at the start of a line
#319: FILE: drivers/base/mod_devicetable.c:78:
+ id->bDeviceProtocol);$

WARNING: please, no spaces at the start of a line
#320: FILE: drivers/base/mod_devicetable.c:79:
+ ADD(buf, count, len, "ic",$

WARNING: please, no spaces at the start of a line
#321: FILE: drivers/base/mod_devicetable.c:80:
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS,$

WARNING: please, no spaces at the start of a line
#322: FILE: drivers/base/mod_devicetable.c:81:
+ id->bInterfaceClass);$

WARNING: please, no spaces at the start of a line
#323: FILE: drivers/base/mod_devicetable.c:82:
+ ADD(buf, count, len, "isc",$

WARNING: please, no spaces at the start of a line
#324: FILE: drivers/base/mod_devicetable.c:83:
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS,$

WARNING: please, no spaces at the start of a line
#325: FILE: drivers/base/mod_devicetable.c:84:
+ id->bInterfaceSubClass);$

WARNING: please, no spaces at the start of a line
#326: FILE: drivers/base/mod_devicetable.c:85:
+ ADD(buf, count, len, "ip",$

WARNING: please, no spaces at the start of a line
#327: FILE: drivers/base/mod_devicetable.c:86:
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL,$

WARNING: please, no spaces at the start of a line
#328: FILE: drivers/base/mod_devicetable.c:87:
+ id->bInterfaceProtocol);$

WARNING: please, no spaces at the start of a line
#329: FILE: drivers/base/mod_devicetable.c:88:
+ ADD(buf, count, len, "in",$

WARNING: please, no spaces at the start of a line
#330: FILE: drivers/base/mod_devicetable.c:89:
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER,$

WARNING: please, no spaces at the start of a line
#331: FILE: drivers/base/mod_devicetable.c:90:
+ id->bInterfaceNumber);$

WARNING: please, no spaces at the start of a line
#333: FILE: drivers/base/mod_devicetable.c:92:
+ len += scnprintf(&buf[len], count - len, " %s\n", mod_name);$

WARNING: please, no spaces at the start of a line
#334: FILE: drivers/base/mod_devicetable.c:93:
+ return len;$

WARNING: please, no spaces at the start of a line
#340: FILE: drivers/base/mod_devicetable.c:99:
+ int inc,$

WARNING: please, no spaces at the start of a line
#341: FILE: drivers/base/mod_devicetable.c:100:
+ unsigned char max,$

WARNING: please, no spaces at the start of a line
#342: FILE: drivers/base/mod_devicetable.c:101:
+ size_t chars)$

WARNING: please, no spaces at the start of a line
#344: FILE: drivers/base/mod_devicetable.c:103:
+ unsigned int init = *bcd, i, j;$

WARNING: please, no spaces at the start of a line
#345: FILE: drivers/base/mod_devicetable.c:104:
+ unsigned long long c, dec = 0;$

WARNING: please, no spaces at the start of a line
#348: FILE: drivers/base/mod_devicetable.c:107:
+ if (max > 0x9) {$

WARNING: suspect code indent for conditional statements (1, 1)
#348: FILE: drivers/base/mod_devicetable.c:107:
+ if (max > 0x9) {
+ *bcd += inc;

WARNING: please, no spaces at the start of a line
#349: FILE: drivers/base/mod_devicetable.c:108:
+ *bcd += inc;$

WARNING: please, no spaces at the start of a line
#350: FILE: drivers/base/mod_devicetable.c:109:
+ return init;$

WARNING: please, no spaces at the start of a line
#351: FILE: drivers/base/mod_devicetable.c:110:
+ }$

WARNING: please, no spaces at the start of a line
#354: FILE: drivers/base/mod_devicetable.c:113:
+ for (i = 0 ; i < chars ; i++) {$

WARNING: suspect code indent for conditional statements (1, 1)
#354: FILE: drivers/base/mod_devicetable.c:113:
+ for (i = 0 ; i < chars ; i++) {
+ c = (*bcd >> (i << 2)) & 0xf;

WARNING: please, no spaces at the start of a line
#355: FILE: drivers/base/mod_devicetable.c:114:
+ c = (*bcd >> (i << 2)) & 0xf;$

WARNING: please, no spaces at the start of a line
#356: FILE: drivers/base/mod_devicetable.c:115:
+ c = c > 9 ? 9 : c; /* force to bcd just in case */$

WARNING: please, no spaces at the start of a line
#357: FILE: drivers/base/mod_devicetable.c:116:
+ for (j = 0 ; j < i ; j++)$

WARNING: suspect code indent for conditional statements (1, 1)
#357: FILE: drivers/base/mod_devicetable.c:116:
+ for (j = 0 ; j < i ; j++)
+ c = c * 10;

WARNING: please, no spaces at the start of a line
#358: FILE: drivers/base/mod_devicetable.c:117:
+ c = c * 10;$

WARNING: please, no spaces at the start of a line
#359: FILE: drivers/base/mod_devicetable.c:118:
+ dec += c;$

WARNING: please, no spaces at the start of a line
#360: FILE: drivers/base/mod_devicetable.c:119:
+ }$

WARNING: please, no spaces at the start of a line
#363: FILE: drivers/base/mod_devicetable.c:122:
+ dec += inc;$

WARNING: please, no spaces at the start of a line
#364: FILE: drivers/base/mod_devicetable.c:123:
+ *bcd = 0;$

WARNING: please, no spaces at the start of a line
#367: FILE: drivers/base/mod_devicetable.c:126:
+ for (i = 0 ; i < chars ; i++) {$

WARNING: suspect code indent for conditional statements (1, 1)
#367: FILE: drivers/base/mod_devicetable.c:126:
+ for (i = 0 ; i < chars ; i++) {
+ for (c = 1, j = 0 ; j < i ; j++)

WARNING: please, no spaces at the start of a line
#368: FILE: drivers/base/mod_devicetable.c:127:
+ for (c = 1, j = 0 ; j < i ; j++)$

WARNING: suspect code indent for conditional statements (1, 1)
#368: FILE: drivers/base/mod_devicetable.c:127:
+ for (c = 1, j = 0 ; j < i ; j++)
+ c = c * 10;

WARNING: please, no spaces at the start of a line
#369: FILE: drivers/base/mod_devicetable.c:128:
+ c = c * 10;$

WARNING: please, no spaces at the start of a line
#370: FILE: drivers/base/mod_devicetable.c:129:
+ c = (dec / c) % 10;$

WARNING: please, no spaces at the start of a line
#371: FILE: drivers/base/mod_devicetable.c:130:
+ *bcd += c << (i << 2);$

WARNING: please, no spaces at the start of a line
#372: FILE: drivers/base/mod_devicetable.c:131:
+ }$

WARNING: please, no spaces at the start of a line
#373: FILE: drivers/base/mod_devicetable.c:132:
+ return init;$

WARNING: please, no spaces at the start of a line
#379: FILE: drivers/base/mod_devicetable.c:138:
+ const char *mod_name, char *buf,$

WARNING: please, no spaces at the start of a line
#380: FILE: drivers/base/mod_devicetable.c:139:
+ size_t count)$

WARNING: please, no spaces at the start of a line
#382: FILE: drivers/base/mod_devicetable.c:141:
+ ssize_t len = 0;$

WARNING: please, no spaces at the start of a line
#383: FILE: drivers/base/mod_devicetable.c:142:
+ unsigned int devlo, devhi;$

WARNING: please, no spaces at the start of a line
#384: FILE: drivers/base/mod_devicetable.c:143:
+ unsigned char chi, clo, max;$

WARNING: please, no spaces at the start of a line
#385: FILE: drivers/base/mod_devicetable.c:144:
+ int ndigits;$

WARNING: please, no spaces at the start of a line
#387: FILE: drivers/base/mod_devicetable.c:146:
+ devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?$

WARNING: please, no spaces at the start of a line
#388: FILE: drivers/base/mod_devicetable.c:147:
+ id->bcdDevice_lo : 0x0U;$

WARNING: please, no spaces at the start of a line
#389: FILE: drivers/base/mod_devicetable.c:148:
+ devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?$

WARNING: please, no spaces at the start of a line
#390: FILE: drivers/base/mod_devicetable.c:149:
+ id->bcdDevice_hi : ~0x0U;$

WARNING: please, no spaces at the start of a line
#393: FILE: drivers/base/mod_devicetable.c:152:
+ max = 0x9; /* Default to decimal format */$

WARNING: please, no spaces at the start of a line
#394: FILE: drivers/base/mod_devicetable.c:153:
+ for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {$

WARNING: suspect code indent for conditional statements (1, 1)
#394: FILE: drivers/base/mod_devicetable.c:153:
+ for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
+ clo = (devlo >> (ndigits << 2)) & 0xf;

WARNING: please, no spaces at the start of a line
#395: FILE: drivers/base/mod_devicetable.c:154:
+ clo = (devlo >> (ndigits << 2)) & 0xf;$

WARNING: please, no spaces at the start of a line
#396: FILE: drivers/base/mod_devicetable.c:155:
+ chi = ((devhi > 0x9999 ? 0x9999 : devhi) >>$

ERROR: code indent should use tabs where possible
#397: FILE: drivers/base/mod_devicetable.c:156:
+ (ndigits << 2)) & 0xf;$

WARNING: please, no spaces at the start of a line
#397: FILE: drivers/base/mod_devicetable.c:156:
+ (ndigits << 2)) & 0xf;$

WARNING: please, no spaces at the start of a line
#398: FILE: drivers/base/mod_devicetable.c:157:
+ if (clo > max || chi > max) {$

WARNING: suspect code indent for conditional statements (1, 1)
#398: FILE: drivers/base/mod_devicetable.c:157:
+ if (clo > max || chi > max) {
+ max = 0xf;

WARNING: please, no spaces at the start of a line
#399: FILE: drivers/base/mod_devicetable.c:158:
+ max = 0xf;$

WARNING: please, no spaces at the start of a line
#400: FILE: drivers/base/mod_devicetable.c:159:
+ break;$

WARNING: please, no spaces at the start of a line
#401: FILE: drivers/base/mod_devicetable.c:160:
+ }$

WARNING: please, no spaces at the start of a line
#402: FILE: drivers/base/mod_devicetable.c:161:
+ }$

WARNING: Block comments should align the * on each line
#405: FILE: drivers/base/mod_devicetable.c:164:
+ /*
+ * Some modules (visor) have empty slots as placeholder for

WARNING: please, no spaces at the start of a line
#408: FILE: drivers/base/mod_devicetable.c:167:
+ if (!(id->idVendor || id->idProduct || id->bDeviceClass ||$

WARNING: suspect code indent for conditional statements (1, 1)
#408: FILE: drivers/base/mod_devicetable.c:167:
+ if (!(id->idVendor || id->idProduct || id->bDeviceClass ||
[...]
+ return len;

WARNING: please, no spaces at the start of a line
#409: FILE: drivers/base/mod_devicetable.c:168:
+ id->bInterfaceClass))$

WARNING: please, no spaces at the start of a line
#410: FILE: drivers/base/mod_devicetable.c:169:
+ return len;$

WARNING: please, no spaces at the start of a line
#413: FILE: drivers/base/mod_devicetable.c:172:
+ for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi;$

WARNING: suspect code indent for conditional statements (1, 1)
#413: FILE: drivers/base/mod_devicetable.c:172:
+ for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi;
[...]
+ clo = devlo & 0xf;

WARNING: please, no spaces at the start of a line
#414: FILE: drivers/base/mod_devicetable.c:173:
+ ndigits--) {$

WARNING: please, no spaces at the start of a line
#415: FILE: drivers/base/mod_devicetable.c:174:
+ clo = devlo & 0xf;$

WARNING: please, no spaces at the start of a line
#416: FILE: drivers/base/mod_devicetable.c:175:
+ chi = devhi & 0xf;$

WARNING: please, no spaces at the start of a line
#418: FILE: drivers/base/mod_devicetable.c:177:
+ if (chi > max)$

WARNING: suspect code indent for conditional statements (1, 1)
#418: FILE: drivers/base/mod_devicetable.c:177:
+ if (chi > max)
+ chi = max;

WARNING: please, no spaces at the start of a line
#419: FILE: drivers/base/mod_devicetable.c:178:
+ chi = max;$

WARNING: please, no spaces at the start of a line
#420: FILE: drivers/base/mod_devicetable.c:179:
+ devlo >>= 4;$

WARNING: please, no spaces at the start of a line
#421: FILE: drivers/base/mod_devicetable.c:180:
+ devhi >>= 4;$

WARNING: please, no spaces at the start of a line
#423: FILE: drivers/base/mod_devicetable.c:182:
+ if (devlo == devhi || !ndigits) {$

WARNING: suspect code indent for conditional statements (1, 1)
#423: FILE: drivers/base/mod_devicetable.c:182:
+ if (devlo == devhi || !ndigits) {
+ len += usb_id_to_modalias(id, devlo, ndigits, clo, chi,

WARNING: please, no spaces at the start of a line
#424: FILE: drivers/base/mod_devicetable.c:183:
+ len += usb_id_to_modalias(id, devlo, ndigits, clo, chi,$

WARNING: please, no spaces at the start of a line
#425: FILE: drivers/base/mod_devicetable.c:184:
+ max, mod_name, buf + len,$

WARNING: please, no spaces at the start of a line
#426: FILE: drivers/base/mod_devicetable.c:185:
+ count - len);$

WARNING: please, no spaces at the start of a line
#427: FILE: drivers/base/mod_devicetable.c:186:
+ break;$

WARNING: please, no spaces at the start of a line
#428: FILE: drivers/base/mod_devicetable.c:187:
+ }$

WARNING: please, no spaces at the start of a line
#430: FILE: drivers/base/mod_devicetable.c:189:
+ if (clo > 0x0)$

WARNING: suspect code indent for conditional statements (1, 1)
#430: FILE: drivers/base/mod_devicetable.c:189:
+ if (clo > 0x0)
+ len += usb_id_to_modalias(id,

WARNING: please, no spaces at the start of a line
#431: FILE: drivers/base/mod_devicetable.c:190:
+ len += usb_id_to_modalias(id,$

WARNING: please, no spaces at the start of a line
#432: FILE: drivers/base/mod_devicetable.c:191:
+ incbcd(&devlo, 1, max,$

ERROR: code indent should use tabs where possible
#433: FILE: drivers/base/mod_devicetable.c:192:
+ sizeof(id->bcdDevice_lo) * 2),$

WARNING: please, no spaces at the start of a line
#433: FILE: drivers/base/mod_devicetable.c:192:
+ sizeof(id->bcdDevice_lo) * 2),$

WARNING: please, no spaces at the start of a line
#434: FILE: drivers/base/mod_devicetable.c:193:
+ ndigits, clo, max, max, mod_name, buf + len,$

WARNING: please, no spaces at the start of a line
#435: FILE: drivers/base/mod_devicetable.c:194:
+ count - len);$

WARNING: please, no spaces at the start of a line
#437: FILE: drivers/base/mod_devicetable.c:196:
+ if (chi < max)$

WARNING: suspect code indent for conditional statements (1, 1)
#437: FILE: drivers/base/mod_devicetable.c:196:
+ if (chi < max)
+ len += usb_id_to_modalias(id,

WARNING: please, no spaces at the start of a line
#438: FILE: drivers/base/mod_devicetable.c:197:
+ len += usb_id_to_modalias(id,$

WARNING: please, no spaces at the start of a line
#439: FILE: drivers/base/mod_devicetable.c:198:
+ incbcd(&devhi, -1, max,$

ERROR: code indent should use tabs where possible
#440: FILE: drivers/base/mod_devicetable.c:199:
+ sizeof(id->bcdDevice_lo) * 2),$

WARNING: please, no spaces at the start of a line
#440: FILE: drivers/base/mod_devicetable.c:199:
+ sizeof(id->bcdDevice_lo) * 2),$

WARNING: please, no spaces at the start of a line
#441: FILE: drivers/base/mod_devicetable.c:200:
+ ndigits, 0x0, chi, max, mod_name, buf + len,$

WARNING: please, no spaces at the start of a line
#442: FILE: drivers/base/mod_devicetable.c:201:
+ count - len);$

WARNING: please, no spaces at the start of a line
#443: FILE: drivers/base/mod_devicetable.c:202:
+ }$

WARNING: please, no spaces at the start of a line
#444: FILE: drivers/base/mod_devicetable.c:203:
+ return len;$

WARNING: please, no spaces at the start of a line
#458: FILE: drivers/base/mod_devicetable.c:217:
+ size_t count)$

WARNING: please, no spaces at the start of a line
#460: FILE: drivers/base/mod_devicetable.c:219:
+ ssize_t len = 0;$

WARNING: please, no spaces at the start of a line
#461: FILE: drivers/base/mod_devicetable.c:220:
+ const struct usb_device_id *id;$

WARNING: please, no spaces at the start of a line
#462: FILE: drivers/base/mod_devicetable.c:221:
+ const char *mod_name;$

WARNING: please, no spaces at the start of a line
#464: FILE: drivers/base/mod_devicetable.c:223:
+ if (drv->bus != &usb_bus_type)$

WARNING: suspect code indent for conditional statements (1, 1)
#464: FILE: drivers/base/mod_devicetable.c:223:
+ if (drv->bus != &usb_bus_type)
+ return -EINVAL;

WARNING: please, no spaces at the start of a line
#465: FILE: drivers/base/mod_devicetable.c:224:
+ return -EINVAL;$

WARNING: please, no spaces at the start of a line
#467: FILE: drivers/base/mod_devicetable.c:226:
+ if (drv->owner)$

WARNING: suspect code indent for conditional statements (1, 1)
#467: FILE: drivers/base/mod_devicetable.c:226:
+ if (drv->owner)
+ mod_name = drv->owner->name;

WARNING: please, no spaces at the start of a line
#468: FILE: drivers/base/mod_devicetable.c:227:
+ mod_name = drv->owner->name;$

WARNING: please, no spaces at the start of a line
#469: FILE: drivers/base/mod_devicetable.c:228:
+ else$

WARNING: suspect code indent for conditional statements (1, 1)
#469: FILE: drivers/base/mod_devicetable.c:228:
+ else
+ mod_name = drv->mod_name;

WARNING: please, no spaces at the start of a line
#470: FILE: drivers/base/mod_devicetable.c:229:
+ mod_name = drv->mod_name;$

WARNING: please, no spaces at the start of a line
#472: FILE: drivers/base/mod_devicetable.c:231:
+ if (is_usb_device_driver(drv))$

WARNING: suspect code indent for conditional statements (1, 1)
#472: FILE: drivers/base/mod_devicetable.c:231:
+ if (is_usb_device_driver(drv))
+ id = to_usb_device_driver(drv)->id_table;

WARNING: please, no spaces at the start of a line
#473: FILE: drivers/base/mod_devicetable.c:232:
+ id = to_usb_device_driver(drv)->id_table;$

WARNING: please, no spaces at the start of a line
#474: FILE: drivers/base/mod_devicetable.c:233:
+ else$

WARNING: suspect code indent for conditional statements (1, 1)
#474: FILE: drivers/base/mod_devicetable.c:233:
+ else
+ id = to_usb_driver(drv)->id_table;

WARNING: please, no spaces at the start of a line
#475: FILE: drivers/base/mod_devicetable.c:234:
+ id = to_usb_driver(drv)->id_table;$

WARNING: please, no spaces at the start of a line
#476: FILE: drivers/base/mod_devicetable.c:235:
+ if (!id)$

WARNING: suspect code indent for conditional statements (1, 1)
#476: FILE: drivers/base/mod_devicetable.c:235:
+ if (!id)
+ return len;

WARNING: please, no spaces at the start of a line
#477: FILE: drivers/base/mod_devicetable.c:236:
+ return len;$

WARNING: please, no spaces at the start of a line
#479: FILE: drivers/base/mod_devicetable.c:238:
+ for (; id->match_flags; id++) {$

WARNING: suspect code indent for conditional statements (1, 1)
#479: FILE: drivers/base/mod_devicetable.c:238:
+ for (; id->match_flags; id++) {
+ len += usb_id_to_modalias_multi(id, mod_name, buf + len,

WARNING: please, no spaces at the start of a line
#480: FILE: drivers/base/mod_devicetable.c:239:
+ len += usb_id_to_modalias_multi(id, mod_name, buf + len,$

WARNING: please, no spaces at the start of a line
#481: FILE: drivers/base/mod_devicetable.c:240:
+ count - len);$

WARNING: please, no spaces at the start of a line
#482: FILE: drivers/base/mod_devicetable.c:241:
+ }$

WARNING: please, no spaces at the start of a line
#483: FILE: drivers/base/mod_devicetable.c:242:
+ return len;$

WARNING: please, no spaces at the start of a line
#501: FILE: drivers/usb/core/driver.c:2034:
+ .drv_to_modalias = usb_drv_to_modalias,$

WARNING: please, no spaces at the start of a line
#522: FILE: include/linux/device/bus.h:114:
+ ssize_t (*drv_to_modalias)(struct device_driver *drv, char *buf,$

WARNING: please, no spaces at the start of a line
#523: FILE: include/linux/device/bus.h:115:
+ size_t count);$

WARNING: please, no spaces at the start of a line
#544: FILE: include/linux/module.h:51:
+ struct bin_attribute modalias_attr;$

ERROR: patch seems to be corrupt (line wrapped?)
#553: FILE: kernel/module/internal.h:258:
*mod, const struct load_info *info

WARNING: please, no spaces at the start of a line
#590: FILE: kernel/module/sysfs.c:249:
+ struct module_kobject *mk;$

WARNING: please, no spaces at the start of a line
#591: FILE: kernel/module/sysfs.c:250:
+ char *buf;$

WARNING: please, no spaces at the start of a line
#592: FILE: kernel/module/sysfs.c:251:
+ size_t count;$

WARNING: please, no spaces at the start of a line
#593: FILE: kernel/module/sysfs.c:252:
+ ssize_t len;$

WARNING: please, no spaces at the start of a line
#598: FILE: kernel/module/sysfs.c:257:
+ struct modalias_bus_print_state *s = p;$

WARNING: please, no spaces at the start of a line
#599: FILE: kernel/module/sysfs.c:258:
+ struct module_kobject *mk = s->mk;$

WARNING: please, no spaces at the start of a line
#600: FILE: kernel/module/sysfs.c:259:
+ ssize_t len;$

WARNING: please, no spaces at the start of a line
#602: FILE: kernel/module/sysfs.c:261:
+ if (mk->mod) {$

WARNING: suspect code indent for conditional statements (1, 1)
#602: FILE: kernel/module/sysfs.c:261:
+ if (mk->mod) {
+ if (mk->mod != drv->owner)

WARNING: please, no spaces at the start of a line
#603: FILE: kernel/module/sysfs.c:262:
+ if (mk->mod != drv->owner)$

WARNING: suspect code indent for conditional statements (1, 1)
#603: FILE: kernel/module/sysfs.c:262:
+ if (mk->mod != drv->owner)
+ return 0;

WARNING: please, no spaces at the start of a line
#604: FILE: kernel/module/sysfs.c:263:
+ return 0;$

WARNING: please, no spaces at the start of a line
#605: FILE: kernel/module/sysfs.c:264:
+ } else if (!mk->kobj.name || !drv->mod_name ||$

WARNING: suspect code indent for conditional statements (1, 1)
#605: FILE: kernel/module/sysfs.c:264:
+ } else if (!mk->kobj.name || !drv->mod_name ||
[...]
+ return 0;

WARNING: please, no spaces at the start of a line
#606: FILE: kernel/module/sysfs.c:265:
+ strcmp(mk->kobj.name, drv->mod_name))$

WARNING: please, no spaces at the start of a line
#607: FILE: kernel/module/sysfs.c:266:
+ return 0;$

WARNING: please, no spaces at the start of a line
#609: FILE: kernel/module/sysfs.c:268:
+ if (drv->bus && drv->bus->drv_to_modalias) {$

WARNING: suspect code indent for conditional statements (1, 1)
#609: FILE: kernel/module/sysfs.c:268:
+ if (drv->bus && drv->bus->drv_to_modalias) {
+ len = drv->bus->drv_to_modalias(drv, s->buf + s->len,

WARNING: please, no spaces at the start of a line
#610: FILE: kernel/module/sysfs.c:269:
+ len = drv->bus->drv_to_modalias(drv, s->buf + s->len,$

WARNING: please, no spaces at the start of a line
#611: FILE: kernel/module/sysfs.c:270:
+ s->count - s->len);$

WARNING: please, no spaces at the start of a line
#612: FILE: kernel/module/sysfs.c:271:
+ if (len < 0)$

WARNING: suspect code indent for conditional statements (1, 1)
#612: FILE: kernel/module/sysfs.c:271:
+ if (len < 0)
+ return len;

WARNING: please, no spaces at the start of a line
#613: FILE: kernel/module/sysfs.c:272:
+ return len;$

WARNING: please, no spaces at the start of a line
#614: FILE: kernel/module/sysfs.c:273:
+ s->len += len;$

WARNING: please, no spaces at the start of a line
#615: FILE: kernel/module/sysfs.c:274:
+ }$

WARNING: please, no spaces at the start of a line
#617: FILE: kernel/module/sysfs.c:276:
+ s->len += scnprintf(&s->buf[s->len], s->count - s->len, "driver %s\n",$

WARNING: please, no spaces at the start of a line
#618: FILE: kernel/module/sysfs.c:277:
+ drv->name);$

WARNING: please, no spaces at the start of a line
#619: FILE: kernel/module/sysfs.c:278:
+ return 0;$

WARNING: please, no spaces at the start of a line
#624: FILE: kernel/module/sysfs.c:283:
+ return bus_for_each_drv(type, NULL, p, print_modalias_for_drv);$

WARNING: please, no spaces at the start of a line
#628: FILE: kernel/module/sysfs.c:287:
+ struct bin_attribute *bin_attr,$

WARNING: please, no spaces at the start of a line
#629: FILE: kernel/module/sysfs.c:288:
+ char *buf, loff_t pos, size_t count)$

WARNING: please, no spaces at the start of a line
#631: FILE: kernel/module/sysfs.c:290:
+ struct module_kobject *mk = container_of(kobj, struct module_kobject,$

WARNING: please, no spaces at the start of a line
#632: FILE: kernel/module/sysfs.c:291:
+ kobj);$

WARNING: please, no spaces at the start of a line
#633: FILE: kernel/module/sysfs.c:292:
+ struct modalias_bus_print_state state = {mk, buf, count, 0};$

WARNING: please, no spaces at the start of a line
#634: FILE: kernel/module/sysfs.c:293:
+ int error = 0;$

WARNING: please, no spaces at the start of a line
#636: FILE: kernel/module/sysfs.c:295:
+ if (pos != 0)$

WARNING: suspect code indent for conditional statements (1, 1)
#636: FILE: kernel/module/sysfs.c:295:
+ if (pos != 0)
+ return -EINVAL;

WARNING: please, no spaces at the start of a line
#637: FILE: kernel/module/sysfs.c:296:
+ return -EINVAL;$

WARNING: please, no spaces at the start of a line
#639: FILE: kernel/module/sysfs.c:298:
+ error = bus_for_each(&state, print_modalias_for_bus);$

WARNING: please, no spaces at the start of a line
#640: FILE: kernel/module/sysfs.c:299:
+ if (error)$

WARNING: suspect code indent for conditional statements (1, 1)
#640: FILE: kernel/module/sysfs.c:299:
+ if (error)
+ return error;

WARNING: please, no spaces at the start of a line
#641: FILE: kernel/module/sysfs.c:300:
+ return error;$

WARNING: please, no spaces at the start of a line
#643: FILE: kernel/module/sysfs.c:302:
+ if (mk->mod)$

WARNING: suspect code indent for conditional statements (1, 1)
#643: FILE: kernel/module/sysfs.c:302:
+ if (mk->mod)
+ state.len += scnprintf(&buf[state.len], count - state.len,

WARNING: please, no spaces at the start of a line
#644: FILE: kernel/module/sysfs.c:303:
+ state.len += scnprintf(&buf[state.len], count - state.len,$

ERROR: code indent should use tabs where possible
#645: FILE: kernel/module/sysfs.c:304:
+ "modalias %s %s\n", kobject_name(kobj),$

WARNING: please, no spaces at the start of a line
#645: FILE: kernel/module/sysfs.c:304:
+ "modalias %s %s\n", kobject_name(kobj),$

ERROR: code indent should use tabs where possible
#646: FILE: kernel/module/sysfs.c:305:
+ mk->mod->name);$

WARNING: please, no spaces at the start of a line
#646: FILE: kernel/module/sysfs.c:305:
+ mk->mod->name);$

WARNING: please, no spaces at the start of a line
#647: FILE: kernel/module/sysfs.c:306:
+ else$

WARNING: suspect code indent for conditional statements (1, 1)
#647: FILE: kernel/module/sysfs.c:306:
+ else
+ state.len += scnprintf(&buf[state.len], count - state.len,

WARNING: please, no spaces at the start of a line
#648: FILE: kernel/module/sysfs.c:307:
+ state.len += scnprintf(&buf[state.len], count - state.len,$

ERROR: code indent should use tabs where possible
#649: FILE: kernel/module/sysfs.c:308:
+ "modalias %s NULL\n",$

WARNING: please, no spaces at the start of a line
#649: FILE: kernel/module/sysfs.c:308:
+ "modalias %s NULL\n",$

ERROR: code indent should use tabs where possible
#650: FILE: kernel/module/sysfs.c:309:
+ kobject_name(kobj));$

WARNING: please, no spaces at the start of a line
#650: FILE: kernel/module/sysfs.c:309:
+ kobject_name(kobj));$

WARNING: Block comments should align the * on each line
#653: FILE: kernel/module/sysfs.c:312:
+ /*
+ * The caller checked the pos and count against our size.

WARNING: please, no spaces at the start of a line
#655: FILE: kernel/module/sysfs.c:314:
+ return state.len;$

WARNING: please, no spaces at the start of a line
#665: FILE: kernel/module/sysfs.c:324:
+ sysfs_bin_attr_init(&mk->modalias_attr);$

WARNING: please, no spaces at the start of a line
#666: FILE: kernel/module/sysfs.c:325:
+ mk->modalias_attr.attr.name = "modalias";$

WARNING: please, no spaces at the start of a line
#667: FILE: kernel/module/sysfs.c:326:
+ mk->modalias_attr.attr.mode = 0444;$

WARNING: please, no spaces at the start of a line
#668: FILE: kernel/module/sysfs.c:327:
+ mk->modalias_attr.read = module_modalias_read;$

WARNING: please, no spaces at the start of a line
#669: FILE: kernel/module/sysfs.c:328:
+ if (sysfs_create_bin_file(&mk->kobj, &mk->modalias_attr)) {$

WARNING: suspect code indent for conditional statements (1, 1)
#669: FILE: kernel/module/sysfs.c:328:
+ if (sysfs_create_bin_file(&mk->kobj, &mk->modalias_attr)) {
[...]
+ return;

WARNING: Block comments should align the * on each line
#671: FILE: kernel/module/sysfs.c:330:
+ /* We shouldn't ignore the return type, but there is nothing to
+ * do.

WARNING: please, no spaces at the start of a line
#673: FILE: kernel/module/sysfs.c:332:
+ return;$

WARNING: please, no spaces at the start of a line
#674: FILE: kernel/module/sysfs.c:333:
+ }$

WARNING: please, no spaces at the start of a line
#679: FILE: kernel/module/sysfs.c:338:
+ sysfs_remove_bin_file(&mk->kobj, &mk->modalias_attr);$

WARNING: please, no spaces at the start of a line
#689: FILE: kernel/module/sysfs.c:499:
+ add_modalias_attr(&mod->mkobj);$

WARNING: please, no spaces at the start of a line
#697: FILE: kernel/module/sysfs.c:517:
+ remove_modalias_attr(&mod->mkobj);$

WARNING: please, no spaces at the start of a line
#717: FILE: kernel/params.c:819:
+ add_modalias_attr(mk);$

total: 9 errors, 284 warnings, 512 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or
--fix-inplace.

NOTE: Whitespace errors detected.
You may wish to use scripts/cleanpatch or scripts/cleanfile

/home/chleroy/Téléchargements/Patch-to-exposing-modalias-es-for-built-in-kernel-modules-USB.patch
has style problems, please review.

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.


---
Christophe

2022-11-11 16:15:01

by Allen Webb

[permalink] [raw]
Subject: [PATCH] modules: add modalias file to sysfs for modules.

USB devices support the authorized attribute which can be used by
user-space to implement trust-based systems for enabling USB devices. It
would be helpful when building these systems to be able to know in
advance which kernel drivers (or modules) are reachable from a
particular USB device.

This information is readily available for external modules in
modules.alias. However, builtin kernel modules are not covered. This
patch adds a sys-fs attribute to both builtin and loaded modules
exposing the matching rules in the modalias format for integration
with tools like USBGuard.

Signed-off-by: Allen Webb <[email protected]>
---
drivers/base/Makefile | 2 +-
drivers/base/base.h | 8 ++
drivers/base/bus.c | 42 ++++++
drivers/base/mod_devicetable.c | 241 +++++++++++++++++++++++++++++++++
drivers/usb/core/driver.c | 2 +
include/linux/device/bus.h | 8 ++
include/linux/module.h | 1 +
kernel/module/internal.h | 2 +
kernel/module/sysfs.c | 100 ++++++++++++++
kernel/params.c | 2 +
10 files changed, 407 insertions(+), 1 deletion(-)
create mode 100644 drivers/base/mod_devicetable.c

diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 83217d243c25b..924d46ae987f4 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -15,7 +15,7 @@ obj-y += firmware_loader/
obj-$(CONFIG_NUMA) += node.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
ifeq ($(CONFIG_SYSFS),y)
-obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_MODULES) += mod_devicetable.o module.o
endif
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
obj-$(CONFIG_REGMAP) += regmap/
diff --git a/drivers/base/base.h b/drivers/base/base.h
index b3a43a164dcd1..7ac5f7a547be8 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -175,6 +175,14 @@ static inline void module_add_driver(struct module *mod,
static inline void module_remove_driver(struct device_driver *drv) { }
#endif

+#if defined(CONFIG_SYSFS)
+ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count);
+#else
+static inline ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count) { return -ENOSUP; }
+#endif
+
#ifdef CONFIG_DEVTMPFS
extern int devtmpfs_init(void);
#else
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7ca47e5b3c1f4..4e0c5925545e5 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -178,6 +178,48 @@ static const struct kset_uevent_ops bus_uevent_ops = {

static struct kset *bus_kset;

+/**
+ * bus_for_each - bus iterator.
+ * @start: bus to start iterating from.
+ * @data: data for the callback.
+ * @fn: function to be called for each device.
+ *
+ * Iterate over list of buses, and call @fn for each,
+ * passing it @data. If @start is not NULL, we use that bus to
+ * begin iterating from.
+ *
+ * We check the return of @fn each time. If it returns anything
+ * other than 0, we break out and return that value.
+ *
+ * NOTE: The bus that returns a non-zero value is not retained
+ * in any way, nor is its refcount incremented. If the caller needs
+ * to retain this data, it should do so, and increment the reference
+ * count in the supplied callback.
+ */
+int bus_for_each(void *data, int (*fn)(struct bus_type *, void *))
+{
+ int error = 0;
+ struct bus_type *bus;
+ struct subsys_private *bus_prv;
+ struct kset *subsys;
+ struct kobject *k;
+
+ spin_lock(&bus_kset->list_lock);
+
+ list_for_each_entry(k, &bus_kset->list, entry) {
+ subsys = container_of(k, struct kset, kobj);
+ bus_prv = container_of(subsys, struct subsys_private, subsys);
+ bus = bus_prv->bus;
+ error = fn(bus, data);
+ if (error)
+ break;
+ }
+
+ spin_unlock(&bus_kset->list_lock);
+ return error;
+}
+EXPORT_SYMBOL_GPL(bus_for_each);
+
/* Manually detach a device from its associated driver. */
static ssize_t unbind_store(struct device_driver *drv, const char *buf,
size_t count)
diff --git a/drivers/base/mod_devicetable.c b/drivers/base/mod_devicetable.c
new file mode 100644
index 0000000000000..da8d524cdf57a
--- /dev/null
+++ b/drivers/base/mod_devicetable.c
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mod_devicetable.c - helpers for displaying modaliases through sysfs.
+ *
+ * This borrows a lot from file2alias.c
+ */
+
+#include <linux/device/bus.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+
+#include "../usb/core/usb.h"
+
+#define ADD(buf, count, len, sep, cond, field) \
+do { \
+ if (cond) \
+ (len) += scnprintf(&(buf)[len], \
+ (count) - (len), \
+ sizeof(field) == 1 ? (sep "%02X") : \
+ sizeof(field) == 2 ? (sep "%04X") : \
+ sizeof(field) == 4 ? (sep "%08X") : "", \
+ (field)); \
+ else \
+ (len) += scnprintf(&(buf)[len], (count) - (len), (sep "*")); \
+} while (0)
+
+/* USB related modaliases can be split because of device number matching, so
+ * this function handles individual modaliases for one segment of the range.
+ *
+ *
+ */
+static ssize_t usb_id_to_modalias(const struct usb_device_id *id,
+ unsigned int bcdDevice_initial,
+ int bcdDevice_initial_digits,
+ unsigned char range_lo,
+ unsigned char range_hi,
+ unsigned char max, const char *mod_name,
+ char *buf, size_t count)
+{
+ ssize_t len = 0;
+
+ ADD(buf, count, len, "alias usb:v",
+ id->match_flags & USB_DEVICE_ID_MATCH_VENDOR, id->idVendor);
+ ADD(buf, count, len, "p", id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT,
+ id->idProduct);
+
+ len += scnprintf(&buf[len], count - len, "d");
+ if (bcdDevice_initial_digits)
+ len += scnprintf(&buf[len], count - len, "%0*X",
+ bcdDevice_initial_digits, bcdDevice_initial);
+ if (range_lo == range_hi) {
+ len += scnprintf(&buf[len], count - len, "%X", range_lo);
+ } else if (range_lo > 0 || range_hi < max) {
+ if (range_lo > 0x9 || range_hi < 0xA) {
+ len += scnprintf(&buf[len], count - len, "[%X-%X]",
+ range_lo, range_hi);
+ } else {
+ len += scnprintf(&buf[len], count - len,
+ range_lo < 0x9 ? "[%X-9" : "[%X",
+ range_lo);
+ len += scnprintf(&buf[len], count - len,
+ range_hi > 0xA ? "A-%X]" : "%X]",
+ range_hi);
+ }
+ }
+ if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
+ len += scnprintf(&buf[len], count - len, "*");
+
+ ADD(buf, count, len, "dc",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS, id->bDeviceClass);
+ ADD(buf, count, len, "dsc",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+ id->bDeviceSubClass);
+ ADD(buf, count, len, "dp",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ id->bDeviceProtocol);
+ ADD(buf, count, len, "ic",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS,
+ id->bInterfaceClass);
+ ADD(buf, count, len, "isc",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ id->bInterfaceSubClass);
+ ADD(buf, count, len, "ip",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+ id->bInterfaceProtocol);
+ ADD(buf, count, len, "in",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER,
+ id->bInterfaceNumber);
+
+ len += scnprintf(&buf[len], count - len, " %s\n", mod_name);
+ return len;
+}
+
+/* Handles increment/decrement of BCD formatted integers */
+/* Returns the previous value, so it works like i++ or i-- */
+static unsigned int incbcd(unsigned int *bcd,
+ int inc,
+ unsigned char max,
+ size_t chars)
+{
+ unsigned int init = *bcd, i, j;
+ unsigned long long c, dec = 0;
+
+ /* If bcd is not in BCD format, just increment */
+ if (max > 0x9) {
+ *bcd += inc;
+ return init;
+ }
+
+ /* Convert BCD to Decimal */
+ for (i = 0 ; i < chars ; i++) {
+ c = (*bcd >> (i << 2)) & 0xf;
+ c = c > 9 ? 9 : c; /* force to bcd just in case */
+ for (j = 0 ; j < i ; j++)
+ c = c * 10;
+ dec += c;
+ }
+
+ /* Do our increment/decrement */
+ dec += inc;
+ *bcd = 0;
+
+ /* Convert back to BCD */
+ for (i = 0 ; i < chars ; i++) {
+ for (c = 1, j = 0 ; j < i ; j++)
+ c = c * 10;
+ c = (dec / c) % 10;
+ *bcd += c << (i << 2);
+ }
+ return init;
+}
+
+/* Print the modaliases for the specified struct usb_device_id.
+ */
+static ssize_t usb_id_to_modalias_multi(const struct usb_device_id *id,
+ const char *mod_name, char *buf,
+ size_t count)
+{
+ ssize_t len = 0;
+ unsigned int devlo, devhi;
+ unsigned char chi, clo, max;
+ int ndigits;
+
+ devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
+ id->bcdDevice_lo : 0x0U;
+ devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
+ id->bcdDevice_hi : ~0x0U;
+
+ /* Figure out if this entry is in bcd or hex format */
+ max = 0x9; /* Default to decimal format */
+ for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
+ clo = (devlo >> (ndigits << 2)) & 0xf;
+ chi = ((devhi > 0x9999 ? 0x9999 : devhi) >>
+ (ndigits << 2)) & 0xf;
+ if (clo > max || chi > max) {
+ max = 0xf;
+ break;
+ }
+ }
+
+ /*
+ * Some modules (visor) have empty slots as placeholder for
+ * run-time specification that results in catch-all alias
+ */
+ if (!(id->idVendor || id->idProduct || id->bDeviceClass ||
+ id->bInterfaceClass))
+ return len;
+
+ /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
+ for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi;
+ ndigits--) {
+ clo = devlo & 0xf;
+ chi = devhi & 0xf;
+ /* If we are in bcd mode, truncate if necessary */
+ if (chi > max)
+ chi = max;
+ devlo >>= 4;
+ devhi >>= 4;
+
+ if (devlo == devhi || !ndigits) {
+ len += usb_id_to_modalias(id, devlo, ndigits, clo, chi,
+ max, mod_name, buf + len,
+ count - len);
+ break;
+ }
+
+ if (clo > 0x0)
+ len += usb_id_to_modalias(id,
+ incbcd(&devlo, 1, max,
+ sizeof(id->bcdDevice_lo) * 2),
+ ndigits, clo, max, max, mod_name, buf + len,
+ count - len);
+
+ if (chi < max)
+ len += usb_id_to_modalias(id,
+ incbcd(&devhi, -1, max,
+ sizeof(id->bcdDevice_lo) * 2),
+ ndigits, 0x0, chi, max, mod_name, buf + len,
+ count - len);
+ }
+ return len;
+}
+
+/* Print the modaliases for the given driver assumed to be an usb_driver or
+ * usb_device_driver.
+ *
+ * "alias" is prepended and the module name is appended to each modalias to
+ * match the format in modules.aliases.
+ *
+ * The modaliases will be written out to @buf with @count being the maximum
+ * bytes to write. The return value is a negative errno on error or the number
+ * of bytes written to @buf on success.
+ */
+ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count)
+{
+ ssize_t len = 0;
+ const struct usb_device_id *id;
+ const char *mod_name;
+
+ if (drv->bus != &usb_bus_type)
+ return -EINVAL;
+
+ if (drv->owner)
+ mod_name = drv->owner->name;
+ else
+ mod_name = drv->mod_name;
+
+ if (is_usb_device_driver(drv))
+ id = to_usb_device_driver(drv)->id_table;
+ else
+ id = to_usb_driver(drv)->id_table;
+ if (!id)
+ return len;
+
+ for (; id->match_flags; id++) {
+ len += usb_id_to_modalias_multi(id, mod_name, buf + len,
+ count - len);
+ }
+ return len;
+}
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7e7e119c253fb..fdbc197b64c9c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -32,6 +32,7 @@
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h>

+#include "../../base/base.h"
#include "usb.h"


@@ -2030,4 +2031,5 @@ struct bus_type usb_bus_type = {
.match = usb_device_match,
.uevent = usb_uevent,
.need_parent_lock = true,
+ .drv_to_modalias = usb_drv_to_modalias,
};
diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h
index d8b29ccd07e56..cce0bedec63d9 100644
--- a/include/linux/device/bus.h
+++ b/include/linux/device/bus.h
@@ -61,6 +61,10 @@ struct fwnode_handle;
* this bus.
* @dma_cleanup: Called to cleanup DMA configuration on a device on
* this bus.
+ * @drv_to_modalias: Called to convert the matching IDs in a
+ * struct device_driver to their corresponding modaliases.
+ * Note that the struct device_driver is expected to belong
+ * to this bus.
* @pm: Power management operations of this bus, callback the specific
* device driver's pm-ops.
* @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU
@@ -107,6 +111,9 @@ struct bus_type {
int (*dma_configure)(struct device *dev);
void (*dma_cleanup)(struct device *dev);

+ ssize_t (*drv_to_modalias)(struct device_driver *drv, char *buf,
+ size_t count);
+
const struct dev_pm_ops *pm;

const struct iommu_ops *iommu_ops;
@@ -161,6 +168,7 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter,
struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
void subsys_dev_iter_exit(struct subsys_dev_iter *iter);

+int bus_for_each(void *data, int (*fn)(struct bus_type *, void *));
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
int (*fn)(struct device *dev, void *data));
struct device *bus_find_device(struct bus_type *bus, struct device *start,
diff --git a/include/linux/module.h b/include/linux/module.h
index 518296ea7f73a..68fe7bfc38683 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -48,6 +48,7 @@ struct module_kobject {
struct kobject *drivers_dir;
struct module_param_attrs *mp;
struct completion *kobj_completion;
+ struct bin_attribute modalias_attr;
} __randomize_layout;

struct module_attribute {
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 680d980a4fb29..63b794cd65df2 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -259,11 +259,13 @@ static inline void add_kallsyms(struct module *mod, const struct load_info *info
#endif /* CONFIG_KALLSYMS */

#ifdef CONFIG_SYSFS
+void add_modalias_attr(struct module_kobject *mk);
int mod_sysfs_setup(struct module *mod, const struct load_info *info,
struct kernel_param *kparam, unsigned int num_params);
void mod_sysfs_teardown(struct module *mod);
void init_param_lock(struct module *mod);
#else /* !CONFIG_SYSFS */
+static inline void add_modalias_attr(struct module_kobject *mk) {}
static inline int mod_sysfs_setup(struct module *mod,
const struct load_info *info,
struct kernel_param *kparam,
diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index ce68f821dcd12..e80bfa4639765 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -5,6 +5,8 @@
* Copyright (C) 2008 Rusty Russell
*/

+#include <linux/device/bus.h>
+#include <linux/device/driver.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
@@ -240,6 +242,102 @@ static inline void add_notes_attrs(struct module *mod, const struct load_info *i
static inline void remove_notes_attrs(struct module *mod) { }
#endif /* CONFIG_KALLSYMS */

+/* Track of the buffer and module identity in callbacks when walking the list of
+ * drivers for each bus.
+ */
+struct modalias_bus_print_state {
+ struct module_kobject *mk;
+ char *buf;
+ size_t count;
+ ssize_t len;
+};
+
+static int print_modalias_for_drv(struct device_driver *drv, void *p)
+{
+ struct modalias_bus_print_state *s = p;
+ struct module_kobject *mk = s->mk;
+ ssize_t len;
+ /* Skip drivers that do not match this module. */
+ if (mk->mod) {
+ if (mk->mod != drv->owner)
+ return 0;
+ } else if (!mk->kobj.name || !drv->mod_name ||
+ strcmp(mk->kobj.name, drv->mod_name))
+ return 0;
+
+ if (drv->bus && drv->bus->drv_to_modalias) {
+ len = drv->bus->drv_to_modalias(drv, s->buf + s->len,
+ s->count - s->len);
+ if (len < 0)
+ return len;
+ s->len += len;
+ }
+
+ s->len += scnprintf(&s->buf[s->len], s->count - s->len, "driver %s\n",
+ drv->name);
+ return 0;
+}
+
+static int print_modalias_for_bus(struct bus_type *type, void *p)
+{
+ return bus_for_each_drv(type, NULL, p, print_modalias_for_drv);
+}
+
+static ssize_t module_modalias_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct module_kobject *mk = container_of(kobj, struct module_kobject,
+ kobj);
+ struct modalias_bus_print_state state = {mk, buf, count, 0};
+ int error = 0;
+
+ if (pos != 0)
+ return -EINVAL;
+
+ error = bus_for_each(&state, print_modalias_for_bus);
+ if (error)
+ return error;
+
+ if (mk->mod)
+ state.len += scnprintf(&buf[state.len], count - state.len,
+ "modalias %s %s\n", kobject_name(kobj),
+ mk->mod->name);
+ else
+ state.len += scnprintf(&buf[state.len], count - state.len,
+ "modalias %s NULL\n",
+ kobject_name(kobj));
+
+ /*
+ * The caller checked the pos and count against our size.
+ */
+ return state.len;
+}
+
+/* Used in kernel/params.c for builtin modules.
+ *
+ * `struct module_kobject` is used instead of `struct module` because for
+ * builtin modules, the `struct module` is not available when this is called.
+ */
+void add_modalias_attr(struct module_kobject *mk)
+{
+ sysfs_bin_attr_init(&mk->modalias_attr);
+ mk->modalias_attr.attr.name = "modalias";
+ mk->modalias_attr.attr.mode = 0444;
+ mk->modalias_attr.read = module_modalias_read;
+ if (sysfs_create_bin_file(&mk->kobj, &mk->modalias_attr)) {
+ /* We shouldn't ignore the return type, but there is nothing to
+ * do.
+ */
+ return;
+ }
+}
+
+static void remove_modalias_attr(struct module_kobject *mk)
+{
+ sysfs_remove_bin_file(&mk->kobj, &mk->modalias_attr);
+}
+
static void del_usage_links(struct module *mod)
{
#ifdef CONFIG_MODULE_UNLOAD
@@ -398,6 +496,7 @@ int mod_sysfs_setup(struct module *mod,

add_sect_attrs(mod, info);
add_notes_attrs(mod, info);
+ add_modalias_attr(&mod->mkobj);

return 0;

@@ -415,6 +514,7 @@ int mod_sysfs_setup(struct module *mod,

static void mod_sysfs_fini(struct module *mod)
{
+ remove_modalias_attr(&mod->mkobj);
remove_notes_attrs(mod);
remove_sect_attrs(mod);
mod_kobject_put(mod);
diff --git a/kernel/params.c b/kernel/params.c
index 5b92310425c50..111024196361a 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/security.h>
+#include "module/internal.h"

#ifdef CONFIG_SYSFS
/* Protects all built-in parameters, modules use their own param_lock */
@@ -815,6 +816,7 @@ static void __init kernel_add_sysfs_param(const char *name,
BUG_ON(err);
kobject_uevent(&mk->kobj, KOBJ_ADD);
kobject_put(&mk->kobj);
+ add_modalias_attr(mk);
}

/*
--
2.37.3


2022-11-11 18:36:46

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
> USB devices support the authorized attribute which can be used by
> user-space to implement trust-based systems for enabling USB devices. It
> would be helpful when building these systems to be able to know in
> advance which kernel drivers (or modules) are reachable from a
> particular USB device.
>
> This information is readily available for external modules in
> modules.alias. However, builtin kernel modules are not covered. This
> patch adds a sys-fs attribute to both builtin and loaded modules
> exposing the matching rules in the modalias format for integration
> with tools like USBGuard.
>
> Signed-off-by: Allen Webb <[email protected]>

Thanks for the patch Allen!

I'd rather have something generic though, and it would seem kmod [0] already
does this, have you seen the kmod support for builtin.alias.bin

Can't that be used?

[0] git://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git

Luis

2022-11-11 21:09:17

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

Hi Allen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on driver-core/driver-core-testing]
[also build test ERROR on driver-core/driver-core-next driver-core/driver-core-linus mcgrof/modules-next usb/usb-testing usb/usb-next usb/usb-linus linus/master v6.1-rc4 next-20221111]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221111-233314
patch link: https://lore.kernel.org/r/20221111152852.2837363-1-allenwebb%40google.com
patch subject: [PATCH] modules: add modalias file to sysfs for modules.
config: um-i386_defconfig
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/6dda398b2e01f44f8fb5f03116ba5e6143360140
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221111-233314
git checkout 6dda398b2e01f44f8fb5f03116ba5e6143360140
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=um SUBARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

/usr/bin/ld: warning: arch/x86/um/checksum_32.o: missing .note.GNU-stack section implies executable stack
/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
/usr/bin/ld: warning: .tmp_vmlinux.kallsyms1 has a LOAD segment with RWX permissions
/usr/bin/ld: drivers/base/mod_devicetable.o: in function `usb_drv_to_modalias':
>> drivers/base/mod_devicetable.c:221: undefined reference to `usb_bus_type'
>> collect2: error: ld returned 1 exit status


vim +221 drivers/base/mod_devicetable.c

203
204 /* Print the modaliases for the given driver assumed to be an usb_driver or
205 * usb_device_driver.
206 *
207 * "alias" is prepended and the module name is appended to each modalias to
208 * match the format in modules.aliases.
209 *
210 * The modaliases will be written out to @buf with @count being the maximum
211 * bytes to write. The return value is a negative errno on error or the number
212 * of bytes written to @buf on success.
213 */
214 ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
215 size_t count)
216 {
217 ssize_t len = 0;
218 const struct usb_device_id *id;
219 const char *mod_name;
220
> 221 if (drv->bus != &usb_bus_type)

--
0-DAY CI Kernel Test Service
https://01.org/lkp


Attachments:
(No filename) (2.91 kB)
config (43.08 kB)
Download all attachments

2022-11-11 23:17:24

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

Hi Allen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on driver-core/driver-core-testing]
[also build test ERROR on driver-core/driver-core-next driver-core/driver-core-linus mcgrof/modules-next usb/usb-testing usb/usb-next usb/usb-linus linus/master v6.1-rc4 next-20221111]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221111-233314
patch link: https://lore.kernel.org/r/20221111152852.2837363-1-allenwebb%40google.com
patch subject: [PATCH] modules: add modalias file to sysfs for modules.
config: m68k-m5208evb_defconfig
compiler: m68k-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/6dda398b2e01f44f8fb5f03116ba5e6143360140
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221111-233314
git checkout 6dda398b2e01f44f8fb5f03116ba5e6143360140
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

In file included from drivers/base/core.c:35:
drivers/base/base.h: In function 'usb_drv_to_modalias':
>> drivers/base/base.h:180:67: error: 'ENOSUP' undeclared (first use in this function); did you mean 'ENOSYS'?
180 | size_t count) { return -ENOSUP; }
| ^~~~~~
| ENOSYS
drivers/base/base.h:180:67: note: each undeclared identifier is reported only once for each function it appears in


vim +180 drivers/base/base.h

174
175 #if defined(CONFIG_SYSFS)
176 ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
177 size_t count);
178 #else
179 static inline ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
> 180 size_t count) { return -ENOSUP; }
181 #endif
182

--
0-DAY CI Kernel Test Service
https://01.org/lkp


Attachments:
(No filename) (2.74 kB)
config (38.93 kB)
Download all attachments

2022-11-12 00:50:19

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

Hi Allen,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on driver-core/driver-core-testing]
[also build test WARNING on driver-core/driver-core-next driver-core/driver-core-linus mcgrof/modules-next usb/usb-testing usb/usb-next usb/usb-linus linus/master v6.1-rc4 next-20221111]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221111-233314
patch link: https://lore.kernel.org/r/20221111152852.2837363-1-allenwebb%40google.com
patch subject: [PATCH] modules: add modalias file to sysfs for modules.
config: sparc-allyesconfig
compiler: sparc64-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/6dda398b2e01f44f8fb5f03116ba5e6143360140
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221111-233314
git checkout 6dda398b2e01f44f8fb5f03116ba5e6143360140
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=sparc SHELL=/bin/bash drivers/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

>> drivers/base/mod_devicetable.c:214:9: warning: no previous prototype for 'usb_drv_to_modalias' [-Wmissing-prototypes]
214 | ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
| ^~~~~~~~~~~~~~~~~~~


vim +/usb_drv_to_modalias +214 drivers/base/mod_devicetable.c

203
204 /* Print the modaliases for the given driver assumed to be an usb_driver or
205 * usb_device_driver.
206 *
207 * "alias" is prepended and the module name is appended to each modalias to
208 * match the format in modules.aliases.
209 *
210 * The modaliases will be written out to @buf with @count being the maximum
211 * bytes to write. The return value is a negative errno on error or the number
212 * of bytes written to @buf on success.
213 */
> 214 ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,

--
0-DAY CI Kernel Test Service
https://01.org/lkp


Attachments:
(No filename) (2.69 kB)
config (328.46 kB)
Download all attachments

2022-11-14 16:55:48

by Allen Webb

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

On Fri, Nov 11, 2022 at 12:29 PM Luis Chamberlain <[email protected]> wrote:
>
> On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
> > USB devices support the authorized attribute which can be used by
> > user-space to implement trust-based systems for enabling USB devices. It
> > would be helpful when building these systems to be able to know in
> > advance which kernel drivers (or modules) are reachable from a
> > particular USB device.
> >
> > This information is readily available for external modules in
> > modules.alias. However, builtin kernel modules are not covered. This
> > patch adds a sys-fs attribute to both builtin and loaded modules
> > exposing the matching rules in the modalias format for integration
> > with tools like USBGuard.
> >
> > Signed-off-by: Allen Webb <[email protected]>
>
> Thanks for the patch Allen!
>
> I'd rather have something generic though, and it would seem kmod [0] already
> does this, have you seen the kmod support for builtin.alias.bin
>
> Can't that be used?

Probably, but I don't see the builtin.alias.bin in my build. Is it experimental?

>
> [0] git://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git
>
> Luis

2022-11-14 17:35:46

by Lucas De Marchi

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

On Mon, Nov 14, 2022 at 10:42:50AM -0600, Allen Webb wrote:
>On Fri, Nov 11, 2022 at 12:29 PM Luis Chamberlain <[email protected]> wrote:
>>
>> On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
>> > USB devices support the authorized attribute which can be used by
>> > user-space to implement trust-based systems for enabling USB devices. It
>> > would be helpful when building these systems to be able to know in
>> > advance which kernel drivers (or modules) are reachable from a
>> > particular USB device.
>> >
>> > This information is readily available for external modules in
>> > modules.alias. However, builtin kernel modules are not covered. This
>> > patch adds a sys-fs attribute to both builtin and loaded modules
>> > exposing the matching rules in the modalias format for integration
>> > with tools like USBGuard.
>> >
>> > Signed-off-by: Allen Webb <[email protected]>
>>
>> Thanks for the patch Allen!
>>
>> I'd rather have something generic though, and it would seem kmod [0] already
>> does this, have you seen the kmod support for builtin.alias.bin
>>
>> Can't that be used?
>
>Probably, but I don't see the builtin.alias.bin in my build. Is it experimental?

no. That is generated by depmod since v27 using modules.builtin.modinfo
generated by the kernel build system. Highly recommend v30 though
as there were fixes in v28 and v29 and some changes to speed up its
generation/use in v30: See entries mentioning
builtin.alias and bultin.modinfo in
https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git/tree/NEWS

libkmod/modprobe/modinfo also have the corresponding changes to lookup that
index when resolving aliases.

Lucas De Marchi


>
>>
>> [0] git://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git
>>
>> Luis

2022-11-15 16:47:10

by Allen Webb

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

On Mon, Nov 14, 2022 at 11:22 AM Lucas De Marchi
<[email protected]> wrote:
>
> On Mon, Nov 14, 2022 at 10:42:50AM -0600, Allen Webb wrote:
> >On Fri, Nov 11, 2022 at 12:29 PM Luis Chamberlain <[email protected]> wrote:
> >>
> >> On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
> >> > USB devices support the authorized attribute which can be used by
> >> > user-space to implement trust-based systems for enabling USB devices. It
> >> > would be helpful when building these systems to be able to know in
> >> > advance which kernel drivers (or modules) are reachable from a
> >> > particular USB device.
> >> >
> >> > This information is readily available for external modules in
> >> > modules.alias. However, builtin kernel modules are not covered. This
> >> > patch adds a sys-fs attribute to both builtin and loaded modules
> >> > exposing the matching rules in the modalias format for integration
> >> > with tools like USBGuard.
> >> >
> >> > Signed-off-by: Allen Webb <[email protected]>
> >>
> >> Thanks for the patch Allen!
> >>
> >> I'd rather have something generic though, and it would seem kmod [0] already
> >> does this, have you seen the kmod support for builtin.alias.bin
> >>
> >> Can't that be used?
> >
> >Probably, but I don't see the builtin.alias.bin in my build. Is it experimental?
>
> no. That is generated by depmod since v27 using modules.builtin.modinfo
> generated by the kernel build system. Highly recommend v30 though
> as there were fixes in v28 and v29 and some changes to speed up its
> generation/use in v30: See entries mentioning
> builtin.alias and bultin.modinfo in
> https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git/tree/NEWS
>
> libkmod/modprobe/modinfo also have the corresponding changes to lookup that
> index when resolving aliases.

I see the file but it is largely missing the aliases I am interested
in, so it looks like I might need to modify my patch that creates
buildin.alias to add the missing alias defines in the header along
with the other module metadata for builtin modules. Does this sound
right to you?

>
> Lucas De Marchi
>
>
> >
> >>
> >> [0] git://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git
> >>
> >> Luis

2022-11-15 17:49:23

by Luis Chamberlain

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

On Tue, Nov 15, 2022 at 10:05:35AM -0600, Allen Webb wrote:
> On Mon, Nov 14, 2022 at 11:22 AM Lucas De Marchi
> <[email protected]> wrote:
> >
> > On Mon, Nov 14, 2022 at 10:42:50AM -0600, Allen Webb wrote:
> > >On Fri, Nov 11, 2022 at 12:29 PM Luis Chamberlain <[email protected]> wrote:
> > >>
> > >> On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
> > >> > USB devices support the authorized attribute which can be used by
> > >> > user-space to implement trust-based systems for enabling USB devices. It
> > >> > would be helpful when building these systems to be able to know in
> > >> > advance which kernel drivers (or modules) are reachable from a
> > >> > particular USB device.
> > >> >
> > >> > This information is readily available for external modules in
> > >> > modules.alias. However, builtin kernel modules are not covered. This
> > >> > patch adds a sys-fs attribute to both builtin and loaded modules
> > >> > exposing the matching rules in the modalias format for integration
> > >> > with tools like USBGuard.
> > >> >
> > >> > Signed-off-by: Allen Webb <[email protected]>
> > >>
> > >> Thanks for the patch Allen!
> > >>
> > >> I'd rather have something generic though, and it would seem kmod [0] already
> > >> does this, have you seen the kmod support for builtin.alias.bin
> > >>
> > >> Can't that be used?
> > >
> > >Probably, but I don't see the builtin.alias.bin in my build. Is it experimental?
> >
> > no. That is generated by depmod since v27 using modules.builtin.modinfo
> > generated by the kernel build system. Highly recommend v30 though
> > as there were fixes in v28 and v29 and some changes to speed up its
> > generation/use in v30: See entries mentioning
> > builtin.alias and bultin.modinfo in
> > https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git/tree/NEWS
> >
> > libkmod/modprobe/modinfo also have the corresponding changes to lookup that
> > index when resolving aliases.
>
> I see the file but it is largely missing the aliases I am interested
> in, so it looks like I might need to modify my patch that creates
> buildin.alias to add the missing alias defines in the header along
> with the other module metadata for builtin modules. Does this sound
> right to you?

Can you clarify what is missing and why? And an RFC is welcomed if it
helps demonstrates what you mean.

Luis

2022-11-15 19:02:01

by Allen Webb

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

When i get the modinfo for usbhid, there are no aliases listed:
```
localhost ~ # modinfo usbhid
name: usbhid
filename: (builtin)
author: Andreas Gal
author: Vojtech Pavlik
author: Jiri Kosina
description: USB HID core driver
file: drivers/hid/usbhid/usbhid
license: GPL
parm: quirks:Add/modify USB HID quirks by specifying
quirks=vendorID:productID:quirks where vendorID, productID, and quirks
are all in 0x-prefixed hex (array of charp)
parm: ignoreled:Autosuspend with active leds (uint)
parm: kbpoll:Polling interval of keyboards (uint)
parm: jspoll:Polling interval of joysticks (uint)
parm: mousepoll:Polling interval of mice (uint)
```

bluetooth however has an alias listed:
```
localhost ~ # modinfo bluetooth
filename:
/lib/modules/5.10.154-20424-gea7532c123d8/kernel/net/bluetooth/bluetooth.ko.gz
author: Marcel Holtmann <[email protected]>
description: Bluetooth Core ver 2.22
version: 2.22
license: GPL
alias: net-pf-31
vermagic: 5.10.154-20424-gea7532c123d8 SMP preempt mod_unload
name: bluetooth
intree: Y
retpoline: Y
depends: ecdh_generic
srcversion: F8E46CD048C50B0AA1CD471
parm: disable_esco:Disable eSCO connection creation (bool)
parm: enable_ecred:Enable enhanced credit flow control mode (bool)
parm: disable_ertm:Disable enhanced retransmission mode (bool)
```

I believe the reason for this is many modules use `#define
MODULE_DEVICE_TABLE(type, name)` which is a noop for buildin modules.
I have a local patch that resolves that issue here:
See: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3840672/1/include/linux/module.h#b246

However, I probably ought to rework that patch to create the
MODULE_ALIAS defines instead of the buildin.alias file.

On Tue, Nov 15, 2022 at 11:35 AM Luis Chamberlain <[email protected]> wrote:
>
> On Tue, Nov 15, 2022 at 10:05:35AM -0600, Allen Webb wrote:
> > On Mon, Nov 14, 2022 at 11:22 AM Lucas De Marchi
> > <[email protected]> wrote:
> > >
> > > On Mon, Nov 14, 2022 at 10:42:50AM -0600, Allen Webb wrote:
> > > >On Fri, Nov 11, 2022 at 12:29 PM Luis Chamberlain <[email protected]> wrote:
> > > >>
> > > >> On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
> > > >> > USB devices support the authorized attribute which can be used by
> > > >> > user-space to implement trust-based systems for enabling USB devices. It
> > > >> > would be helpful when building these systems to be able to know in
> > > >> > advance which kernel drivers (or modules) are reachable from a
> > > >> > particular USB device.
> > > >> >
> > > >> > This information is readily available for external modules in
> > > >> > modules.alias. However, builtin kernel modules are not covered. This
> > > >> > patch adds a sys-fs attribute to both builtin and loaded modules
> > > >> > exposing the matching rules in the modalias format for integration
> > > >> > with tools like USBGuard.
> > > >> >
> > > >> > Signed-off-by: Allen Webb <[email protected]>
> > > >>
> > > >> Thanks for the patch Allen!
> > > >>
> > > >> I'd rather have something generic though, and it would seem kmod [0] already
> > > >> does this, have you seen the kmod support for builtin.alias.bin
> > > >>
> > > >> Can't that be used?
> > > >
> > > >Probably, but I don't see the builtin.alias.bin in my build. Is it experimental?
> > >
> > > no. That is generated by depmod since v27 using modules.builtin.modinfo
> > > generated by the kernel build system. Highly recommend v30 though
> > > as there were fixes in v28 and v29 and some changes to speed up its
> > > generation/use in v30: See entries mentioning
> > > builtin.alias and bultin.modinfo in
> > > https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git/tree/NEWS
> > >
> > > libkmod/modprobe/modinfo also have the corresponding changes to lookup that
> > > index when resolving aliases.
> >
> > I see the file but it is largely missing the aliases I am interested
> > in, so it looks like I might need to modify my patch that creates
> > buildin.alias to add the missing alias defines in the header along
> > with the other module metadata for builtin modules. Does this sound
> > right to you?
>
> Can you clarify what is missing and why? And an RFC is welcomed if it
> helps demonstrates what you mean.
>
> Luis

2022-11-16 21:37:15

by Allen Webb

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

I think I am misunderstanding something because the aliases visible
through kmod_config_get_aliases don't look anything like the
modaliases used by udev to match devices to modules.

I have some concern that making the changes necessary to use kmod
would result in the files/indexes being much larger to include all the
extra values that are being left out, so I think the sysfs approach
might be the better way to go.

On Tue, Nov 15, 2022 at 12:40 PM Allen Webb <[email protected]> wrote:
>
> When i get the modinfo for usbhid, there are no aliases listed:
> ```
> localhost ~ # modinfo usbhid
> name: usbhid
> filename: (builtin)
> author: Andreas Gal
> author: Vojtech Pavlik
> author: Jiri Kosina
> description: USB HID core driver
> file: drivers/hid/usbhid/usbhid
> license: GPL
> parm: quirks:Add/modify USB HID quirks by specifying
> quirks=vendorID:productID:quirks where vendorID, productID, and quirks
> are all in 0x-prefixed hex (array of charp)
> parm: ignoreled:Autosuspend with active leds (uint)
> parm: kbpoll:Polling interval of keyboards (uint)
> parm: jspoll:Polling interval of joysticks (uint)
> parm: mousepoll:Polling interval of mice (uint)
> ```
>
> bluetooth however has an alias listed:
> ```
> localhost ~ # modinfo bluetooth
> filename:
> /lib/modules/5.10.154-20424-gea7532c123d8/kernel/net/bluetooth/bluetooth.ko.gz
> author: Marcel Holtmann <[email protected]>
> description: Bluetooth Core ver 2.22
> version: 2.22
> license: GPL
> alias: net-pf-31
> vermagic: 5.10.154-20424-gea7532c123d8 SMP preempt mod_unload
> name: bluetooth
> intree: Y
> retpoline: Y
> depends: ecdh_generic
> srcversion: F8E46CD048C50B0AA1CD471
> parm: disable_esco:Disable eSCO connection creation (bool)
> parm: enable_ecred:Enable enhanced credit flow control mode (bool)
> parm: disable_ertm:Disable enhanced retransmission mode (bool)
> ```
>
> I believe the reason for this is many modules use `#define
> MODULE_DEVICE_TABLE(type, name)` which is a noop for buildin modules.
> I have a local patch that resolves that issue here:
> See: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3840672/1/include/linux/module.h#b246
>
> However, I probably ought to rework that patch to create the
> MODULE_ALIAS defines instead of the buildin.alias file.
>
> On Tue, Nov 15, 2022 at 11:35 AM Luis Chamberlain <[email protected]> wrote:
> >
> > On Tue, Nov 15, 2022 at 10:05:35AM -0600, Allen Webb wrote:
> > > On Mon, Nov 14, 2022 at 11:22 AM Lucas De Marchi
> > > <[email protected]> wrote:
> > > >
> > > > On Mon, Nov 14, 2022 at 10:42:50AM -0600, Allen Webb wrote:
> > > > >On Fri, Nov 11, 2022 at 12:29 PM Luis Chamberlain <[email protected]> wrote:
> > > > >>
> > > > >> On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
> > > > >> > USB devices support the authorized attribute which can be used by
> > > > >> > user-space to implement trust-based systems for enabling USB devices. It
> > > > >> > would be helpful when building these systems to be able to know in
> > > > >> > advance which kernel drivers (or modules) are reachable from a
> > > > >> > particular USB device.
> > > > >> >
> > > > >> > This information is readily available for external modules in
> > > > >> > modules.alias. However, builtin kernel modules are not covered. This
> > > > >> > patch adds a sys-fs attribute to both builtin and loaded modules
> > > > >> > exposing the matching rules in the modalias format for integration
> > > > >> > with tools like USBGuard.
> > > > >> >
> > > > >> > Signed-off-by: Allen Webb <[email protected]>
> > > > >>
> > > > >> Thanks for the patch Allen!
> > > > >>
> > > > >> I'd rather have something generic though, and it would seem kmod [0] already
> > > > >> does this, have you seen the kmod support for builtin.alias.bin
> > > > >>
> > > > >> Can't that be used?
> > > > >
> > > > >Probably, but I don't see the builtin.alias.bin in my build. Is it experimental?
> > > >
> > > > no. That is generated by depmod since v27 using modules.builtin.modinfo
> > > > generated by the kernel build system. Highly recommend v30 though
> > > > as there were fixes in v28 and v29 and some changes to speed up its
> > > > generation/use in v30: See entries mentioning
> > > > builtin.alias and bultin.modinfo in
> > > > https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git/tree/NEWS
> > > >
> > > > libkmod/modprobe/modinfo also have the corresponding changes to lookup that
> > > > index when resolving aliases.
> > >
> > > I see the file but it is largely missing the aliases I am interested
> > > in, so it looks like I might need to modify my patch that creates
> > > buildin.alias to add the missing alias defines in the header along
> > > with the other module metadata for builtin modules. Does this sound
> > > right to you?
> >
> > Can you clarify what is missing and why? And an RFC is welcomed if it
> > helps demonstrates what you mean.
> >
> > Luis

2022-11-17 16:28:15

by Alexey Gladkov

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

On Tue, Nov 15, 2022 at 12:40:57PM -0600, Allen Webb wrote:
> When i get the modinfo for usbhid, there are no aliases listed:
> ```
> localhost ~ # modinfo usbhid
> name: usbhid
> filename: (builtin)
> author: Andreas Gal
> author: Vojtech Pavlik
> author: Jiri Kosina
> description: USB HID core driver
> file: drivers/hid/usbhid/usbhid
> license: GPL
> parm: quirks:Add/modify USB HID quirks by specifying
> quirks=vendorID:productID:quirks where vendorID, productID, and quirks
> are all in 0x-prefixed hex (array of charp)
> parm: ignoreled:Autosuspend with active leds (uint)
> parm: kbpoll:Polling interval of keyboards (uint)
> parm: jspoll:Polling interval of joysticks (uint)
> parm: mousepoll:Polling interval of mice (uint)
> ```

Hm. Interesting. Actually, alias gets into modules.builtin.modinfo:

$ tr '\0' '\n' < /lib/modules/`uname -r`/modules.builtin.modinfo |grep ^crc32c_generic.alias=
crc32c_generic.alias=crypto-crc32c-generic
crc32c_generic.alias=crc32c-generic
crc32c_generic.alias=crypto-crc32c
crc32c_generic.alias=crc32c

> bluetooth however has an alias listed:
> ```
> localhost ~ # modinfo bluetooth
> filename:
> /lib/modules/5.10.154-20424-gea7532c123d8/kernel/net/bluetooth/bluetooth.ko.gz
> author: Marcel Holtmann <[email protected]>
> description: Bluetooth Core ver 2.22
> version: 2.22
> license: GPL
> alias: net-pf-31
> vermagic: 5.10.154-20424-gea7532c123d8 SMP preempt mod_unload
> name: bluetooth
> intree: Y
> retpoline: Y
> depends: ecdh_generic
> srcversion: F8E46CD048C50B0AA1CD471
> parm: disable_esco:Disable eSCO connection creation (bool)
> parm: enable_ecred:Enable enhanced credit flow control mode (bool)
> parm: disable_ertm:Disable enhanced retransmission mode (bool)
> ```
>
> I believe the reason for this is many modules use `#define
> MODULE_DEVICE_TABLE(type, name)` which is a noop for buildin modules.
> I have a local patch that resolves that issue here:
> See: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/3840672/1/include/linux/module.h#b246
>
> However, I probably ought to rework that patch to create the
> MODULE_ALIAS defines instead of the buildin.alias file.
>
> On Tue, Nov 15, 2022 at 11:35 AM Luis Chamberlain <[email protected]> wrote:
> >
> > On Tue, Nov 15, 2022 at 10:05:35AM -0600, Allen Webb wrote:
> > > On Mon, Nov 14, 2022 at 11:22 AM Lucas De Marchi
> > > <[email protected]> wrote:
> > > >
> > > > On Mon, Nov 14, 2022 at 10:42:50AM -0600, Allen Webb wrote:
> > > > >On Fri, Nov 11, 2022 at 12:29 PM Luis Chamberlain <[email protected]> wrote:
> > > > >>
> > > > >> On Fri, Nov 11, 2022 at 09:28:52AM -0600, Allen Webb wrote:
> > > > >> > USB devices support the authorized attribute which can be used by
> > > > >> > user-space to implement trust-based systems for enabling USB devices. It
> > > > >> > would be helpful when building these systems to be able to know in
> > > > >> > advance which kernel drivers (or modules) are reachable from a
> > > > >> > particular USB device.
> > > > >> >
> > > > >> > This information is readily available for external modules in
> > > > >> > modules.alias. However, builtin kernel modules are not covered. This
> > > > >> > patch adds a sys-fs attribute to both builtin and loaded modules
> > > > >> > exposing the matching rules in the modalias format for integration
> > > > >> > with tools like USBGuard.
> > > > >> >
> > > > >> > Signed-off-by: Allen Webb <[email protected]>
> > > > >>
> > > > >> Thanks for the patch Allen!
> > > > >>
> > > > >> I'd rather have something generic though, and it would seem kmod [0] already
> > > > >> does this, have you seen the kmod support for builtin.alias.bin
> > > > >>
> > > > >> Can't that be used?
> > > > >
> > > > >Probably, but I don't see the builtin.alias.bin in my build. Is it experimental?
> > > >
> > > > no. That is generated by depmod since v27 using modules.builtin.modinfo
> > > > generated by the kernel build system. Highly recommend v30 though
> > > > as there were fixes in v28 and v29 and some changes to speed up its
> > > > generation/use in v30: See entries mentioning
> > > > builtin.alias and bultin.modinfo in
> > > > https://git.kernel.org/pub/scm/utils/kernel/kmod/kmod.git/tree/NEWS
> > > >
> > > > libkmod/modprobe/modinfo also have the corresponding changes to lookup that
> > > > index when resolving aliases.
> > >
> > > I see the file but it is largely missing the aliases I am interested
> > > in, so it looks like I might need to modify my patch that creates
> > > buildin.alias to add the missing alias defines in the header along
> > > with the other module metadata for builtin modules. Does this sound
> > > right to you?
> >
> > Can you clarify what is missing and why? And an RFC is welcomed if it
> > helps demonstrates what you mean.
> >
> > Luis
>

--
Rgrds, legion


2022-11-28 20:33:58

by Allen Webb

[permalink] [raw]
Subject: [PATCH] modules: add modalias file to sysfs for modules.

USB devices support the authorized attribute which can be used by
user-space to implement trust-based systems for enabling USB devices. It
would be helpful when building these systems to be able to know in
advance which kernel drivers (or modules) are reachable from a
particular USB device.

This information is readily available for external modules in
modules.alias. However, builtin kernel modules are not covered. This
patch adds a sys-fs attribute to both builtin and loaded modules
exposing the matching rules in the modalias format for integration
with tools like USBGuard.

Signed-off-by: Allen Webb <[email protected]>
---
drivers/base/Makefile | 2 +-
drivers/base/base.h | 8 ++
drivers/base/bus.c | 42 ++++++
drivers/base/mod_devicetable.c | 247 +++++++++++++++++++++++++++++++++
drivers/usb/core/driver.c | 2 +
include/linux/device/bus.h | 8 ++
include/linux/module.h | 1 +
kernel/module/internal.h | 2 +
kernel/module/sysfs.c | 100 +++++++++++++
kernel/params.c | 2 +
10 files changed, 413 insertions(+), 1 deletion(-)
create mode 100644 drivers/base/mod_devicetable.c

diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 83217d243c25b..924d46ae987f4 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -15,7 +15,7 @@ obj-y += firmware_loader/
obj-$(CONFIG_NUMA) += node.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
ifeq ($(CONFIG_SYSFS),y)
-obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_MODULES) += mod_devicetable.o module.o
endif
obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
obj-$(CONFIG_REGMAP) += regmap/
diff --git a/drivers/base/base.h b/drivers/base/base.h
index b902d1ecc247f..beaa252c04388 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -173,6 +173,14 @@ static inline void module_add_driver(struct module *mod,
static inline void module_remove_driver(struct device_driver *drv) { }
#endif

+#if defined(CONFIG_SYSFS)
+ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count);
+#else
+static inline ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count) { return -EINVAL; }
+#endif
+
#ifdef CONFIG_DEVTMPFS
extern int devtmpfs_init(void);
#else
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 7ca47e5b3c1f4..4e0c5925545e5 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -178,6 +178,48 @@ static const struct kset_uevent_ops bus_uevent_ops = {

static struct kset *bus_kset;

+/**
+ * bus_for_each - bus iterator.
+ * @start: bus to start iterating from.
+ * @data: data for the callback.
+ * @fn: function to be called for each device.
+ *
+ * Iterate over list of buses, and call @fn for each,
+ * passing it @data. If @start is not NULL, we use that bus to
+ * begin iterating from.
+ *
+ * We check the return of @fn each time. If it returns anything
+ * other than 0, we break out and return that value.
+ *
+ * NOTE: The bus that returns a non-zero value is not retained
+ * in any way, nor is its refcount incremented. If the caller needs
+ * to retain this data, it should do so, and increment the reference
+ * count in the supplied callback.
+ */
+int bus_for_each(void *data, int (*fn)(struct bus_type *, void *))
+{
+ int error = 0;
+ struct bus_type *bus;
+ struct subsys_private *bus_prv;
+ struct kset *subsys;
+ struct kobject *k;
+
+ spin_lock(&bus_kset->list_lock);
+
+ list_for_each_entry(k, &bus_kset->list, entry) {
+ subsys = container_of(k, struct kset, kobj);
+ bus_prv = container_of(subsys, struct subsys_private, subsys);
+ bus = bus_prv->bus;
+ error = fn(bus, data);
+ if (error)
+ break;
+ }
+
+ spin_unlock(&bus_kset->list_lock);
+ return error;
+}
+EXPORT_SYMBOL_GPL(bus_for_each);
+
/* Manually detach a device from its associated driver. */
static ssize_t unbind_store(struct device_driver *drv, const char *buf,
size_t count)
diff --git a/drivers/base/mod_devicetable.c b/drivers/base/mod_devicetable.c
new file mode 100644
index 0000000000000..b04442207668c
--- /dev/null
+++ b/drivers/base/mod_devicetable.c
@@ -0,0 +1,247 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mod_devicetable.c - helpers for displaying modaliases through sysfs.
+ *
+ * This borrows a lot from file2alias.c
+ */
+
+#include <linux/device/bus.h>
+#include <linux/device.h>
+#include <linux/usb.h>
+
+#include "base.h"
+#include "../usb/core/usb.h"
+
+#define ADD(buf, count, len, sep, cond, field) \
+do { \
+ if (cond) \
+ (len) += scnprintf(&(buf)[len], \
+ (count) - (len), \
+ sizeof(field) == 1 ? (sep "%02X") : \
+ sizeof(field) == 2 ? (sep "%04X") : \
+ sizeof(field) == 4 ? (sep "%08X") : "", \
+ (field)); \
+ else \
+ (len) += scnprintf(&(buf)[len], (count) - (len), (sep "*")); \
+} while (0)
+
+#ifdef CONFIG_USB
+/* USB related modaliases can be split because of device number matching, so
+ * this function handles individual modaliases for one segment of the range.
+ *
+ *
+ */
+static ssize_t usb_id_to_modalias(const struct usb_device_id *id,
+ unsigned int bcdDevice_initial,
+ int bcdDevice_initial_digits,
+ unsigned char range_lo,
+ unsigned char range_hi,
+ unsigned char max, const char *mod_name,
+ char *buf, size_t count)
+{
+ ssize_t len = 0;
+
+ ADD(buf, count, len, "alias usb:v",
+ id->match_flags & USB_DEVICE_ID_MATCH_VENDOR, id->idVendor);
+ ADD(buf, count, len, "p", id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT,
+ id->idProduct);
+
+ len += scnprintf(&buf[len], count - len, "d");
+ if (bcdDevice_initial_digits)
+ len += scnprintf(&buf[len], count - len, "%0*X",
+ bcdDevice_initial_digits, bcdDevice_initial);
+ if (range_lo == range_hi) {
+ len += scnprintf(&buf[len], count - len, "%X", range_lo);
+ } else if (range_lo > 0 || range_hi < max) {
+ if (range_lo > 0x9 || range_hi < 0xA) {
+ len += scnprintf(&buf[len], count - len, "[%X-%X]",
+ range_lo, range_hi);
+ } else {
+ len += scnprintf(&buf[len], count - len,
+ range_lo < 0x9 ? "[%X-9" : "[%X",
+ range_lo);
+ len += scnprintf(&buf[len], count - len,
+ range_hi > 0xA ? "A-%X]" : "%X]",
+ range_hi);
+ }
+ }
+ if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
+ len += scnprintf(&buf[len], count - len, "*");
+
+ ADD(buf, count, len, "dc",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS, id->bDeviceClass);
+ ADD(buf, count, len, "dsc",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+ id->bDeviceSubClass);
+ ADD(buf, count, len, "dp",
+ id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ id->bDeviceProtocol);
+ ADD(buf, count, len, "ic",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS,
+ id->bInterfaceClass);
+ ADD(buf, count, len, "isc",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+ id->bInterfaceSubClass);
+ ADD(buf, count, len, "ip",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+ id->bInterfaceProtocol);
+ ADD(buf, count, len, "in",
+ id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER,
+ id->bInterfaceNumber);
+
+ len += scnprintf(&buf[len], count - len, " %s\n", mod_name);
+ return len;
+}
+
+/* Handles increment/decrement of BCD formatted integers */
+/* Returns the previous value, so it works like i++ or i-- */
+static unsigned int incbcd(unsigned int *bcd,
+ int inc,
+ unsigned char max,
+ size_t chars)
+{
+ unsigned int init = *bcd, i, j;
+ unsigned long long c, dec = 0;
+
+ /* If bcd is not in BCD format, just increment */
+ if (max > 0x9) {
+ *bcd += inc;
+ return init;
+ }
+
+ /* Convert BCD to Decimal */
+ for (i = 0 ; i < chars ; i++) {
+ c = (*bcd >> (i << 2)) & 0xf;
+ c = c > 9 ? 9 : c; /* force to bcd just in case */
+ for (j = 0 ; j < i ; j++)
+ c = c * 10;
+ dec += c;
+ }
+
+ /* Do our increment/decrement */
+ dec += inc;
+ *bcd = 0;
+
+ /* Convert back to BCD */
+ for (i = 0 ; i < chars ; i++) {
+ for (c = 1, j = 0 ; j < i ; j++)
+ c = c * 10;
+ c = (dec / c) % 10;
+ *bcd += c << (i << 2);
+ }
+ return init;
+}
+
+/* Print the modaliases for the specified struct usb_device_id.
+ */
+static ssize_t usb_id_to_modalias_multi(const struct usb_device_id *id,
+ const char *mod_name, char *buf,
+ size_t count)
+{
+ ssize_t len = 0;
+ unsigned int devlo, devhi;
+ unsigned char chi, clo, max;
+ int ndigits;
+
+ devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
+ id->bcdDevice_lo : 0x0U;
+ devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
+ id->bcdDevice_hi : ~0x0U;
+
+ /* Figure out if this entry is in bcd or hex format */
+ max = 0x9; /* Default to decimal format */
+ for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
+ clo = (devlo >> (ndigits << 2)) & 0xf;
+ chi = ((devhi > 0x9999 ? 0x9999 : devhi) >>
+ (ndigits << 2)) & 0xf;
+ if (clo > max || chi > max) {
+ max = 0xf;
+ break;
+ }
+ }
+
+ /*
+ * Some modules (visor) have empty slots as placeholder for
+ * run-time specification that results in catch-all alias
+ */
+ if (!(id->idVendor || id->idProduct || id->bDeviceClass ||
+ id->bInterfaceClass))
+ return len;
+
+ /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
+ for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi;
+ ndigits--) {
+ clo = devlo & 0xf;
+ chi = devhi & 0xf;
+ /* If we are in bcd mode, truncate if necessary */
+ if (chi > max)
+ chi = max;
+ devlo >>= 4;
+ devhi >>= 4;
+
+ if (devlo == devhi || !ndigits) {
+ len += usb_id_to_modalias(id, devlo, ndigits, clo, chi,
+ max, mod_name, buf + len,
+ count - len);
+ break;
+ }
+
+ if (clo > 0x0)
+ len += usb_id_to_modalias(id,
+ incbcd(&devlo, 1, max,
+ sizeof(id->bcdDevice_lo) * 2),
+ ndigits, clo, max, max, mod_name, buf + len,
+ count - len);
+
+ if (chi < max)
+ len += usb_id_to_modalias(id,
+ incbcd(&devhi, -1, max,
+ sizeof(id->bcdDevice_lo) * 2),
+ ndigits, 0x0, chi, max, mod_name, buf + len,
+ count - len);
+ }
+ return len;
+}
+
+/* Print the modaliases for the given driver assumed to be an usb_driver or
+ * usb_device_driver.
+ *
+ * "alias" is prepended and the module name is appended to each modalias to
+ * match the format in modules.aliases.
+ *
+ * The modaliases will be written out to @buf with @count being the maximum
+ * bytes to write. The return value is a negative errno on error or the number
+ * of bytes written to @buf on success.
+ */
+ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count)
+{
+ ssize_t len = 0;
+ const struct usb_device_id *id;
+ const char *mod_name;
+
+ if (drv->bus != &usb_bus_type)
+ return -EINVAL;
+
+ if (drv->owner)
+ mod_name = drv->owner->name;
+ else
+ mod_name = drv->mod_name;
+
+ if (is_usb_device_driver(drv))
+ id = to_usb_device_driver(drv)->id_table;
+ else
+ id = to_usb_driver(drv)->id_table;
+ if (!id)
+ return len;
+
+ for (; id->match_flags; id++) {
+ len += usb_id_to_modalias_multi(id, mod_name, buf + len,
+ count - len);
+ }
+ return len;
+}
+#else
+inline ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
+ size_t count){ return 0; }
+#endif
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 7e7e119c253fb..fdbc197b64c9c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -32,6 +32,7 @@
#include <linux/usb/quirks.h>
#include <linux/usb/hcd.h>

+#include "../../base/base.h"
#include "usb.h"


@@ -2030,4 +2031,5 @@ struct bus_type usb_bus_type = {
.match = usb_device_match,
.uevent = usb_uevent,
.need_parent_lock = true,
+ .drv_to_modalias = usb_drv_to_modalias,
};
diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h
index d8b29ccd07e56..cce0bedec63d9 100644
--- a/include/linux/device/bus.h
+++ b/include/linux/device/bus.h
@@ -61,6 +61,10 @@ struct fwnode_handle;
* this bus.
* @dma_cleanup: Called to cleanup DMA configuration on a device on
* this bus.
+ * @drv_to_modalias: Called to convert the matching IDs in a
+ * struct device_driver to their corresponding modaliases.
+ * Note that the struct device_driver is expected to belong
+ * to this bus.
* @pm: Power management operations of this bus, callback the specific
* device driver's pm-ops.
* @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU
@@ -107,6 +111,9 @@ struct bus_type {
int (*dma_configure)(struct device *dev);
void (*dma_cleanup)(struct device *dev);

+ ssize_t (*drv_to_modalias)(struct device_driver *drv, char *buf,
+ size_t count);
+
const struct dev_pm_ops *pm;

const struct iommu_ops *iommu_ops;
@@ -161,6 +168,7 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter,
struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
void subsys_dev_iter_exit(struct subsys_dev_iter *iter);

+int bus_for_each(void *data, int (*fn)(struct bus_type *, void *));
int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
int (*fn)(struct device *dev, void *data));
struct device *bus_find_device(struct bus_type *bus, struct device *start,
diff --git a/include/linux/module.h b/include/linux/module.h
index ec61fb53979a9..0bfa859a21566 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -47,6 +47,7 @@ struct module_kobject {
struct kobject *drivers_dir;
struct module_param_attrs *mp;
struct completion *kobj_completion;
+ struct bin_attribute modalias_attr;
} __randomize_layout;

struct module_attribute {
diff --git a/kernel/module/internal.h b/kernel/module/internal.h
index 2e2bf236f5582..8d7ae37584868 100644
--- a/kernel/module/internal.h
+++ b/kernel/module/internal.h
@@ -259,11 +259,13 @@ static inline void add_kallsyms(struct module *mod, const struct load_info *info
#endif /* CONFIG_KALLSYMS */

#ifdef CONFIG_SYSFS
+void add_modalias_attr(struct module_kobject *mk);
int mod_sysfs_setup(struct module *mod, const struct load_info *info,
struct kernel_param *kparam, unsigned int num_params);
void mod_sysfs_teardown(struct module *mod);
void init_param_lock(struct module *mod);
#else /* !CONFIG_SYSFS */
+static inline void add_modalias_attr(struct module_kobject *mk) {}
static inline int mod_sysfs_setup(struct module *mod,
const struct load_info *info,
struct kernel_param *kparam,
diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
index ce68f821dcd12..e80bfa4639765 100644
--- a/kernel/module/sysfs.c
+++ b/kernel/module/sysfs.c
@@ -5,6 +5,8 @@
* Copyright (C) 2008 Rusty Russell
*/

+#include <linux/device/bus.h>
+#include <linux/device/driver.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
@@ -240,6 +242,102 @@ static inline void add_notes_attrs(struct module *mod, const struct load_info *i
static inline void remove_notes_attrs(struct module *mod) { }
#endif /* CONFIG_KALLSYMS */

+/* Track of the buffer and module identity in callbacks when walking the list of
+ * drivers for each bus.
+ */
+struct modalias_bus_print_state {
+ struct module_kobject *mk;
+ char *buf;
+ size_t count;
+ ssize_t len;
+};
+
+static int print_modalias_for_drv(struct device_driver *drv, void *p)
+{
+ struct modalias_bus_print_state *s = p;
+ struct module_kobject *mk = s->mk;
+ ssize_t len;
+ /* Skip drivers that do not match this module. */
+ if (mk->mod) {
+ if (mk->mod != drv->owner)
+ return 0;
+ } else if (!mk->kobj.name || !drv->mod_name ||
+ strcmp(mk->kobj.name, drv->mod_name))
+ return 0;
+
+ if (drv->bus && drv->bus->drv_to_modalias) {
+ len = drv->bus->drv_to_modalias(drv, s->buf + s->len,
+ s->count - s->len);
+ if (len < 0)
+ return len;
+ s->len += len;
+ }
+
+ s->len += scnprintf(&s->buf[s->len], s->count - s->len, "driver %s\n",
+ drv->name);
+ return 0;
+}
+
+static int print_modalias_for_bus(struct bus_type *type, void *p)
+{
+ return bus_for_each_drv(type, NULL, p, print_modalias_for_drv);
+}
+
+static ssize_t module_modalias_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct module_kobject *mk = container_of(kobj, struct module_kobject,
+ kobj);
+ struct modalias_bus_print_state state = {mk, buf, count, 0};
+ int error = 0;
+
+ if (pos != 0)
+ return -EINVAL;
+
+ error = bus_for_each(&state, print_modalias_for_bus);
+ if (error)
+ return error;
+
+ if (mk->mod)
+ state.len += scnprintf(&buf[state.len], count - state.len,
+ "modalias %s %s\n", kobject_name(kobj),
+ mk->mod->name);
+ else
+ state.len += scnprintf(&buf[state.len], count - state.len,
+ "modalias %s NULL\n",
+ kobject_name(kobj));
+
+ /*
+ * The caller checked the pos and count against our size.
+ */
+ return state.len;
+}
+
+/* Used in kernel/params.c for builtin modules.
+ *
+ * `struct module_kobject` is used instead of `struct module` because for
+ * builtin modules, the `struct module` is not available when this is called.
+ */
+void add_modalias_attr(struct module_kobject *mk)
+{
+ sysfs_bin_attr_init(&mk->modalias_attr);
+ mk->modalias_attr.attr.name = "modalias";
+ mk->modalias_attr.attr.mode = 0444;
+ mk->modalias_attr.read = module_modalias_read;
+ if (sysfs_create_bin_file(&mk->kobj, &mk->modalias_attr)) {
+ /* We shouldn't ignore the return type, but there is nothing to
+ * do.
+ */
+ return;
+ }
+}
+
+static void remove_modalias_attr(struct module_kobject *mk)
+{
+ sysfs_remove_bin_file(&mk->kobj, &mk->modalias_attr);
+}
+
static void del_usage_links(struct module *mod)
{
#ifdef CONFIG_MODULE_UNLOAD
@@ -398,6 +496,7 @@ int mod_sysfs_setup(struct module *mod,

add_sect_attrs(mod, info);
add_notes_attrs(mod, info);
+ add_modalias_attr(&mod->mkobj);

return 0;

@@ -415,6 +514,7 @@ int mod_sysfs_setup(struct module *mod,

static void mod_sysfs_fini(struct module *mod)
{
+ remove_modalias_attr(&mod->mkobj);
remove_notes_attrs(mod);
remove_sect_attrs(mod);
mod_kobject_put(mod);
diff --git a/kernel/params.c b/kernel/params.c
index 5b92310425c50..111024196361a 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/security.h>
+#include "module/internal.h"

#ifdef CONFIG_SYSFS
/* Protects all built-in parameters, modules use their own param_lock */
@@ -815,6 +816,7 @@ static void __init kernel_add_sysfs_param(const char *name,
BUG_ON(err);
kobject_uevent(&mk->kobj, KOBJ_ADD);
kobject_put(&mk->kobj);
+ add_modalias_attr(mk);
}

/*
--
2.37.3

2022-11-29 07:48:03

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

On Mon, Nov 28, 2022 at 02:13:32PM -0600, Allen Webb wrote:
> USB devices support the authorized attribute which can be used by
> user-space to implement trust-based systems for enabling USB devices. It
> would be helpful when building these systems to be able to know in
> advance which kernel drivers (or modules) are reachable from a
> particular USB device.
>
> This information is readily available for external modules in
> modules.alias. However, builtin kernel modules are not covered. This
> patch adds a sys-fs attribute to both builtin and loaded modules
> exposing the matching rules in the modalias format for integration
> with tools like USBGuard.
>
> Signed-off-by: Allen Webb <[email protected]>
> ---
> drivers/base/Makefile | 2 +-
> drivers/base/base.h | 8 ++
> drivers/base/bus.c | 42 ++++++
> drivers/base/mod_devicetable.c | 247 +++++++++++++++++++++++++++++++++
> drivers/usb/core/driver.c | 2 +
> include/linux/device/bus.h | 8 ++
> include/linux/module.h | 1 +
> kernel/module/internal.h | 2 +
> kernel/module/sysfs.c | 100 +++++++++++++
> kernel/params.c | 2 +
> 10 files changed, 413 insertions(+), 1 deletion(-)
> create mode 100644 drivers/base/mod_devicetable.c

Hi,

This is the friendly patch-bot of Greg Kroah-Hartman. You have sent him
a patch that has triggered this response. He used to manually respond
to these common problems, but in order to save his sanity (he kept
writing the same thing over and over, yet to different people), I was
created. Hopefully you will not take offence and will fix the problem
in your patch and resubmit it so that it can be accepted into the Linux
kernel tree.

You are receiving this message because of the following common error(s)
as indicated below:

- This looks like a new version of a previously submitted patch, but you
did not list below the --- line any changes from the previous version.
Please read the section entitled "The canonical patch format" in the
kernel file, Documentation/SubmittingPatches for what needs to be done
here to properly describe this.

If you wish to discuss this problem further, or you have questions about
how to resolve this issue, please feel free to respond to this email and
Greg will reply once he has dug out from the pending patches received
from other developers.

thanks,

greg k-h's patch email bot

2022-11-29 08:16:57

by Christophe Leroy

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.



Le 28/11/2022 à 21:13, Allen Webb a écrit :
> USB devices support the authorized attribute which can be used by
> user-space to implement trust-based systems for enabling USB devices. It
> would be helpful when building these systems to be able to know in
> advance which kernel drivers (or modules) are reachable from a
> particular USB device.
>
> This information is readily available for external modules in
> modules.alias. However, builtin kernel modules are not covered. This
> patch adds a sys-fs attribute to both builtin and loaded modules
> exposing the matching rules in the modalias format for integration
> with tools like USBGuard.
>
> Signed-off-by: Allen Webb <[email protected]>
> ---

You already sent a patch with the same title on Nov 11th. Why are you
resending ?

The line count is different from previous patch. Is that just a rebase ?

The commit message is different, so is it a new version ? If so it
should be marked [PATCH v2] in the title.

Also, there should be some explanation of the resend here below the ---,
so that everyone knows the reason you are resending or sending a new
version.

> drivers/base/Makefile | 2 +-
> drivers/base/base.h | 8 ++
> drivers/base/bus.c | 42 ++++++
> drivers/base/mod_devicetable.c | 247 +++++++++++++++++++++++++++++++++
> drivers/usb/core/driver.c | 2 +
> include/linux/device/bus.h | 8 ++
> include/linux/module.h | 1 +
> kernel/module/internal.h | 2 +
> kernel/module/sysfs.c | 100 +++++++++++++
> kernel/params.c | 2 +
> 10 files changed, 413 insertions(+), 1 deletion(-)
> create mode 100644 drivers/base/mod_devicetable.c
>
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 83217d243c25b..924d46ae987f4 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -15,7 +15,7 @@ obj-y += firmware_loader/
> obj-$(CONFIG_NUMA) += node.o
> obj-$(CONFIG_MEMORY_HOTPLUG) += memory.o
> ifeq ($(CONFIG_SYSFS),y)
> -obj-$(CONFIG_MODULES) += module.o
> +obj-$(CONFIG_MODULES) += mod_devicetable.o module.o
> endif
> obj-$(CONFIG_SYS_HYPERVISOR) += hypervisor.o
> obj-$(CONFIG_REGMAP) += regmap/
> diff --git a/drivers/base/base.h b/drivers/base/base.h
> index b902d1ecc247f..beaa252c04388 100644
> --- a/drivers/base/base.h
> +++ b/drivers/base/base.h
> @@ -173,6 +173,14 @@ static inline void module_add_driver(struct module *mod,
> static inline void module_remove_driver(struct device_driver *drv) { }
> #endif
>
> +#if defined(CONFIG_SYSFS)
> +ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
> + size_t count);
> +#else
> +static inline ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
> + size_t count) { return -EINVAL; }
> +#endif
> +
> #ifdef CONFIG_DEVTMPFS
> extern int devtmpfs_init(void);
> #else
> diff --git a/drivers/base/bus.c b/drivers/base/bus.c
> index 7ca47e5b3c1f4..4e0c5925545e5 100644
> --- a/drivers/base/bus.c
> +++ b/drivers/base/bus.c
> @@ -178,6 +178,48 @@ static const struct kset_uevent_ops bus_uevent_ops = {
>
> static struct kset *bus_kset;
>
> +/**
> + * bus_for_each - bus iterator.
> + * @start: bus to start iterating from.
> + * @data: data for the callback.
> + * @fn: function to be called for each device.
> + *
> + * Iterate over list of buses, and call @fn for each,
> + * passing it @data. If @start is not NULL, we use that bus to
> + * begin iterating from.
> + *
> + * We check the return of @fn each time. If it returns anything
> + * other than 0, we break out and return that value.
> + *
> + * NOTE: The bus that returns a non-zero value is not retained
> + * in any way, nor is its refcount incremented. If the caller needs
> + * to retain this data, it should do so, and increment the reference
> + * count in the supplied callback.
> + */
> +int bus_for_each(void *data, int (*fn)(struct bus_type *, void *))
> +{
> + int error = 0;
> + struct bus_type *bus;
> + struct subsys_private *bus_prv;
> + struct kset *subsys;
> + struct kobject *k;
> +
> + spin_lock(&bus_kset->list_lock);
> +
> + list_for_each_entry(k, &bus_kset->list, entry) {
> + subsys = container_of(k, struct kset, kobj);
> + bus_prv = container_of(subsys, struct subsys_private, subsys);
> + bus = bus_prv->bus;
> + error = fn(bus, data);
> + if (error)
> + break;
> + }
> +
> + spin_unlock(&bus_kset->list_lock);
> + return error;
> +}
> +EXPORT_SYMBOL_GPL(bus_for_each);
> +
> /* Manually detach a device from its associated driver. */
> static ssize_t unbind_store(struct device_driver *drv, const char *buf,
> size_t count)
> diff --git a/drivers/base/mod_devicetable.c b/drivers/base/mod_devicetable.c
> new file mode 100644
> index 0000000000000..b04442207668c
> --- /dev/null
> +++ b/drivers/base/mod_devicetable.c
> @@ -0,0 +1,247 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * mod_devicetable.c - helpers for displaying modaliases through sysfs.
> + *
> + * This borrows a lot from file2alias.c
> + */
> +
> +#include <linux/device/bus.h>
> +#include <linux/device.h>
> +#include <linux/usb.h>
> +
> +#include "base.h"
> +#include "../usb/core/usb.h"
> +
> +#define ADD(buf, count, len, sep, cond, field) \
> +do { \
> + if (cond) \
> + (len) += scnprintf(&(buf)[len], \
> + (count) - (len), \
> + sizeof(field) == 1 ? (sep "%02X") : \
> + sizeof(field) == 2 ? (sep "%04X") : \
> + sizeof(field) == 4 ? (sep "%08X") : "", \
> + (field)); \
> + else \
> + (len) += scnprintf(&(buf)[len], (count) - (len), (sep "*")); \
> +} while (0)
> +
> +#ifdef CONFIG_USB
> +/* USB related modaliases can be split because of device number matching, so
> + * this function handles individual modaliases for one segment of the range.
> + *
> + *
> + */
> +static ssize_t usb_id_to_modalias(const struct usb_device_id *id,
> + unsigned int bcdDevice_initial,
> + int bcdDevice_initial_digits,
> + unsigned char range_lo,
> + unsigned char range_hi,
> + unsigned char max, const char *mod_name,
> + char *buf, size_t count)
> +{
> + ssize_t len = 0;
> +
> + ADD(buf, count, len, "alias usb:v",
> + id->match_flags & USB_DEVICE_ID_MATCH_VENDOR, id->idVendor);
> + ADD(buf, count, len, "p", id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT,
> + id->idProduct);
> +
> + len += scnprintf(&buf[len], count - len, "d");
> + if (bcdDevice_initial_digits)
> + len += scnprintf(&buf[len], count - len, "%0*X",
> + bcdDevice_initial_digits, bcdDevice_initial);
> + if (range_lo == range_hi) {
> + len += scnprintf(&buf[len], count - len, "%X", range_lo);
> + } else if (range_lo > 0 || range_hi < max) {
> + if (range_lo > 0x9 || range_hi < 0xA) {
> + len += scnprintf(&buf[len], count - len, "[%X-%X]",
> + range_lo, range_hi);
> + } else {
> + len += scnprintf(&buf[len], count - len,
> + range_lo < 0x9 ? "[%X-9" : "[%X",
> + range_lo);
> + len += scnprintf(&buf[len], count - len,
> + range_hi > 0xA ? "A-%X]" : "%X]",
> + range_hi);
> + }
> + }
> + if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
> + len += scnprintf(&buf[len], count - len, "*");
> +
> + ADD(buf, count, len, "dc",
> + id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS, id->bDeviceClass);
> + ADD(buf, count, len, "dsc",
> + id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
> + id->bDeviceSubClass);
> + ADD(buf, count, len, "dp",
> + id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
> + id->bDeviceProtocol);
> + ADD(buf, count, len, "ic",
> + id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS,
> + id->bInterfaceClass);
> + ADD(buf, count, len, "isc",
> + id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS,
> + id->bInterfaceSubClass);
> + ADD(buf, count, len, "ip",
> + id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL,
> + id->bInterfaceProtocol);
> + ADD(buf, count, len, "in",
> + id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER,
> + id->bInterfaceNumber);
> +
> + len += scnprintf(&buf[len], count - len, " %s\n", mod_name);
> + return len;
> +}
> +
> +/* Handles increment/decrement of BCD formatted integers */
> +/* Returns the previous value, so it works like i++ or i-- */
> +static unsigned int incbcd(unsigned int *bcd,
> + int inc,
> + unsigned char max,
> + size_t chars)
> +{
> + unsigned int init = *bcd, i, j;
> + unsigned long long c, dec = 0;
> +
> + /* If bcd is not in BCD format, just increment */
> + if (max > 0x9) {
> + *bcd += inc;
> + return init;
> + }
> +
> + /* Convert BCD to Decimal */
> + for (i = 0 ; i < chars ; i++) {
> + c = (*bcd >> (i << 2)) & 0xf;
> + c = c > 9 ? 9 : c; /* force to bcd just in case */
> + for (j = 0 ; j < i ; j++)
> + c = c * 10;
> + dec += c;
> + }
> +
> + /* Do our increment/decrement */
> + dec += inc;
> + *bcd = 0;
> +
> + /* Convert back to BCD */
> + for (i = 0 ; i < chars ; i++) {
> + for (c = 1, j = 0 ; j < i ; j++)
> + c = c * 10;
> + c = (dec / c) % 10;
> + *bcd += c << (i << 2);
> + }
> + return init;
> +}
> +
> +/* Print the modaliases for the specified struct usb_device_id.
> + */
> +static ssize_t usb_id_to_modalias_multi(const struct usb_device_id *id,
> + const char *mod_name, char *buf,
> + size_t count)
> +{
> + ssize_t len = 0;
> + unsigned int devlo, devhi;
> + unsigned char chi, clo, max;
> + int ndigits;
> +
> + devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
> + id->bcdDevice_lo : 0x0U;
> + devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
> + id->bcdDevice_hi : ~0x0U;
> +
> + /* Figure out if this entry is in bcd or hex format */
> + max = 0x9; /* Default to decimal format */
> + for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
> + clo = (devlo >> (ndigits << 2)) & 0xf;
> + chi = ((devhi > 0x9999 ? 0x9999 : devhi) >>
> + (ndigits << 2)) & 0xf;
> + if (clo > max || chi > max) {
> + max = 0xf;
> + break;
> + }
> + }
> +
> + /*
> + * Some modules (visor) have empty slots as placeholder for
> + * run-time specification that results in catch-all alias
> + */
> + if (!(id->idVendor || id->idProduct || id->bDeviceClass ||
> + id->bInterfaceClass))
> + return len;
> +
> + /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
> + for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi;
> + ndigits--) {
> + clo = devlo & 0xf;
> + chi = devhi & 0xf;
> + /* If we are in bcd mode, truncate if necessary */
> + if (chi > max)
> + chi = max;
> + devlo >>= 4;
> + devhi >>= 4;
> +
> + if (devlo == devhi || !ndigits) {
> + len += usb_id_to_modalias(id, devlo, ndigits, clo, chi,
> + max, mod_name, buf + len,
> + count - len);
> + break;
> + }
> +
> + if (clo > 0x0)
> + len += usb_id_to_modalias(id,
> + incbcd(&devlo, 1, max,
> + sizeof(id->bcdDevice_lo) * 2),
> + ndigits, clo, max, max, mod_name, buf + len,
> + count - len);
> +
> + if (chi < max)
> + len += usb_id_to_modalias(id,
> + incbcd(&devhi, -1, max,
> + sizeof(id->bcdDevice_lo) * 2),
> + ndigits, 0x0, chi, max, mod_name, buf + len,
> + count - len);
> + }
> + return len;
> +}
> +
> +/* Print the modaliases for the given driver assumed to be an usb_driver or
> + * usb_device_driver.
> + *
> + * "alias" is prepended and the module name is appended to each modalias to
> + * match the format in modules.aliases.
> + *
> + * The modaliases will be written out to @buf with @count being the maximum
> + * bytes to write. The return value is a negative errno on error or the number
> + * of bytes written to @buf on success.
> + */
> +ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
> + size_t count)
> +{
> + ssize_t len = 0;
> + const struct usb_device_id *id;
> + const char *mod_name;
> +
> + if (drv->bus != &usb_bus_type)
> + return -EINVAL;
> +
> + if (drv->owner)
> + mod_name = drv->owner->name;
> + else
> + mod_name = drv->mod_name;
> +
> + if (is_usb_device_driver(drv))
> + id = to_usb_device_driver(drv)->id_table;
> + else
> + id = to_usb_driver(drv)->id_table;
> + if (!id)
> + return len;
> +
> + for (; id->match_flags; id++) {
> + len += usb_id_to_modalias_multi(id, mod_name, buf + len,
> + count - len);
> + }
> + return len;
> +}
> +#else
> +inline ssize_t usb_drv_to_modalias(struct device_driver *drv, char *buf,
> + size_t count){ return 0; }
> +#endif
> diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
> index 7e7e119c253fb..fdbc197b64c9c 100644
> --- a/drivers/usb/core/driver.c
> +++ b/drivers/usb/core/driver.c
> @@ -32,6 +32,7 @@
> #include <linux/usb/quirks.h>
> #include <linux/usb/hcd.h>
>
> +#include "../../base/base.h"
> #include "usb.h"
>
>
> @@ -2030,4 +2031,5 @@ struct bus_type usb_bus_type = {
> .match = usb_device_match,
> .uevent = usb_uevent,
> .need_parent_lock = true,
> + .drv_to_modalias = usb_drv_to_modalias,
> };
> diff --git a/include/linux/device/bus.h b/include/linux/device/bus.h
> index d8b29ccd07e56..cce0bedec63d9 100644
> --- a/include/linux/device/bus.h
> +++ b/include/linux/device/bus.h
> @@ -61,6 +61,10 @@ struct fwnode_handle;
> * this bus.
> * @dma_cleanup: Called to cleanup DMA configuration on a device on
> * this bus.
> + * @drv_to_modalias: Called to convert the matching IDs in a
> + * struct device_driver to their corresponding modaliases.
> + * Note that the struct device_driver is expected to belong
> + * to this bus.
> * @pm: Power management operations of this bus, callback the specific
> * device driver's pm-ops.
> * @iommu_ops: IOMMU specific operations for this bus, used to attach IOMMU
> @@ -107,6 +111,9 @@ struct bus_type {
> int (*dma_configure)(struct device *dev);
> void (*dma_cleanup)(struct device *dev);
>
> + ssize_t (*drv_to_modalias)(struct device_driver *drv, char *buf,
> + size_t count);
> +
> const struct dev_pm_ops *pm;
>
> const struct iommu_ops *iommu_ops;
> @@ -161,6 +168,7 @@ void subsys_dev_iter_init(struct subsys_dev_iter *iter,
> struct device *subsys_dev_iter_next(struct subsys_dev_iter *iter);
> void subsys_dev_iter_exit(struct subsys_dev_iter *iter);
>
> +int bus_for_each(void *data, int (*fn)(struct bus_type *, void *));
> int bus_for_each_dev(struct bus_type *bus, struct device *start, void *data,
> int (*fn)(struct device *dev, void *data));
> struct device *bus_find_device(struct bus_type *bus, struct device *start,
> diff --git a/include/linux/module.h b/include/linux/module.h
> index ec61fb53979a9..0bfa859a21566 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -47,6 +47,7 @@ struct module_kobject {
> struct kobject *drivers_dir;
> struct module_param_attrs *mp;
> struct completion *kobj_completion;
> + struct bin_attribute modalias_attr;
> } __randomize_layout;
>
> struct module_attribute {
> diff --git a/kernel/module/internal.h b/kernel/module/internal.h
> index 2e2bf236f5582..8d7ae37584868 100644
> --- a/kernel/module/internal.h
> +++ b/kernel/module/internal.h
> @@ -259,11 +259,13 @@ static inline void add_kallsyms(struct module *mod, const struct load_info *info
> #endif /* CONFIG_KALLSYMS */
>
> #ifdef CONFIG_SYSFS
> +void add_modalias_attr(struct module_kobject *mk);
> int mod_sysfs_setup(struct module *mod, const struct load_info *info,
> struct kernel_param *kparam, unsigned int num_params);
> void mod_sysfs_teardown(struct module *mod);
> void init_param_lock(struct module *mod);
> #else /* !CONFIG_SYSFS */
> +static inline void add_modalias_attr(struct module_kobject *mk) {}
> static inline int mod_sysfs_setup(struct module *mod,
> const struct load_info *info,
> struct kernel_param *kparam,
> diff --git a/kernel/module/sysfs.c b/kernel/module/sysfs.c
> index ce68f821dcd12..e80bfa4639765 100644
> --- a/kernel/module/sysfs.c
> +++ b/kernel/module/sysfs.c
> @@ -5,6 +5,8 @@
> * Copyright (C) 2008 Rusty Russell
> */
>
> +#include <linux/device/bus.h>
> +#include <linux/device/driver.h>
> #include <linux/module.h>
> #include <linux/kernel.h>
> #include <linux/fs.h>
> @@ -240,6 +242,102 @@ static inline void add_notes_attrs(struct module *mod, const struct load_info *i
> static inline void remove_notes_attrs(struct module *mod) { }
> #endif /* CONFIG_KALLSYMS */
>
> +/* Track of the buffer and module identity in callbacks when walking the list of
> + * drivers for each bus.
> + */
> +struct modalias_bus_print_state {
> + struct module_kobject *mk;
> + char *buf;
> + size_t count;
> + ssize_t len;
> +};
> +
> +static int print_modalias_for_drv(struct device_driver *drv, void *p)
> +{
> + struct modalias_bus_print_state *s = p;
> + struct module_kobject *mk = s->mk;
> + ssize_t len;
> + /* Skip drivers that do not match this module. */
> + if (mk->mod) {
> + if (mk->mod != drv->owner)
> + return 0;
> + } else if (!mk->kobj.name || !drv->mod_name ||
> + strcmp(mk->kobj.name, drv->mod_name))
> + return 0;
> +
> + if (drv->bus && drv->bus->drv_to_modalias) {
> + len = drv->bus->drv_to_modalias(drv, s->buf + s->len,
> + s->count - s->len);
> + if (len < 0)
> + return len;
> + s->len += len;
> + }
> +
> + s->len += scnprintf(&s->buf[s->len], s->count - s->len, "driver %s\n",
> + drv->name);
> + return 0;
> +}
> +
> +static int print_modalias_for_bus(struct bus_type *type, void *p)
> +{
> + return bus_for_each_drv(type, NULL, p, print_modalias_for_drv);
> +}
> +
> +static ssize_t module_modalias_read(struct file *filp, struct kobject *kobj,
> + struct bin_attribute *bin_attr,
> + char *buf, loff_t pos, size_t count)
> +{
> + struct module_kobject *mk = container_of(kobj, struct module_kobject,
> + kobj);
> + struct modalias_bus_print_state state = {mk, buf, count, 0};
> + int error = 0;
> +
> + if (pos != 0)
> + return -EINVAL;
> +
> + error = bus_for_each(&state, print_modalias_for_bus);
> + if (error)
> + return error;
> +
> + if (mk->mod)
> + state.len += scnprintf(&buf[state.len], count - state.len,
> + "modalias %s %s\n", kobject_name(kobj),
> + mk->mod->name);
> + else
> + state.len += scnprintf(&buf[state.len], count - state.len,
> + "modalias %s NULL\n",
> + kobject_name(kobj));
> +
> + /*
> + * The caller checked the pos and count against our size.
> + */
> + return state.len;
> +}
> +
> +/* Used in kernel/params.c for builtin modules.
> + *
> + * `struct module_kobject` is used instead of `struct module` because for
> + * builtin modules, the `struct module` is not available when this is called.
> + */
> +void add_modalias_attr(struct module_kobject *mk)
> +{
> + sysfs_bin_attr_init(&mk->modalias_attr);
> + mk->modalias_attr.attr.name = "modalias";
> + mk->modalias_attr.attr.mode = 0444;
> + mk->modalias_attr.read = module_modalias_read;
> + if (sysfs_create_bin_file(&mk->kobj, &mk->modalias_attr)) {
> + /* We shouldn't ignore the return type, but there is nothing to
> + * do.
> + */
> + return;
> + }
> +}
> +
> +static void remove_modalias_attr(struct module_kobject *mk)
> +{
> + sysfs_remove_bin_file(&mk->kobj, &mk->modalias_attr);
> +}
> +
> static void del_usage_links(struct module *mod)
> {
> #ifdef CONFIG_MODULE_UNLOAD
> @@ -398,6 +496,7 @@ int mod_sysfs_setup(struct module *mod,
>
> add_sect_attrs(mod, info);
> add_notes_attrs(mod, info);
> + add_modalias_attr(&mod->mkobj);
>
> return 0;
>
> @@ -415,6 +514,7 @@ int mod_sysfs_setup(struct module *mod,
>
> static void mod_sysfs_fini(struct module *mod)
> {
> + remove_modalias_attr(&mod->mkobj);
> remove_notes_attrs(mod);
> remove_sect_attrs(mod);
> mod_kobject_put(mod);
> diff --git a/kernel/params.c b/kernel/params.c
> index 5b92310425c50..111024196361a 100644
> --- a/kernel/params.c
> +++ b/kernel/params.c
> @@ -13,6 +13,7 @@
> #include <linux/slab.h>
> #include <linux/ctype.h>
> #include <linux/security.h>
> +#include "module/internal.h"
>
> #ifdef CONFIG_SYSFS
> /* Protects all built-in parameters, modules use their own param_lock */
> @@ -815,6 +816,7 @@ static void __init kernel_add_sysfs_param(const char *name,
> BUG_ON(err);
> kobject_uevent(&mk->kobj, KOBJ_ADD);
> kobject_put(&mk->kobj);
> + add_modalias_attr(mk);
> }
>
> /*

2022-11-29 11:40:57

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

Hi Allen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on driver-core/driver-core-testing]
[also build test ERROR on driver-core/driver-core-next driver-core/driver-core-linus mcgrof/modules-next usb/usb-testing usb/usb-next usb/usb-linus linus/master v6.1-rc7 next-20221129]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221129-041511
patch link: https://lore.kernel.org/r/20221128201332.3482092-1-allenwebb%40google.com
patch subject: [PATCH] modules: add modalias file to sysfs for modules.
config: i386-defconfig
compiler: gcc-11 (Debian 11.3.0-8) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/5f45459f50fc0240781c397065e1b7bafcc79e08
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221129-041511
git checkout 5f45459f50fc0240781c397065e1b7bafcc79e08
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

ld: drivers/base/mod_devicetable.o: in function `incbcd.constprop.0':
>> mod_devicetable.c:(.text+0x67a): undefined reference to `__udivdi3'

--
0-DAY CI Kernel Test Service
https://01.org/lkp


Attachments:
(No filename) (1.74 kB)
config (136.46 kB)
Download all attachments

2022-11-30 02:49:57

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] modules: add modalias file to sysfs for modules.

Hi Allen,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on driver-core/driver-core-testing]
[also build test ERROR on driver-core/driver-core-next driver-core/driver-core-linus mcgrof/modules-next usb/usb-testing usb/usb-next usb/usb-linus linus/master v6.1-rc7 next-20221129]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221129-041511
patch link: https://lore.kernel.org/r/20221128201332.3482092-1-allenwebb%40google.com
patch subject: [PATCH] modules: add modalias file to sysfs for modules.
config: arm-buildonly-randconfig-r003-20221128
compiler: arm-linux-gnueabi-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/5f45459f50fc0240781c397065e1b7bafcc79e08
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Allen-Webb/modules-add-modalias-file-to-sysfs-for-modules/20221129-041511
git checkout 5f45459f50fc0240781c397065e1b7bafcc79e08
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

In file included from include/linux/container_of.h:5,
from include/linux/kernel.h:21,
from kernel/params.c:6:
kernel/module/internal.h: In function 'mod_find':
>> include/linux/container_of.h:20:54: error: invalid use of undefined type 'struct module'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/linux/rculist.h:391:20: note: in expansion of macro 'list_entry_rcu'
391 | pos = list_entry_rcu((head)->next, typeof(*pos), member); \
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:298:27: error: expression in static assertion is not an integer
298 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/linux/rculist.h:391:20: note: in expansion of macro 'list_entry_rcu'
391 | pos = list_entry_rcu((head)->next, typeof(*pos), member); \
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
In file included from include/uapi/linux/posix_types.h:5,
from include/uapi/linux/types.h:14,
from include/linux/types.h:6,
from include/linux/limits.h:6,
from include/linux/kernel.h:16:
>> include/linux/stddef.h:16:33: error: invalid use of undefined type 'struct module'
16 | #define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
| ^~~~~~~~~~~~~~~~~~
include/linux/container_of.h:23:28: note: in expansion of macro 'offsetof'
23 | ((type *)(__mptr - offsetof(type, member))); })
| ^~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/linux/rculist.h:391:20: note: in expansion of macro 'list_entry_rcu'
391 | pos = list_entry_rcu((head)->next, typeof(*pos), member); \
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
In file included from include/linux/pid.h:5,
from include/linux/sched.h:14,
from include/linux/sched/mm.h:7,
from include/linux/xarray.h:19,
from include/linux/radix-tree.h:21,
from include/linux/idr.h:15,
from include/linux/kernfs.h:12,
from include/linux/sysfs.h:16,
from include/linux/kobject.h:20,
from include/linux/module.h:21,
from kernel/params.c:9:
>> include/linux/rculist.h:392:21: error: invalid use of undefined type 'struct module'
392 | &pos->member != (head); \
| ^~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/container_of.h:19:33: note: in definition of macro 'container_of'
19 | void *__mptr = (void *)(ptr); \
| ^~~
include/linux/compiler_types.h:345:9: note: in expansion of macro '__compiletime_assert'
345 | __compiletime_assert(condition, msg, prefix, suffix)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:357:9: note: in expansion of macro '_compiletime_assert'
357 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:9: note: in expansion of macro 'compiletime_assert'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:28: note: in expansion of macro '__native_word'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~
include/asm-generic/rwonce.h:49:9: note: in expansion of macro 'compiletime_assert_rwonce_type'
49 | compiletime_assert_rwonce_type(x); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/container_of.h:19:33: note: in definition of macro 'container_of'
19 | void *__mptr = (void *)(ptr); \
| ^~~
include/linux/compiler_types.h:345:9: note: in expansion of macro '__compiletime_assert'
345 | __compiletime_assert(condition, msg, prefix, suffix)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:357:9: note: in expansion of macro '_compiletime_assert'
357 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:9: note: in expansion of macro 'compiletime_assert'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:28: note: in expansion of macro '__native_word'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~
include/asm-generic/rwonce.h:49:9: note: in expansion of macro 'compiletime_assert_rwonce_type'
49 | compiletime_assert_rwonce_type(x); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/container_of.h:19:33: note: in definition of macro 'container_of'
19 | void *__mptr = (void *)(ptr); \
| ^~~
include/linux/compiler_types.h:345:9: note: in expansion of macro '__compiletime_assert'
345 | __compiletime_assert(condition, msg, prefix, suffix)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:357:9: note: in expansion of macro '_compiletime_assert'
357 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:9: note: in expansion of macro 'compiletime_assert'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:28: note: in expansion of macro '__native_word'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~
include/asm-generic/rwonce.h:49:9: note: in expansion of macro 'compiletime_assert_rwonce_type'
49 | compiletime_assert_rwonce_type(x); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/container_of.h:19:33: note: in definition of macro 'container_of'
19 | void *__mptr = (void *)(ptr); \
--
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/linux/compiler_types.h:345:9: note: in expansion of macro '__compiletime_assert'
345 | __compiletime_assert(condition, msg, prefix, suffix)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:357:9: note: in expansion of macro '_compiletime_assert'
357 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:9: note: in expansion of macro 'compiletime_assert'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:49:9: note: in expansion of macro 'compiletime_assert_rwonce_type'
49 | compiletime_assert_rwonce_type(x); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/asm-generic/rwonce.h:44:43: note: in expansion of macro '__unqual_scalar_typeof'
44 | #define __READ_ONCE(x) (*(const volatile __unqual_scalar_typeof(x) *)&(x))
| ^~~~~~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:50:9: note: in expansion of macro '__READ_ONCE'
50 | __READ_ONCE(x); \
| ^~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/asm-generic/rwonce.h:50:9: note: in expansion of macro '__READ_ONCE'
50 | __READ_ONCE(x); \
| ^~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
>> include/linux/container_of.h:20:54: error: invalid use of undefined type 'struct module'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:21:23: note: in expansion of macro '__same_type'
21 | __same_type(*(ptr), void), \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/linux/compiler_types.h:345:9: note: in expansion of macro '__compiletime_assert'
345 | __compiletime_assert(condition, msg, prefix, suffix)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:357:9: note: in expansion of macro '_compiletime_assert'
357 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:9: note: in expansion of macro 'compiletime_assert'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:28: note: in expansion of macro '__native_word'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~
include/asm-generic/rwonce.h:49:9: note: in expansion of macro 'compiletime_assert_rwonce_type'
49 | compiletime_assert_rwonce_type(x); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~
include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
| ^~~~
include/linux/container_of.h:20:9: note: in expansion of macro 'static_assert'
20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
| ^~~~~~~~~~~~~
include/linux/container_of.h:21:23: note: in expansion of macro '__same_type'
21 | __same_type(*(ptr), void), \
| ^~~~~~~~~~~
include/linux/rculist.h:307:9: note: in expansion of macro 'container_of'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~~~~
include/linux/compiler_types.h:345:9: note: in expansion of macro '__compiletime_assert'
345 | __compiletime_assert(condition, msg, prefix, suffix)
| ^~~~~~~~~~~~~~~~~~~~
include/linux/compiler_types.h:357:9: note: in expansion of macro '_compiletime_assert'
357 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:9: note: in expansion of macro 'compiletime_assert'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~~~~~~
include/asm-generic/rwonce.h:36:28: note: in expansion of macro '__native_word'
36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \
| ^~~~~~~~~~~~~
include/asm-generic/rwonce.h:49:9: note: in expansion of macro 'compiletime_assert_rwonce_type'
49 | compiletime_assert_rwonce_type(x); \
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:307:22: note: in expansion of macro 'READ_ONCE'
307 | container_of(READ_ONCE(ptr), type, member)
| ^~~~~~~~~
include/linux/rculist.h:393:23: note: in expansion of macro 'list_entry_rcu'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
| ^~~~~~~~~~~~~~
kernel/module/internal.h:212:9: note: in expansion of macro 'list_for_each_entry_rcu'
212 | list_for_each_entry_rcu(mod, &modules, list,
| ^~~~~~~~~~~~~~~~~~~~~~~
include/linux/rculist.h:393:41: error: invalid use of undefined type 'struct module'
393 | pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
..


vim +20 include/linux/container_of.h

d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 9
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 10 /**
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 11 * container_of - cast a member of a structure out to the containing structure
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 12 * @ptr: the pointer to the member.
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 13 * @type: the type of the container struct this is embedded in.
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 14 * @member: the name of the member within the struct.
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 15 *
7376e561fd2e01 Sakari Ailus 2022-10-24 16 * WARNING: any const qualifier of @ptr is lost.
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 17 */
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 18 #define container_of(ptr, type, member) ({ \
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 19 void *__mptr = (void *)(ptr); \
e1edc277e6f6df Rasmus Villemoes 2021-11-08 @20 static_assert(__same_type(*(ptr), ((type *)0)->member) || \
e1edc277e6f6df Rasmus Villemoes 2021-11-08 21 __same_type(*(ptr), void), \
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 22 "pointer type mismatch in container_of()"); \
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 23 ((type *)(__mptr - offsetof(type, member))); })
d2a8ebbf8192b8 Andy Shevchenko 2021-11-08 24

--
0-DAY CI Kernel Test Service
https://01.org/lkp


Attachments:
(No filename) (29.17 kB)
config (139.18 kB)
Download all attachments