@@ -100,6 +100,7 @@ Bit Log Number Reason that got the kernel tainted
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 _/Q 262144 driver firmware crash annotation
=== === ====== ========================================================
Note: The character ``_`` is representing a blank in this table to make reading
@@ -162,3 +163,8 @@ More detailed explanation for tainting
produce extremely unusual kernel structure layouts (even performance
pathological ones), which is important to know when debugging. Set at
build time.
+
+ 18) ``Q`` used by device drivers to annotate that the device driver's firmware
+ has crashed and the device's operation has been severely affected. The
+ device may be left in a crippled state, requiring full driver removal /
+ addition, system reboot, or it is unclear how long recovery will take.
@@ -571,7 +571,7 @@ extern int root_mountflags;
extern bool early_boot_irqs_disabled;
extern enum system_states system_state;
-#define TAINT_FLAGS_COUNT 18
+#define TAINT_FLAGS_COUNT 19
#define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1)
struct taint_flag {
@@ -705,6 +705,14 @@ static inline bool is_livepatch_module(struct module *mod)
bool is_module_sig_enforced(void);
void set_module_sig_enforced(void);
+void add_taint_module(struct module *mod, unsigned int flag,
+ enum lockdep_ok lockdep_ok);
+
+static inline void taint_firmware_crashed(void)
+{
+ add_taint_module(THIS_MODULE, TAINT_FIRMWARE_CRASH, LOCKDEP_STILL_OK);
+}
+
#else /* !CONFIG_MODULES... */
static inline struct module *__module_address(unsigned long addr)
@@ -852,6 +860,11 @@ void *dereference_module_function_descriptor(struct module *mod, void *ptr)
return ptr;
}
+static inline void taint_firmware_crashed(void)
+{
+ add_taint(TAINT_FIRMWARE_CRASH, LOCKDEP_STILL_OK);
+}
+
#endif /* CONFIG_MODULES */
#ifdef CONFIG_SYSFS
@@ -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_FIRMWARE_CRASH), "Q" })
TRACE_EVENT(module_load,
@@ -45,6 +45,7 @@ enum system_states {
#define TAINT_LIVEPATCH 15
#define TAINT_AUX 16
#define TAINT_RANDSTRUCT 17
+#define TAINT_FIRMWARE_CRASH 18
/* be sure to update TAINT_FLAGS_COUNT when extending this */
#endif /* _UAPI_LINUX_KERNEL_H */
@@ -326,13 +326,18 @@ 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)
+void add_taint_module(struct module *mod, unsigned int flag,
+ enum lockdep_ok lockdep_ok)
{
add_taint(flag, lockdep_ok);
- set_bit(flag, &mod->taints);
- panic_uevent_taint(flag, mod);
+
+ /* Skip this if the module is built-in */
+ if (mod) {
+ set_bit(flag, &mod->taints);
+ panic_uevent_taint(flag, mod);
+ }
}
+EXPORT_SYMBOL_GPL(add_taint_module);
/*
* A thread that wants to hold a reference to a module only while it
@@ -387,6 +387,7 @@ const struct taint_flag taint_flags[TAINT_FLAGS_COUNT] = {
[ TAINT_LIVEPATCH ] = { 'K', ' ', true },
[ TAINT_AUX ] = { 'X', ' ', true },
[ TAINT_RANDSTRUCT ] = { 'T', ' ', true },
+ [ TAINT_FIRMWARE_CRASH ] = { 'Q', ' ', true },
};
/**
@@ -194,6 +194,13 @@ else
addout "T"
echo " * kernel was built with the struct randomization plugin (#17)"
fi
+T=`expr $T / 2`
+if [ `expr $T % 2` -eq 0 ]; then
+ addout " "
+else
+ addout "Q"
+ echo " * a device driver's firmware has crashed (#18)"
+fi
echo "For a more detailed explanation of the various taint flags see"
echo " Documentation/admin-guide/tainted-kernels.rst in the the Linux kernel sources"
Device drivers firmware can crash, and *sometimes*, this can leave your system in a state which makes the device or subsystem completely useless. In the worst of cases not even removing the module and adding it back again will correct your situation and you are left with no other option but to do a full system reboot. Some drivers have work arounds for these situations, and sometimes they can recover the device / functionality but not all device drivers have these arrangements and in the worst cases requiring a full reboot is completely hidden from the user experience, leaving them dumbfounded with what has happened. Detecting this by inspecting /proc/sys/kernel/tainted instead of scraping some magical words from the kernel log, which is driver specific, is much easier. So instead provide a helper which lets drivers annotate this. Once this happens, scrapers can easily look for modules taint flags for a firmware crash. This will taint both the kernel and respective calling module. The new helper taint_firmware_crashed() uses LOCKDEP_STILL_OK as this fact should in no way shape or form affect lockdep. This taint is device driver specific. While extending the declaration of add_taint_module(), just make the flag unsigned int clear. Signed-off-by: Luis Chamberlain <mcgrof@kernel.org> --- Documentation/admin-guide/tainted-kernels.rst | 6 ++++++ include/linux/kernel.h | 2 +- include/linux/module.h | 13 +++++++++++++ include/trace/events/module.h | 3 ++- include/uapi/linux/kernel.h | 1 + kernel/module.c | 13 +++++++++---- kernel/panic.c | 1 + tools/debugging/kernel-chktaint | 7 +++++++ 8 files changed, 40 insertions(+), 6 deletions(-)