diff options
| author | Mark Brown <broonie@kernel.org> | 2026-09-30 13:35:23 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-09-30 13:35:23 +0100 |
| commit | e650bf0d64f98b8ea28f99811de7a78e8fc55bb6 (patch) | |
| tree | 7df444bf9100a44db387e9339a842d5abc0f5343 | |
| parent | e33aa711e77b3b62454b357c29f6a109e7dba52e (diff) | |
| parent | f1850e443b0e4f2429ddf42a8d5033ea54ae8a90 (diff) | |
| download | linux-next-e650bf0d64f98b8ea28f99811de7a78e8fc55bb6.tar.gz linux-next-e650bf0d64f98b8ea28f99811de7a78e8fc55bb6.zip | |
Merge branch 'driver-core-next' of https://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core.git
38 files changed, 180 insertions, 119 deletions
diff --git a/Documentation/admin-guide/tainted-kernels.rst b/Documentation/admin-guide/tainted-kernels.rst index 9ead927a37c0..a208811ad525 100644 --- a/Documentation/admin-guide/tainted-kernels.rst +++ b/Documentation/admin-guide/tainted-kernels.rst @@ -74,35 +74,36 @@ a particular type of taint. It's best to leave that to the aforementioned script, but if you need something quick you can use this shell command to check which bits are set:: - $ for i in $(seq 20); do echo $(($i-1)) $(($(cat /proc/sys/kernel/tainted)>>($i-1)&1));done + $ for i in $(seq 0 20); do echo $i $(($(cat /proc/sys/kernel/tainted)>>$i&1));done Table for decoding tainted state ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -=== === ====== ======================================================== -Bit Log Number Reason that got the kernel tainted -=== === ====== ======================================================== - 0 G/P 1 proprietary module was loaded - 1 _/F 2 module was force loaded - 2 _/S 4 kernel running on an out of specification system - 3 _/R 8 module was force unloaded - 4 _/M 16 processor reported a Machine Check Exception (MCE) - 5 _/B 32 bad page referenced or some unexpected page flags - 6 _/U 64 taint requested by userspace application - 7 _/D 128 kernel died recently, i.e. there was an OOPS or BUG - 8 _/A 256 ACPI table overridden by user - 9 _/W 512 kernel issued warning - 10 _/C 1024 staging driver was loaded - 11 _/I 2048 workaround for bug in platform firmware applied - 12 _/O 4096 externally-built ("out-of-tree") module was loaded - 13 _/E 8192 unsigned module was loaded - 14 _/L 16384 soft lockup occurred - 15 _/K 32768 kernel has been live patched - 16 _/X 65536 auxiliary taint, defined for and used by distros - 17 _/T 131072 kernel was built with the struct randomization plugin - 18 _/N 262144 an in-kernel test has been run - 19 _/J 524288 userspace used a mutating debug operation in fwctl -=== === ====== ======================================================== +=== === ======= ======================================================== +Bit Log Number Reason that got the kernel tainted +=== === ======= ======================================================== + 0 G/P 1 proprietary module was loaded + 1 _/F 2 module was force loaded + 2 _/S 4 kernel running on an out of specification system + 3 _/R 8 module was force unloaded + 4 _/M 16 processor reported a Machine Check Exception (MCE) + 5 _/B 32 bad page referenced or some unexpected page flags + 6 _/U 64 taint requested by userspace application + 7 _/D 128 kernel died recently, i.e. there was an OOPS or BUG + 8 _/A 256 ACPI table overridden by user + 9 _/W 512 kernel issued warning + 10 _/C 1024 staging driver was loaded + 11 _/I 2048 workaround for bug in platform firmware applied + 12 _/O 4096 externally-built ("out-of-tree") module was loaded + 13 _/E 8192 unsigned module was loaded + 14 _/L 16384 soft lockup occurred + 15 _/K 32768 kernel has been live patched + 16 _/X 65536 auxiliary taint, defined for and used by distros + 17 _/T 131072 kernel was built with the struct randomization plugin + 18 _/N 262144 an in-kernel test has been run + 19 _/J 524288 userspace used a mutating debug operation in fwctl + 20 _/Y 1048576 device was manually bound or unbound from a driver +=== === ======= ======================================================== Note: The character ``_`` is representing a blank in this table to make reading easier. @@ -189,3 +190,6 @@ More detailed explanation for tainting 19) ``J`` if userspace opened /dev/fwctl/* and performed a FWTCL_RPC_DEBUG_WRITE to use the devices debugging features. Device debugging features could cause the device to malfunction in undefined ways. + + 20) ``Y`` If userspace wrote to the `bind` or `unbind` sysfs files and + successfully bound or removed a device from a driver. diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index b0eedf185960..3e094dc7d76b 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c @@ -462,7 +462,7 @@ static struct attribute *device_str_attr_create_(char *name, char *str) attr->var = str; attr->attr.attr.name = name; attr->attr.attr.mode = 0444; - attr->attr.show = device_show_string; + attr->attr.show_const = device_show_string; return &attr->attr.attr; } diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c index 39f238952e14..50b1614968be 100644 --- a/arch/x86/kernel/cpu/mce/core.c +++ b/arch/x86/kernel/cpu/mce/core.c @@ -2614,17 +2614,17 @@ static DEVICE_BOOL_ATTR(dont_log_ce, 0644, mca_cfg.dont_log_ce); static DEVICE_BOOL_ATTR(print_all, 0644, mca_cfg.print_all); static struct dev_ext_attribute dev_attr_check_interval = { - __ATTR(check_interval, 0644, device_show_int, store_int_with_restart), + __DEVICE_ATTR(check_interval, 0644, device_show_int, store_int_with_restart), &check_interval }; static struct dev_ext_attribute dev_attr_ignore_ce = { - __ATTR(ignore_ce, 0644, device_show_bool, set_ignore_ce), + __DEVICE_ATTR(ignore_ce, 0644, device_show_bool, set_ignore_ce), &mca_cfg.ignore_ce }; static struct dev_ext_attribute dev_attr_cmci_disabled = { - __ATTR(cmci_disabled, 0644, device_show_bool, set_cmci_disabled), + __DEVICE_ATTR(cmci_disabled, 0644, device_show_bool, set_cmci_disabled), &mca_cfg.cmci_disabled }; diff --git a/drivers/base/bus.c b/drivers/base/bus.c index d89333806a4e..18f12c6f910a 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -19,6 +19,7 @@ #include <linux/string.h> #include <linux/mutex.h> #include <linux/sysfs.h> +#include <linux/panic.h> #include "base.h" #include "power/power.h" @@ -241,6 +242,7 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf, dev = bus_find_device_by_name(bus, NULL, buf); if (dev && dev->driver == drv) { + add_taint_module(drv->owner, TAINT_FORCED_BIND, LOCKDEP_STILL_OK); device_driver_detach(dev); err = count; } @@ -264,6 +266,7 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, dev = bus_find_device_by_name(bus, NULL, buf); if (dev && driver_match_device(drv, dev)) { + add_taint_module(drv->owner, TAINT_FORCED_BIND, LOCKDEP_STILL_OK); err = device_driver_attach(drv, dev); if (!err) { /* success */ diff --git a/drivers/base/core.c b/drivers/base/core.c index 4c0c373998a1..5daa88fa724a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2517,13 +2517,13 @@ static const struct sysfs_ops dev_sysfs_ops = { .store = dev_attr_store, }; -#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr) +#define to_ext_attr(x) container_of_const(x, struct dev_ext_attribute, attr) ssize_t device_store_ulong(struct device *dev, - struct device_attribute *attr, + const struct device_attribute *attr, const char *buf, size_t size) { - struct dev_ext_attribute *ea = to_ext_attr(attr); + const struct dev_ext_attribute *ea = to_ext_attr(attr); int ret; unsigned long new; @@ -2537,19 +2537,19 @@ ssize_t device_store_ulong(struct device *dev, EXPORT_SYMBOL_GPL(device_store_ulong); ssize_t device_show_ulong(struct device *dev, - struct device_attribute *attr, + const struct device_attribute *attr, char *buf) { - struct dev_ext_attribute *ea = to_ext_attr(attr); + const struct dev_ext_attribute *ea = to_ext_attr(attr); return sysfs_emit(buf, "%lx\n", *(unsigned long *)(ea->var)); } EXPORT_SYMBOL_GPL(device_show_ulong); ssize_t device_store_int(struct device *dev, - struct device_attribute *attr, + const struct device_attribute *attr, const char *buf, size_t size) { - struct dev_ext_attribute *ea = to_ext_attr(attr); + const struct dev_ext_attribute *ea = to_ext_attr(attr); int ret; long new; @@ -2566,19 +2566,19 @@ ssize_t device_store_int(struct device *dev, EXPORT_SYMBOL_GPL(device_store_int); ssize_t device_show_int(struct device *dev, - struct device_attribute *attr, + const struct device_attribute *attr, char *buf) { - struct dev_ext_attribute *ea = to_ext_attr(attr); + const struct dev_ext_attribute *ea = to_ext_attr(attr); return sysfs_emit(buf, "%d\n", *(int *)(ea->var)); } EXPORT_SYMBOL_GPL(device_show_int); -ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, +ssize_t device_store_bool(struct device *dev, const struct device_attribute *attr, const char *buf, size_t size) { - struct dev_ext_attribute *ea = to_ext_attr(attr); + const struct dev_ext_attribute *ea = to_ext_attr(attr); if (kstrtobool(buf, ea->var) < 0) return -EINVAL; @@ -2587,19 +2587,19 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, } EXPORT_SYMBOL_GPL(device_store_bool); -ssize_t device_show_bool(struct device *dev, struct device_attribute *attr, +ssize_t device_show_bool(struct device *dev, const struct device_attribute *attr, char *buf) { - struct dev_ext_attribute *ea = to_ext_attr(attr); + const struct dev_ext_attribute *ea = to_ext_attr(attr); return sysfs_emit(buf, "%d\n", *(bool *)(ea->var)); } EXPORT_SYMBOL_GPL(device_show_bool); ssize_t device_show_string(struct device *dev, - struct device_attribute *attr, char *buf) + const struct device_attribute *attr, char *buf) { - struct dev_ext_attribute *ea = to_ext_attr(attr); + const struct dev_ext_attribute *ea = to_ext_attr(attr); return sysfs_emit(buf, "%s\n", (char *)ea->var); } diff --git a/drivers/base/node.c b/drivers/base/node.c index 3da91929ad4e..dcdc8626627a 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -167,20 +167,19 @@ static struct node_access_nodes *node_init_node_access(struct node *node, dev->parent = &node->dev; dev->release = node_access_release; dev->groups = node_access_node_groups; - if (dev_set_name(dev, "access%u", access)) - goto free; + if (dev_set_name(dev, "access%u", access)) { + kfree(access_node); + return NULL; + } - if (device_register(dev)) - goto free_name; + if (device_register(dev)) { + put_device(dev); + return NULL; + } pm_runtime_no_callbacks(dev); list_add_tail(&access_node->list_node, &node->access_list); return access_node; -free_name: - kfree_const(dev->kobj.name); -free: - kfree(access_node); - return NULL; } #ifdef CONFIG_HMEM_REPORTING diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 66f9ec73d47e..3593d45f4a7a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -632,16 +632,17 @@ struct platform_device *platform_device_alloc(const char *name, int id) struct platform_object *pa; pa = kzalloc(sizeof(*pa) + strlen(name) + 1, GFP_KERNEL); - if (pa) { - strcpy(pa->name, name); - pa->pdev.name = pa->name; - pa->pdev.id = id; - device_initialize(&pa->pdev.dev); - pa->pdev.dev.release = platform_device_release; - setup_pdev_dma_masks(&pa->pdev); - } + if (!pa) + return NULL; + + strcpy(pa->name, name); + pa->pdev.name = pa->name; + pa->pdev.id = id; + device_initialize(&pa->pdev.dev); + pa->pdev.dev.release = platform_device_release; + setup_pdev_dma_masks(&pa->pdev); - return pa ? &pa->pdev : NULL; + return &pa->pdev; } EXPORT_SYMBOL_GPL(platform_device_alloc); diff --git a/drivers/base/property.c b/drivers/base/property.c index cceaa3240ca4..51109794d727 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -705,7 +705,7 @@ bool fwnode_name_eq(const struct fwnode_handle *fwnode, const char *name) EXPORT_SYMBOL_GPL(fwnode_name_eq); /** - * fwnode_get_parent - Return parent firwmare node + * fwnode_get_parent - Return parent firmware node * @fwnode: Firmware whose parent is retrieved * * The caller is responsible for calling fwnode_handle_put() on the returned diff --git a/drivers/base/transport_class.c b/drivers/base/transport_class.c index 351c3d3ce6a0..2bee796601ed 100644 --- a/drivers/base/transport_class.c +++ b/drivers/base/transport_class.c @@ -7,7 +7,7 @@ * * The basic idea here is to allow any "device controller" (which * would most often be a Host Bus Adapter to use the services of one - * or more tranport classes for performing transport specific + * or more transport classes for performing transport specific * services. Transport specific services are things that the generic * command layer doesn't want to know about (speed settings, line * condidtioning, etc), but which the user might be interested in. diff --git a/drivers/perf/alibaba_uncore_drw_pmu.c b/drivers/perf/alibaba_uncore_drw_pmu.c index fc934bccf4a6..5b6d3a4736da 100644 --- a/drivers/perf/alibaba_uncore_drw_pmu.c +++ b/drivers/perf/alibaba_uncore_drw_pmu.c @@ -135,7 +135,7 @@ static ssize_t ali_drw_pmu_event_show(struct device *dev, #define ALI_DRW_PMU_ATTR(_name, _func, _config) \ (&((struct dev_ext_attribute[]) { \ - { __ATTR(_name, 0444, _func, NULL), (void *)_config } \ + { __DEVICE_ATTR(_name, 0444, _func, NULL), (void *)_config } \ })[0].attr.attr) #define ALI_DRW_PMU_FORMAT_ATTR(_name, _config) \ diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c index f0ef0a679e74..71035227f58b 100644 --- a/drivers/perf/arm-cci.c +++ b/drivers/perf/arm-cci.c @@ -132,7 +132,7 @@ static ssize_t __maybe_unused cci_pmu_event_show(struct device *dev, #define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \ &((struct dev_ext_attribute[]) { \ - { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_config } \ + { __DEVICE_ATTR(_name, S_IRUGO, _func, NULL), (void *)_config } \ })[0].attr.attr #define CCI_FORMAT_EXT_ATTR_ENTRY(_name, _config) \ diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c index c40da3450c8f..e3411bdf5c7c 100644 --- a/drivers/perf/arm-ccn.c +++ b/drivers/perf/arm-ccn.c @@ -216,7 +216,7 @@ static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port) #define CCN_FORMAT_ATTR(_name, _config) \ struct dev_ext_attribute arm_ccn_pmu_format_attr_##_name = \ - { __ATTR(_name, S_IRUGO, device_show_string, \ + { __DEVICE_ATTR(_name, S_IRUGO, device_show_string, \ NULL), _config } static CCN_FORMAT_ATTR(node, "config:0-7"); diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h index c4058d602477..93d5b062de8b 100644 --- a/drivers/perf/arm_cspmu/arm_cspmu.h +++ b/drivers/perf/arm_cspmu/arm_cspmu.h @@ -23,7 +23,7 @@ #define ARM_CSPMU_EXT_ATTR(_name, _func, _config) \ (&((struct dev_ext_attribute[]){ \ { \ - .attr = __ATTR(_name, 0444, _func, NULL), \ + .attr = __DEVICE_ATTR(_name, 0444, _func, NULL),\ .var = (void *)_config \ } \ })[0].attr.attr) diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c index bcbd19e075a5..8332eaca06dc 100644 --- a/drivers/perf/arm_dsu_pmu.c +++ b/drivers/perf/arm_dsu_pmu.c @@ -69,7 +69,7 @@ #define DSU_EXT_ATTR(_name, _func, _config) \ (&((struct dev_ext_attribute[]) { \ { \ - .attr = __ATTR(_name, 0444, _func, NULL), \ + .attr = __DEVICE_ATTR(_name, 0444, _func, NULL),\ .var = (void *)_config \ } \ })[0].attr.attr) diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index b70f3fedf028..e298d6d6371e 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c @@ -172,9 +172,9 @@ static ssize_t arm_spe_pmu_cap_show_hex(struct device *dev, return sysfs_emit(buf, "0x%llx\n", arm_spe_pmu_cap_get(spe_pmu, cap)); } -#define SPE_EXT_ATTR_ENTRY(_name, _func, _var) \ - &((struct dev_ext_attribute[]) { \ - { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_var } \ +#define SPE_EXT_ATTR_ENTRY(_name, _func, _var) \ + &((struct dev_ext_attribute[]) { \ + { __DEVICE_ATTR(_name, S_IRUGO, _func, NULL), (void *)_var } \ })[0].attr.attr #define SPE_CAP_EXT_ATTR_ENTRY(_name, _var) \ diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c index 2c8a03cc11e4..a36cf792a2d0 100644 --- a/drivers/perf/cxl_pmu.c +++ b/drivers/perf/cxl_pmu.c @@ -216,11 +216,11 @@ static int cxl_pmu_parse_caps(struct device *dev, struct cxl_pmu_info *info) } #define CXL_PMU_FORMAT_ATTR(_name, _format)\ - (&((struct dev_ext_attribute[]) { \ - { \ - .attr = __ATTR(_name, 0444, device_show_string, NULL), \ - .var = (void *)_format \ - } \ + (&((struct dev_ext_attribute[]) { \ + { \ + .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL), \ + .var = (void *)_format \ + } \ })[0].attr.attr) enum { diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c index dd8046265584..7553c5872600 100644 --- a/drivers/perf/fsl_imx8_ddr_perf.c +++ b/drivers/perf/fsl_imx8_ddr_perf.c @@ -214,7 +214,7 @@ static ssize_t ddr_perf_filter_cap_show(struct device *dev, #define PERF_EXT_ATTR_ENTRY(_name, _func, _var) \ (&((struct dev_ext_attribute) { \ - __ATTR(_name, 0444, _func, NULL), (void *)_var \ + __DEVICE_ATTR(_name, 0444, _func, NULL), (void *)_var \ }).attr.attr) #define PERF_FILTER_EXT_ATTR_ENTRY(_name, _var) \ diff --git a/drivers/perf/fujitsu_uncore_pmu.c b/drivers/perf/fujitsu_uncore_pmu.c index fa64146fcac6..db90e181b9a8 100644 --- a/drivers/perf/fujitsu_uncore_pmu.c +++ b/drivers/perf/fujitsu_uncore_pmu.c @@ -291,7 +291,7 @@ static void fujitsu_uncore_event_read(struct perf_event *event) #define UNCORE_PMU_FORMAT_ATTR(_name, _config) \ (&((struct dev_ext_attribute[]) { \ - { .attr = __ATTR(_name, 0444, device_show_string, NULL), \ + { .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL), \ .var = (void *)_config, } \ })[0].attr.attr) diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c index 0f55d871c67e..0a69d13fa453 100644 --- a/drivers/perf/hisilicon/hisi_pcie_pmu.c +++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c @@ -110,7 +110,7 @@ static ssize_t hisi_pcie_event_sysfs_show(struct device *dev, struct device_attr #define HISI_PCIE_PMU_FORMAT_ATTR(_name, _format) \ (&((struct dev_ext_attribute[]){ \ - { .attr = __ATTR(_name, 0444, device_show_string, NULL), \ + { .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL),\ .var = (void *)_format } \ })[0].attr.attr) diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h index 3ffe6acda653..a4cb9ed7ea20 100644 --- a/drivers/perf/hisilicon/hisi_uncore_pmu.h +++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h @@ -27,9 +27,9 @@ #define HISI_MAX_COUNTERS 0x18 #define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu)) -#define HISI_PMU_ATTR(_name, _func, _config) \ - (&((struct dev_ext_attribute[]) { \ - { __ATTR(_name, 0444, _func, NULL), (void *)_config } \ +#define HISI_PMU_ATTR(_name, _func, _config) \ + (&((struct dev_ext_attribute[]) { \ + { __DEVICE_ATTR(_name, 0444, _func, NULL), (void *)_config } \ })[0].attr.attr) #define HISI_PMU_FORMAT_ATTR(_name, _config) \ diff --git a/drivers/perf/hisilicon/hns3_pmu.c b/drivers/perf/hisilicon/hns3_pmu.c index c157f3572cae..88a1129e9b90 100644 --- a/drivers/perf/hisilicon/hns3_pmu.c +++ b/drivers/perf/hisilicon/hns3_pmu.c @@ -405,9 +405,9 @@ static ssize_t hns3_pmu_filter_mode_show(struct device *dev, return len; } -#define HNS3_PMU_ATTR(_name, _func, _config) \ - (&((struct dev_ext_attribute[]) { \ - { __ATTR(_name, 0444, _func, NULL), (void *)_config } \ +#define HNS3_PMU_ATTR(_name, _func, _config) \ + (&((struct dev_ext_attribute[]) { \ + { __DEVICE_ATTR(_name, 0444, _func, NULL), (void *)_config } \ })[0].attr.attr) #define HNS3_PMU_FORMAT_ATTR(_name, _format) \ diff --git a/drivers/perf/nvidia_t410_c2c_pmu.c b/drivers/perf/nvidia_t410_c2c_pmu.c index bff875f4f625..a41d5712da91 100644 --- a/drivers/perf/nvidia_t410_c2c_pmu.c +++ b/drivers/perf/nvidia_t410_c2c_pmu.c @@ -545,7 +545,7 @@ static struct attribute_group nv_c2c_pmu_peer_attr_group = { #define NV_C2C_PMU_EXT_ATTR(_name, _func, _config) \ (&((struct dev_ext_attribute[]){ \ { \ - .attr = __ATTR(_name, 0444, _func, NULL), \ + .attr = __DEVICE_ATTR(_name, 0444, _func, NULL),\ .var = (void *)_config \ } \ })[0].attr.attr) diff --git a/drivers/perf/nvidia_t410_cmem_latency_pmu.c b/drivers/perf/nvidia_t410_cmem_latency_pmu.c index 6c8e41598ec1..da91a51fe29e 100644 --- a/drivers/perf/nvidia_t410_cmem_latency_pmu.c +++ b/drivers/perf/nvidia_t410_cmem_latency_pmu.c @@ -435,12 +435,12 @@ static struct attribute_group cmem_lat_pmu_identifier_attr_group = { /* Format attributes. */ -#define NV_PMU_EXT_ATTR(_name, _func, _config) \ - (&((struct dev_ext_attribute[]){ \ - { \ - .attr = __ATTR(_name, 0444, _func, NULL), \ - .var = (void *)_config \ - } \ +#define NV_PMU_EXT_ATTR(_name, _func, _config) \ + (&((struct dev_ext_attribute[]){ \ + { \ + .attr = __DEVICE_ATTR(_name, 0444, _func, NULL), \ + .var = (void *)_config \ + } \ })[0].attr.attr) static struct attribute *cmem_lat_pmu_formats[] = { diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c index e18d0f94e8d8..d036fa05aeab 100644 --- a/drivers/perf/qcom_l3_pmu.c +++ b/drivers/perf/qcom_l3_pmu.c @@ -609,10 +609,10 @@ static void qcom_l3_cache__event_read(struct perf_event *event) /* formats */ -#define L3CACHE_PMU_FORMAT_ATTR(_name, _config) \ - (&((struct dev_ext_attribute[]) { \ - { .attr = __ATTR(_name, 0444, device_show_string, NULL), \ - .var = (void *) _config, } \ +#define L3CACHE_PMU_FORMAT_ATTR(_name, _config) \ + (&((struct dev_ext_attribute[]) { \ + { .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL), \ + .var = (void *) _config, } \ })[0].attr.attr) static struct attribute *qcom_l3_cache_pmu_formats[] = { diff --git a/drivers/perf/starfive_starlink_pmu.c b/drivers/perf/starfive_starlink_pmu.c index 98e5ccee2fdc..d9843645554b 100644 --- a/drivers/perf/starfive_starlink_pmu.c +++ b/drivers/perf/starfive_starlink_pmu.c @@ -51,7 +51,7 @@ #define STARLINK_FORMAT_ATTR(_name, _config) \ (&((struct dev_ext_attribute[]) { \ - { .attr = __ATTR(_name, 0444, starlink_pmu_sysfs_format_show, NULL), \ + { .attr = __DEVICE_ATTR(_name, 0444, starlink_pmu_sysfs_format_show, NULL), \ .var = (void *)_config, } \ })[0].attr.attr) diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c index ab3623fab914..104cd0277b58 100644 --- a/drivers/perf/xgene_pmu.c +++ b/drivers/perf/xgene_pmu.c @@ -164,7 +164,7 @@ enum xgene_pmu_dev_type { */ #define XGENE_PMU_FORMAT_ATTR(_name, _config) \ (&((struct dev_ext_attribute[]) { \ - { .attr = __ATTR(_name, S_IRUGO, device_show_string, NULL), \ + { .attr = __DEVICE_ATTR(_name, S_IRUGO, device_show_string, NULL), \ .var = (void *) _config, } \ })[0].attr.attr) diff --git a/include/linux/device.h b/include/linux/device.h index aee79fd6b32b..90cdd77458bb 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -129,19 +129,19 @@ struct dev_ext_attribute { void *var; }; -ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr, +ssize_t device_show_ulong(struct device *dev, const struct device_attribute *attr, char *buf); -ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr, +ssize_t device_store_ulong(struct device *dev, const struct device_attribute *attr, const char *buf, size_t count); -ssize_t device_show_int(struct device *dev, struct device_attribute *attr, +ssize_t device_show_int(struct device *dev, const struct device_attribute *attr, char *buf); -ssize_t device_store_int(struct device *dev, struct device_attribute *attr, +ssize_t device_store_int(struct device *dev, const struct device_attribute *attr, const char *buf, size_t count); -ssize_t device_show_bool(struct device *dev, struct device_attribute *attr, +ssize_t device_show_bool(struct device *dev, const struct device_attribute *attr, char *buf); -ssize_t device_store_bool(struct device *dev, struct device_attribute *attr, +ssize_t device_store_bool(struct device *dev, const struct device_attribute *attr, const char *buf, size_t count); -ssize_t device_show_string(struct device *dev, struct device_attribute *attr, +ssize_t device_show_string(struct device *dev, const struct device_attribute *attr, char *buf); typedef ssize_t __device_show_handler_const(struct device *dev, const struct device_attribute *attr, diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index 351a5101c862..73786b567ccd 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h @@ -309,7 +309,7 @@ struct kernfs_ops { * write() is bounced through kernel buffer. If atomic_write_len * is not set, a write larger than PAGE_SIZE results in partial * operations of PAGE_SIZE chunks. If atomic_write_len is set, - * writes upto the specified size are executed atomically but + * writes up to the specified size are executed atomically but * larger ones are rejected with -E2BIG. */ size_t atomic_write_len; diff --git a/include/linux/module.h b/include/linux/module.h index 96cc98568eea..f6f90cd88f15 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -29,6 +29,7 @@ #include <linux/srcu.h> #include <linux/static_call_types.h> #include <linux/dynamic_debug.h> +#include <linux/panic.h> #include <linux/percpu.h> #include <asm/module.h> @@ -770,6 +771,9 @@ static inline bool is_livepatch_module(struct module *mod) void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data); +void add_taint_module(struct module *mod, unsigned flag, + enum lockdep_ok lockdep_ok); + #else /* !CONFIG_MODULES... */ static inline struct module *__module_address(unsigned long addr) @@ -877,6 +881,12 @@ static inline bool module_is_coming(struct module *mod) static inline void module_for_each_mod(int(*func)(struct module *mod, void *data), void *data) { } + +static inline void add_taint_module(struct module *mod, unsigned flag, + enum lockdep_ok lockdep_ok) +{ + add_taint(flag, lockdep_ok); +} #endif /* CONFIG_MODULES */ #ifdef CONFIG_SYSFS diff --git a/include/linux/panic.h b/include/linux/panic.h index 17e61b61c45f..23976b1dfdb6 100644 --- a/include/linux/panic.h +++ b/include/linux/panic.h @@ -89,7 +89,8 @@ static inline void set_arch_panic_timeout(int timeout, int arch_default_timeout) #define TAINT_RANDSTRUCT 17 #define TAINT_TEST 18 #define TAINT_FWCTL 19 -#define TAINT_FLAGS_COUNT 20 +#define TAINT_FORCED_BIND 20 +#define TAINT_FLAGS_COUNT 21 #define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1) struct taint_flag { diff --git a/include/trace/events/module.h b/include/trace/events/module.h index e5a006be9dc6..19df3e39bba4 100644 --- a/include/trace/events/module.h +++ b/include/trace/events/module.h @@ -26,7 +26,8 @@ struct module; { (1UL << TAINT_OOT_MODULE), "O" }, \ { (1UL << TAINT_FORCED_MODULE), "F" }, \ { (1UL << TAINT_CRAP), "C" }, \ - { (1UL << TAINT_UNSIGNED_MODULE), "E" }) + { (1UL << TAINT_UNSIGNED_MODULE), "E" }, \ + { (1UL << TAINT_FORCED_BIND), "Y" }) TRACE_EVENT(module_load, diff --git a/kernel/module/main.c b/kernel/module/main.c index c1b34dc1e89a..0d720b33d648 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -191,11 +191,22 @@ static inline int strong_try_module_get(struct module *mod) return -ENOENT; } -static inline void add_taint_module(struct module *mod, unsigned flag, - enum lockdep_ok lockdep_ok) +/** + * add_taint_module: add a taint flag if not already set for a specific module + * @mod: pointer to the module that caused the problem + * @flag: one of the TAINT_* constants. + * @lockdep_ok: whether lock debugging is still OK. + * + * If something bad has gone wrong, you'll want + * @lockdep_ok = LOCKDEP_NOW_UNRELIABLE, but for some + * noteworthy-but-not-corrupting cases, it can be set to LOCKDEP_STILL_OK. + */ +void add_taint_module(struct module *mod, unsigned flag, + enum lockdep_ok lockdep_ok) { add_taint(flag, lockdep_ok); - set_bit(flag, &mod->taints); + if (mod) + set_bit(flag, &mod->taints); } /* diff --git a/kernel/panic.c b/kernel/panic.c index 170744163fc2..b824b68fcb08 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -825,6 +825,7 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = { TAINT_FLAG(RANDSTRUCT, 'T', ' '), TAINT_FLAG(TEST, 'N', ' '), TAINT_FLAG(FWCTL, 'J', ' '), + TAINT_FLAG(FORCED_BIND, 'Y', ' '), }; #undef TAINT_FLAG @@ -861,9 +862,9 @@ static void print_tainted_seq(struct seq_buf *s, bool verbose) * exact size is allocated dynamically; the initial buffer remains * as a fallback if allocation fails. * - * The verbose taint string currently requires up to 327 characters. + * The verbose taint string currently requires up to 344 characters. */ -#define INIT_TAINT_BUF_MAX 350 +#define INIT_TAINT_BUF_MAX 370 static char init_taint_buf[INIT_TAINT_BUF_MAX] __initdata; static char *taint_buf __refdata = init_taint_buf; @@ -947,8 +948,9 @@ unsigned long get_taint(void) * @flag: one of the TAINT_* constants. * @lockdep_ok: whether lock debugging is still OK. * - * If something bad has gone wrong, you'll want @lockdebug_ok = false, but for - * some notewortht-but-not-corrupting cases, it can be set to true. + * If something bad has gone wrong, you'll want + * @lockdep_ok = LOCKDEP_NOW_UNRELIABLE, but for some + * noteworthy-but-not-corrupting cases, it can be set to LOCKDEP_STILL_OK. */ void add_taint(unsigned flag, enum lockdep_ok lockdep_ok) { diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c index a67129e452a3..1480e2c27ed0 100644 --- a/lib/kobject_uevent.c +++ b/lib/kobject_uevent.c @@ -83,7 +83,7 @@ static int kobject_action_type(const char *buf, size_t count, for (action = 0; action < ARRAY_SIZE(kobject_actions); action++) { if (strncmp(kobject_actions[action], buf, count_first) != 0) continue; - if (kobject_actions[action][count_first] != '\0') + if (strlen(kobject_actions[action]) != count_first) continue; if (args) *args = args_start; diff --git a/rust/helpers/dma.c b/rust/helpers/dma.c index 9fbeb507b08c..ff8f24dae9df 100644 --- a/rust/helpers/dma.c +++ b/rust/helpers/dma.c @@ -49,3 +49,8 @@ __rust_helper void rust_helper_dma_set_max_seg_size(struct device *dev, { dma_set_max_seg_size(dev, size); } + +__rust_helper unsigned int rust_helper_dma_get_max_seg_size(struct device *dev) +{ + return dma_get_max_seg_size(dev); +} diff --git a/rust/kernel/auxiliary.rs b/rust/kernel/auxiliary.rs index 06f816420790..9d3de109b381 100644 --- a/rust/kernel/auxiliary.rs +++ b/rust/kernel/auxiliary.rs @@ -137,10 +137,18 @@ pub struct DeviceId(bindings::auxiliary_device_id); impl DeviceId { /// Create a new [`DeviceId`] from name. + /// + /// This is only intended to be called in const context, when constructing a + /// device ID table, where exceeding `AUXILIARY_NAME_SIZE` is a compile time error. pub const fn new(modname: &'static CStr, name: &'static CStr) -> Self { let name = name.to_bytes_with_nul(); let modname = modname.to_bytes_with_nul(); + assert!( + modname.len().saturating_add(name.len()) <= bindings::AUXILIARY_NAME_SIZE as usize, + "auxiliary device ID is too long" + ); + let mut id: bindings::auxiliary_device_id = pin_init::zeroed(); let mut i = 0; while i < modname.len() { diff --git a/rust/kernel/scatterlist.rs b/rust/kernel/scatterlist.rs index b83c468b5c63..44eeafed05e3 100644 --- a/rust/kernel/scatterlist.rs +++ b/rust/kernel/scatterlist.rs @@ -350,15 +350,23 @@ where page_vec.push(page.as_ptr(), flags)?; } + // Cap segments at both the DMA mapping-path limit and the device's declared + // max segment size. + // // `dma_max_mapping_size` returns `size_t`, but `sg_alloc_table_from_pages_segment()` takes // an `unsigned int`. // // SAFETY: `dev.as_raw()` is a valid pointer to a `struct device`. - let max_segment = match unsafe { bindings::dma_max_mapping_size(dev.as_raw()) } { + let max_mapping_size = match unsafe { bindings::dma_max_mapping_size(dev.as_raw()) } { 0 => u32::MAX, - max_segment => u32::try_from(max_segment).unwrap_or(u32::MAX), + max_mapping_size => u32::try_from(max_mapping_size).unwrap_or(u32::MAX), }; + // SAFETY: `dev.as_raw()` is a valid pointer to a `struct device`. + let max_seg_size = unsafe { bindings::dma_get_max_seg_size(dev.as_raw()) }; + + let max_segment = max_mapping_size.min(max_seg_size); + Ok(try_pin_init!(&this in Self { // SAFETY: // - `page_vec` is a `KVec` of valid `struct page *` obtained from `pages`. diff --git a/tools/debugging/kernel-chktaint b/tools/debugging/kernel-chktaint index e1571c04afb5..d8628be37214 100755 --- a/tools/debugging/kernel-chktaint +++ b/tools/debugging/kernel-chktaint @@ -211,6 +211,14 @@ else addout "J" echo " * fwctl's mutating debug interface was used (#19)" fi + +T=`expr $T / 2` +if [ `expr $T % 2` -eq 0 ]; then + addout " " +else + addout "Y" + echo " * device was manually bound or unbound from a driver (#20)" +fi echo "Raw taint value as int/string: $taint/'$out'" # report on any tainted loadable modules |
