History

kernel: add panic_on_taint

Analogously to the introduction of panic_on_warn, this patch introduces a kernel option named panic_on_taint in order to provide a simple and generic way to stop execution and catch a coredump when the kernel gets tainted by any given flag. This is useful for debugging sessions as it avoids having to rebuild the kernel to explicitly add calls to panic() into the code sites that introduce the taint flags of interest. For instance, if one is interested in proceeding with a post-mortem analysis at the point a given code path is hitting a bad page (i.e. unaccount_page_cache_page(), or slab_bug()), a coredump can be collected by rebooting the kernel with 'panic_on_taint=0x20' amended to the command line. Another, perhaps less frequent, use for this option would be as a means for assuring a security policy case where only a subset of taints, or no single taint (in paranoid mode), is allowed for the running system. The optional switch 'nousertaint' is handy in this particular scenario, as it will avoid userspace induced crashes by writes to sysctl interface /proc/sys/kernel/tainted causing false positive hits for such policies. [akpm@linux-foundation.org: tweak kernel-parameters.txt wording]

Rafael Aquini committed 6 years ago

Commit db38d5c1 parent ceabef76 files · +75 −1Browse files

Unified · Split

6 files
  1. Documentation/admin-guide/kdump/kdump.rst +8 −0
  2. Documentation/admin-guide/kernel-parameters.txt +13 −0
  3. Documentation/admin-guide/sysctl/kernel.rst +7 −0
  4. include/linux/kernel.h +3 −0
  5. kernel/panic.c +34 −0
  6. kernel/sysctl.c +10 −1
