printk: honor the max_reason field in kmsg_dumper
authorPavel Tatashin <pasha.tatashin@soleen.com>
Tue, 5 May 2020 15:45:06 +0000 (11:45 -0400)
committerKees Cook <keescook@chromium.org>
Sat, 30 May 2020 17:34:03 +0000 (10:34 -0700)
kmsg_dump() allows to dump kmesg buffer for various system events: oops,
panic, reboot, etc. It provides an interface to register a callback
call for clients, and in that callback interface there is a field
"max_reason", but it was getting ignored when set to any "reason"
higher than KMSG_DUMP_OOPS unless "always_kmsg_dump" was passed as
kernel parameter.

Allow clients to actually control their "max_reason", and keep the
current behavior when "max_reason" is not set.

Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
Link: https://lore.kernel.org/lkml/20200515184434.8470-3-keescook@chromium.org/
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
include/linux/kmsg_dump.h
kernel/printk/printk.c

index 3f82b5cb2d82d83fdb193b54615bff861667b7a2..9826014771ab5b98abd076732f26cdff3ecfb128 100644 (file)
@@ -26,6 +26,7 @@ enum kmsg_dump_reason {
        KMSG_DUMP_OOPS,
        KMSG_DUMP_EMERG,
        KMSG_DUMP_SHUTDOWN,
+       KMSG_DUMP_MAX
 };
 
 /**
index 9a9b6156270bb755a16c5601d2473c5b58a0c896..a121c2255737e2d434fc2c5d42747ac8f828c77a 100644 (file)
@@ -3157,12 +3157,19 @@ void kmsg_dump(enum kmsg_dump_reason reason)
        struct kmsg_dumper *dumper;
        unsigned long flags;
 
-       if ((reason > KMSG_DUMP_OOPS) && !always_kmsg_dump)
-               return;
-
        rcu_read_lock();
        list_for_each_entry_rcu(dumper, &dump_list, list) {
-               if (dumper->max_reason && reason > dumper->max_reason)
+               enum kmsg_dump_reason max_reason = dumper->max_reason;
+
+               /*
+                * If client has not provided a specific max_reason, default
+                * to KMSG_DUMP_OOPS, unless always_kmsg_dump was set.
+                */
+               if (max_reason == KMSG_DUMP_UNDEF) {
+                       max_reason = always_kmsg_dump ? KMSG_DUMP_MAX :
+                                                       KMSG_DUMP_OOPS;
+               }
+               if (reason > max_reason)
                        continue;
 
                /* initialize iterator with data about the stored records */