Linux Modules
 help / color / mirror / Atom feed
From: Bradley Morgan <brads@mainlining.org>
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: Re: [PATCH 2/2] driver core: add TAINT_FORCED_BIND for when userspace manually messes with devices and drivers
Date: Wed, 26 Aug 2026 12:58:00 +0100	[thread overview]
Message-ID: <C35F2CF9-9CD7-482F-8F30-2D152AB42D0B@mainlining.org> (raw)
In-Reply-To: <20260826-bind_taint-v1-2-52b05f4a965c@linuxfoundation.org>

On 26 August 2026 10:19:33 BST, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> 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 <gregkh@linuxfoundation.org>
>---
> 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 <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/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/

  parent reply	other threads:[~2026-08-26 11:58 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-26  9:19 [PATCH 0/2] driver core: add TAINT_FORCED_BIND for when userspace manually messes with devices and drivers Greg Kroah-Hartman
2026-08-26  9:19 ` [PATCH 1/2] module: pull out add_taint_module() to be public Greg Kroah-Hartman
2026-08-26 10:29   ` sashiko-bot
2026-08-26 10:39     ` Greg Kroah-Hartman
2026-08-26 11:13   ` Aaron Tomlin
2026-08-26 11:54     ` Greg Kroah-Hartman
2026-08-27 13:36   ` Johan Hovold
2026-08-27 14:30     ` Greg Kroah-Hartman
2026-08-26  9:19 ` [PATCH 2/2] driver core: add TAINT_FORCED_BIND for when userspace manually messes with devices and drivers Greg Kroah-Hartman
2026-08-26 10:34   ` sashiko-bot
2026-08-26 11:58   ` Bradley Morgan [this message]
2026-08-26 13:10     ` Greg KH
2026-08-26 14:26     ` Steven Rostedt
2026-08-26 14:34       ` Bradley Morgan
2026-08-27 13:33   ` Johan Hovold
2026-08-26 13:33 ` [PATCH 0/2] " Michal Pecio
2026-08-26 14:25   ` Greg Kroah-Hartman
2026-08-26 15:35     ` Michal Pecio
2026-08-26 15:44       ` Greg Kroah-Hartman
2026-08-26 17:09         ` Michal Pecio

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=C35F2CF9-9CD7-482F-8F30-2D152AB42D0B@mainlining.org \
    --to=brads@mainlining.org \
    --cc=atomlin@atomlin.com \
    --cc=corbet@lwn.net \
    --cc=da.gomez@kernel.org \
    --cc=dakr@kernel.org \
    --cc=driver-core@lists.linux.dev \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-modules@vger.kernel.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathieu.desnoyers@efficios.com \
    --cc=mcgrof@kernel.org \
    --cc=mhiramat@kernel.org \
    --cc=petr.pavlu@suse.com \
    --cc=rafael@kernel.org \
    --cc=rdunlap@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=samitolvanen@google.com \
    --cc=skhan@linuxfoundation.org \
    /path/to/YOUR_REPLY

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

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