From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B36653F660D; Wed, 26 Aug 2026 11:58:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787745519; cv=none; b=DqCwAv+zmc8tvCjG3vSTdwRY7SYpcI0LSc6X1hGUjBJuvYLrTPdCtZTG0kLstMzu43666nK8wXeLKspnX2J70buxNLMEMkmMQxvsdR4N6FZxzG9q2RIPkmOlHHvAMnrVPXWdq8+0bKlfAB165NisulYVtLM8uZCLbfPO+la4gBA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787745519; c=relaxed/simple; bh=pouOubpzeE/eS4e+NhDcKnaQ6GcMPvRq1umrSysyCF0=; h=Date:From:To:CC:Subject:In-Reply-To:Message-ID:MIME-Version: Content-Type; b=GFMZukEsyrI7aZrmDEmN+dCsuH00iimavJJgaGnwQ5ve1V9yZQAoxuzEciIImGKPiuSxx3O3Uf+OufT+TgxLfr8YUmCj4sQ6eMvb78PYJY1izrvHPwdDlj+UnCWlx8sWSQqG3BuGDJtFgwvmCuI4wkAiDRbkMwICr09gZcUhSoY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=WjxOkzSj; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=DGByaH1F; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="WjxOkzSj"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="DGByaH1F" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Subject:To:From:Date; t=1787745480; bh=81HuOHkJZ/6XeH/5mgBHH0G O6RDqXAynRuVEOzIkn/I=; b=WjxOkzSjnF1zBJoljGrh1GdoR3dxF/UL0gQeN3ud1DqydsotOX DBZTiQiZwRfS9FnzGYbIVwxMbYSl/KyS3cZwEPMlK73mu4oNwVsVgpRZY3XZMshdts+hWsZLREL pWRdJOQkjzvXOuf0r7aD8vHD/r1UYmSD/KyK+yfQjhsN2XFUNSHDB6J+rcDbvMO9o2yxw4R4C2t fWXPmBL2C3MZGBvIaq0+BiigXDRwhUn9aLYW0GDvEx8ZfsnWF5GaMU61mOjxNGxwD4jJb+Jbg/P GB+9PspPXZbKTQ75W0tQFq0bTYk3yMHIgaJh+sC5HxFLNDP8/5y7aiyoPLdAj6sn+HA==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Subject:To:From:Date; t=1787745480; bh=81HuOHkJZ/6XeH/5mgBHH0G O6RDqXAynRuVEOzIkn/I=; b=DGByaH1FxTnjtyUBTvcnIcEI69Ke674msqKlOH9rJCPrxyqo6j +XozhIcBWI5yM1GOkqBgVKEsRgyIgDI9AhBA==; Date: Wed, 26 Aug 2026 12:58:00 +0100 From: Bradley Morgan To: gregkh@linuxfoundation.org CC: atomlin@atomlin.com, corbet@lwn.net, da.gomez@kernel.org, dakr@kernel.org, driver-core@lists.linux.dev, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-modules@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-usb@vger.kernel.org, mathieu.desnoyers@efficios.com, mcgrof@kernel.org, mhiramat@kernel.org, petr.pavlu@suse.com, rafael@kernel.org, rdunlap@infradead.org, rostedt@goodmis.org, samitolvanen@google.com, skhan@linuxfoundation.org Subject: =?US-ASCII?Q?Re=3A_=5BPATCH_2/2=5D_driver_core?= =?US-ASCII?Q?=3A_add_TAINT=5FFORCED=5FBIND_for_?= =?US-ASCII?Q?when_userspace_manually_messes_with_devices_and_drivers?= In-Reply-To: <20260826-bind_taint-v1-2-52b05f4a965c@linuxfoundation.org> Message-ID: Precedence: bulk X-Mailing-List: linux-modules@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit On 26 August 2026 10:19:33 BST, Greg Kroah-Hartman wrote: >The ability to add and remove devices from a driver through the sysfs >"bind" and "unbind" files was created all those decades ago as a way >that kernel developers can iterate faster, and provide a debugging way >for users to attempt to add a new device to a driver without having to >rebuild their kernel. > >This api over the years has been abused and recently come under a major >fuzzing "attack" through tools like syzbot which decided that it would >attempt to just randomly bind any driver to any type of device, causing >loads of unneeded errors and pointless kernel patches to be generated by >unsuspecting new developers. > >Handle all of this by adding a new taint flag, TAINT_FORCED_BIND, which >will be set on the driver if the bind/unbind sysfs files are ever >successfully written to. This lets kernel developers "know" that a user >is attempting to do something that is not normal, and as such, if the >kernel breaks they get to keep the shiny pieces laying around on the >floor. > >Note, the taint flag gets set _BEFORE_ the bind/unbind callback happens, >as many times crashes/oops/warnings/failures happen within the callback, >and the taint flag needs to be there to show what was being attempted. >If it were to be set after the callback happens, the oops report would >not properly reflect what foolishness was being attempted. > sashiko found a couple valid concerns for 2/2 >Signed-off-by: Greg Kroah-Hartman >--- > Documentation/admin-guide/tainted-kernels.rst | 52 > ++++++++++++++------------- > drivers/base/bus.c | 3 ++ > include/linux/panic.h | 3 +- > include/trace/events/module.h | 3 +- > kernel/panic.c | 5 +-- > tools/debugging/kernel-chktaint | 8 +++++ > 6 files changed, 46 insertions(+), 28 deletions(-) > >diff --git a/Documentation/admin-guide/tainted-kernels.rst b/Documentation/admin-guide/tainted-kernels.rst >index 9ead927a37c0..d4ca8b9e3819 100644 >--- a/Documentation/admin-guide/tainted-kernels.rst >+++ b/Documentation/admin-guide/tainted-kernels.rst >@@ -79,30 +79,31 @@ which bits are set:: > 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/drivers/base/bus.c b/drivers/base/bus.c >index d17bd91490ee..c51ad96d4de4 100644 >--- a/drivers/base/bus.c >+++ b/drivers/base/bus.c >@@ -19,6 +19,7 @@ > #include > #include > #include >+#include > #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/include/linux/panic.h b/include/linux/panic.h >index f1dd417e54b2..8e7250b0e913 100644 >--- a/include/linux/panic.h >+++ b/include/linux/panic.h >@@ -88,7 +88,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/panic.c b/kernel/panic.c >index 213725b612aa..6bf60f9dd120 100644 >--- a/kernel/panic.c >+++ b/kernel/panic.c >@@ -826,6 +826,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 >@@ -862,9 +863,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; >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 > > --- Thanks! https://lore.kernel.org/all/EE579805-42F2-4C58-B752-F28779EEB717@grrlz.net/