Documentation/admin-guide/kdump/kdump.rst+8−0
@@ -521,6 +521,14 @@ will cause a kdump to occur at the panic() call. In cases where a user wants · 520 unmodified lines
521to specify this during runtime, /proc/sys/kernel/panic_on_warn can be set to 1521to specify this during runtime, /proc/sys/kernel/panic_on_warn can be set to 1
522to achieve the same behaviour.522to achieve the same behaviour.
523 523
524Trigger Kdump on add_taint()
525============================
526
527The kernel parameter panic_on_taint facilitates a conditional call to panic()
528from within add_taint() whenever the value set in this bitmask matches with the
529bit flag being set by add_taint().
530This will cause a kdump to occur at the add_taint()->panic() call.
531
524Contact532Contact
525=======533=======
526 534
Documentation/admin-guide/kernel-parameters.txt+13−0
@@ -3447,6 +3447,19 @@ · 3446 unmodified lines
3447 bit 4: print ftrace buffer3447 bit 4: print ftrace buffer
3448 bit 5: print all printk messages in buffer3448 bit 5: print all printk messages in buffer
3449 3449
3450 panic_on_taint= Bitmask for conditionally calling panic() in add_taint()
3451 Format: <hex>[,nousertaint]
3452 Hexadecimal bitmask representing the set of TAINT flags
3453 that will cause the kernel to panic when add_taint() is
3454 called with any of the flags in this set.
3455 The optional switch "nousertaint" can be utilized to
3456 prevent userspace forced crashes by writing to sysctl
3457 /proc/sys/kernel/tainted any flagset matching with the
3458 bitmask set on panic_on_taint.
3459 See Documentation/admin-guide/tainted-kernels.rst for
3460 extra details on the taint flags that users can pick
3461 to compose the bitmask to assign to panic_on_taint.
3462
3450 panic_on_warn panic() instead of WARN(). Useful to cause kdump3463 panic_on_warn panic() instead of WARN(). Useful to cause kdump
3451 on a WARN().3464 on a WARN().
3452 3465
Documentation/admin-guide/sysctl/kernel.rst+7−0
@@ -1239,6 +1239,13 @@ ORed together. The letters are seen in "Tainted" line of Oops reports. · 1238 unmodified lines
1239 1239
1240See :doc:`/admin-guide/tainted-kernels` for more information.1240See :doc:`/admin-guide/tainted-kernels` for more information.
1241 1241
1242Note:
1243 writes to this sysctl interface will fail with ``EINVAL`` if the kernel is
1244 booted with the command line option ``panic_on_taint=<bitmask>,nousertaint``
1245 and any of the ORed together values being written to ``tainted`` match with
1246 the bitmask declared on panic_on_taint.
1247 See :doc:`/admin-guide/kernel-parameters` for more details on that particular
1248 kernel command line option and its optional ``nousertaint`` switch.
1242 1249
1243threads-max1250threads-max
1244===========1251===========
include/linux/kernel.h+3−0
@@ -528,6 +528,8 @@ extern int panic_on_oops; · 527 unmodified lines
528extern int panic_on_unrecovered_nmi;528extern int panic_on_unrecovered_nmi;
529extern int panic_on_io_nmi;529extern int panic_on_io_nmi;
530extern int panic_on_warn;530extern int panic_on_warn;
531extern unsigned long panic_on_taint;
532extern bool panic_on_taint_nousertaint;
531extern int sysctl_panic_on_rcu_stall;533extern int sysctl_panic_on_rcu_stall;
532extern int sysctl_panic_on_stackoverflow;534extern int sysctl_panic_on_stackoverflow;
533 535
@@ -596,6 +598,7 @@ extern enum system_states { · 62 unmodified lines
596#define TAINT_AUX 16598#define TAINT_AUX 16
597#define TAINT_RANDSTRUCT 17599#define TAINT_RANDSTRUCT 17
598#define TAINT_FLAGS_COUNT 18600#define TAINT_FLAGS_COUNT 18
601#define TAINT_FLAGS_MAX ((1UL << TAINT_FLAGS_COUNT) - 1)
599 602
600struct taint_flag {603struct taint_flag {
601 char c_true; /* character printed when tainted */604 char c_true; /* character printed when tainted */
kernel/panic.c+34−0
@@ -44,6 +44,8 @@ static int pause_on_oops_flag; · 43 unmodified lines
44static DEFINE_SPINLOCK(pause_on_oops_lock);44static DEFINE_SPINLOCK(pause_on_oops_lock);
45bool crash_kexec_post_notifiers;45bool crash_kexec_post_notifiers;
46int panic_on_warn __read_mostly;46int panic_on_warn __read_mostly;
47unsigned long panic_on_taint;
48bool panic_on_taint_nousertaint = false;
47 49
48int panic_timeout = CONFIG_PANIC_TIMEOUT;50int panic_timeout = CONFIG_PANIC_TIMEOUT;
49EXPORT_SYMBOL_GPL(panic_timeout);51EXPORT_SYMBOL_GPL(panic_timeout);
@@ -434,6 +436,11 @@ void add_taint(unsigned flag, enum lockdep_ok lockdep_ok) · 384 unmodified lines
434 pr_warn("Disabling lock debugging due to kernel taint\n");436 pr_warn("Disabling lock debugging due to kernel taint\n");
435 437
436 set_bit(flag, &tainted_mask);438 set_bit(flag, &tainted_mask);
439
440 if (tainted_mask & panic_on_taint) {
441 panic_on_taint = 0;
442 panic("panic_on_taint set ...");
443 }
437}444}
438EXPORT_SYMBOL(add_taint);445EXPORT_SYMBOL(add_taint);
439 446
@@ -686,3 +693,30 @@ static int __init oops_setup(char *s) · 246 unmodified lines
686 return 0;693 return 0;
687}694}
688early_param("oops", oops_setup);695early_param("oops", oops_setup);
696
697static int __init panic_on_taint_setup(char *s)
698{
699 char *taint_str;
700
701 if (!s)
702 return -EINVAL;
703
704 taint_str = strsep(&s, ",");
705 if (kstrtoul(taint_str, 16, &panic_on_taint))
706 return -EINVAL;
707
708 /* make sure panic_on_taint doesn't hold out-of-range TAINT flags */
709 panic_on_taint &= TAINT_FLAGS_MAX;
710
711 if (!panic_on_taint)
712 return -EINVAL;
713
714 if (s && !strcmp(s, "nousertaint"))
715 panic_on_taint_nousertaint = true;
716
717 pr_info("panic_on_taint: bitmask=0x%lx nousertaint_mode=%sabled\n",
718 panic_on_taint, panic_on_taint_nousertaint ? "en" : "dis");
719
720 return 0;
721}
722early_param("panic_on_taint", panic_on_taint_setup);
kernel/sysctl.c+10−1
@@ -866,11 +866,20 @@ static int proc_taint(struct ctl_table *table, int write, · 865 unmodified lines
866 return err;866 return err;
867 867
868 if (write) {868 if (write) {
869 int i;
870
871 /*
872 * If we are relying on panic_on_taint not producing
873 * false positives due to userspace input, bail out
874 * before setting the requested taint flags.
875 */
876 if (panic_on_taint_nousertaint && (tmptaint & panic_on_taint))
877 return -EINVAL;
878
869 /*879 /*
870 * Poor man's atomic or. Not worth adding a primitive880 * Poor man's atomic or. Not worth adding a primitive
871 * to everyone's atomic.h for this881 * to everyone's atomic.h for this
872 */882 */
873 int i;
874 for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {883 for (i = 0; i < BITS_PER_LONG && tmptaint >> i; i++) {
875 if ((tmptaint >> i) & 1)884 if ((tmptaint >> i) & 1)
876 add_taint(i, LOCKDEP_STILL_OK);885 add_taint(i, LOCKDEP_STILL_OK);