[SATYR PATCH] koops: parse taint flags

Martin Milata mmilata at redhat.com
Mon May 13 13:47:43 UTC 2013


- flag taint_virtual_box was removed because it does not exist (or does
  it?), taint_module_gpl removed due to it being the negation of
  taint_module_proprietary
- the json format is a bit more compact than was originally intended

Signed-off-by: Martin Milata <mmilata at redhat.com>
---
 lib/koops_stacktrace.c                  | 164 ++++++++++++++++++++------------
 lib/koops_stacktrace.h                  |   2 -
 tests/kerneloopses/rhbz-827868-modified |  38 ++++++++
 tests/koops_stacktrace.at               |  69 ++++++++------
 4 files changed, 181 insertions(+), 92 deletions(-)
 create mode 100644 tests/kerneloopses/rhbz-827868-modified

diff --git a/lib/koops_stacktrace.c b/lib/koops_stacktrace.c
index a10d816..1d68d85 100644
--- a/lib/koops_stacktrace.c
+++ b/lib/koops_stacktrace.c
@@ -24,6 +24,7 @@
 #include "strbuf.h"
 #include "normalize.h"
 #include <string.h>
+#include <stddef.h>
 
 struct sr_koops_stacktrace *
 sr_koops_stacktrace_new()
@@ -114,6 +115,67 @@ sr_koops_stacktrace_remove_frame(struct sr_koops_stacktrace *stacktrace,
 
 }
 
+struct taint_flag {
+    char letter;
+    size_t member_offset;
+};
+
+/* http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/kernel/panic.c?id=HEAD */
+
+#define FLAG_OFFSET(flag) offsetof(struct sr_koops_stacktrace, taint_ ## flag)
+static struct taint_flag flags[] = {
+    { 'P', FLAG_OFFSET(module_proprietary)  },
+    { 'F', FLAG_OFFSET(forced_module)       },
+    { 'S', FLAG_OFFSET(smp_unsafe)          },
+    { 'R', FLAG_OFFSET(forced_removal)      },
+    { 'M', FLAG_OFFSET(mce)                 },
+    { 'B', FLAG_OFFSET(page_release)        },
+    { 'U', FLAG_OFFSET(userspace)           },
+    { 'D', FLAG_OFFSET(died_recently)       },
+    { 'A', FLAG_OFFSET(acpi_overridden)     },
+    { 'W', FLAG_OFFSET(warning)             },
+    { 'C', FLAG_OFFSET(staging_driver)      },
+    { 'I', FLAG_OFFSET(firmware_workaround) },
+    { 'O', FLAG_OFFSET(module_out_of_tree)  },
+    { '\0', 0 /* sentinel */                }
+};
+#undef FLAG_OFFSET
+
+/* Based on function kernel_tainted_short from abrt/src/lib/kernel.c */
+static bool
+parse_taint_flags(const char *input, struct sr_koops_stacktrace *stacktrace)
+{
+    /* example of flags: 'Tainted: G    B       ' */
+    const char *tainted = strstr(input, "Tainted: ");
+    if (!tainted)
+        return false;
+
+    tainted += strlen("Tainted: ");
+
+    for (;;)
+    {
+        if (tainted[0] >= 'A' && tainted[0] <= 'Z')
+        {
+            /* set the appropriate flag */
+            struct taint_flag *f;
+            for (f = flags; f->letter; f++)
+            {
+                if (tainted[0] == f->letter)
+                {
+                    *(bool *)((void *)stacktrace + f->member_offset) = true;
+                    break;
+                }
+            }
+        }
+        else if (tainted[0] != ' ')
+            break;
+
+        ++tainted;
+    }
+
+    return true;
+}
+
 struct sr_koops_stacktrace *
 sr_koops_stacktrace_parse(const char **input,
                           struct sr_location *location)
@@ -122,6 +184,9 @@ sr_koops_stacktrace_parse(const char **input,
 
     struct sr_koops_stacktrace *stacktrace = sr_koops_stacktrace_new();
 
+    /* Looks for the "Tainted: " line in the whole input */
+    parse_taint_flags(local_input, stacktrace);
+
     while (*local_input)
     {
         struct sr_koops_frame *frame = sr_koops_frame_parse(&local_input);
@@ -185,6 +250,41 @@ sr_koops_stacktrace_parse_modules(const char **input)
     return result;
 }
 
+static char *
+taint_flags_to_json(struct sr_koops_stacktrace *stacktrace)
+{
+    struct sr_strbuf *strbuf = sr_strbuf_new();
+
+#define FLAG_APPEND(flag)                                   \
+    if (stacktrace->taint_ ## flag)                         \
+        sr_strbuf_append_strf(strbuf, ", \"" #flag "\"\n"); \
+
+    FLAG_APPEND(module_proprietary)
+    FLAG_APPEND(forced_module)
+    FLAG_APPEND(forced_removal)
+    FLAG_APPEND(smp_unsafe)
+    FLAG_APPEND(mce)
+    FLAG_APPEND(page_release)
+    FLAG_APPEND(userspace)
+    FLAG_APPEND(died_recently)
+    FLAG_APPEND(acpi_overridden)
+    FLAG_APPEND(warning)
+    FLAG_APPEND(staging_driver)
+    FLAG_APPEND(firmware_workaround)
+    FLAG_APPEND(module_out_of_tree)
+
+#undef FLAG_APPEND
+
+    if (strbuf->len == 0)
+        return sr_strdup("[]");
+
+    sr_strbuf_append_char(strbuf, ']');
+    char *result = sr_strbuf_free_nobuf(strbuf);
+    result[0] = '[';
+    result[strlen(result) - 2] = ' '; /* erase the last newline */
+    return result;
+}
+
 char *
 sr_koops_stacktrace_to_json(struct sr_koops_stacktrace *stacktrace)
 {
@@ -199,65 +299,11 @@ sr_koops_stacktrace_to_json(struct sr_koops_stacktrace *stacktrace)
     }
 
     /* Kernel taint flags. */
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_module_proprietary\": %s\n",
-                          stacktrace->taint_module_proprietary ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_module_gpl\": %s\n",
-                          stacktrace->taint_module_gpl ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_module_out_of_tree\": %s\n",
-                          stacktrace->taint_module_out_of_tree ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_forced_module\": %s\n",
-                          stacktrace->taint_forced_module ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_forced_removal\": %s\n",
-                          stacktrace->taint_forced_removal ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_smp_unsafe\": %s\n",
-                          stacktrace->taint_smp_unsafe ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_mce\": %s\n",
-                          stacktrace->taint_mce ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_page_release\": %s\n",
-                          stacktrace->taint_page_release ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_userspace\": %s\n",
-                          stacktrace->taint_userspace ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_died_recently\": %s\n",
-                          stacktrace->taint_died_recently ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_acpi_overridden\": %s\n",
-                          stacktrace->taint_acpi_overridden ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_warning\": %s\n",
-                          stacktrace->taint_warning ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_staging_driver\": %s\n",
-                          stacktrace->taint_staging_driver ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_firmware_workaround\": %s\n",
-                          stacktrace->taint_firmware_workaround ? "true" : "false");
-
-    sr_strbuf_append_strf(strbuf,
-                          ",   \"taint_virtual_box\": %s\n",
-                          stacktrace->taint_virtual_box ? "true" : "false");
+    char *taint_flags = taint_flags_to_json(stacktrace);
+    char *indented_taint_flags = sr_indent_except_first_line(taint_flags, strlen(",   \"taint_flags\": "));
+    free(taint_flags);
+    sr_strbuf_append_strf(strbuf, ",   \"taint_flags\": %s\n", indented_taint_flags);
+    free(indented_taint_flags);
 
     /* Modules. */
     if (stacktrace->modules)
diff --git a/lib/koops_stacktrace.h b/lib/koops_stacktrace.h
index 62854a8..54bd0cc 100644
--- a/lib/koops_stacktrace.h
+++ b/lib/koops_stacktrace.h
@@ -47,7 +47,6 @@ struct sr_koops_stacktrace
      */
 
     bool taint_module_proprietary;
-    bool taint_module_gpl;
     bool taint_module_out_of_tree;
     bool taint_forced_module;
     bool taint_forced_removal;
@@ -62,7 +61,6 @@ struct sr_koops_stacktrace
     bool taint_warning;
     bool taint_staging_driver;
     bool taint_firmware_workaround;
-    bool taint_virtual_box;
 
     /**
      * @brief List of loaded modules.
diff --git a/tests/kerneloopses/rhbz-827868-modified b/tests/kerneloopses/rhbz-827868-modified
new file mode 100644
index 0000000..c73ef85
--- /dev/null
+++ b/tests/kerneloopses/rhbz-827868-modified
@@ -0,0 +1,38 @@
+[110417.280426] WARNING: at mm/page_alloc.c:2204 __alloc_pages_nodemask+0x231/0x8f0()
+[110417.280429] Hardware name: Latitude E6420
+[110417.280431] Modules linked in: vfat fat usb_storage authenc l2tp_ppp pppox ppp_generic slhc l2tp_netlink l2tp_core rmd160 crypto_null camellia lzo cast6 cast5 deflate zlib_deflate cts gcm ccm serpent_sse2_x86_64 serpent_generic blowfish_generic blowfish_x86_64 blowfish_common twofish_generic twofish_x86_64_3way lrw twofish_x86_64 twofish_common xcbc sha256_generic sha512_generic des_generic ah6 ah4 esp6 esp4 xfrm4_mode_beet xfrm4_tunnel tunnel4 xfrm4_mode_tunnel xfrm4_mode_transport xfrm6_mode_transport xfrm6_mode_ro xfrm6_mode_beet xfrm6_mode_tunnel ipcomp ipcomp6 xfrm_ipcomp xfrm6_tunnel tunnel6 af_key snd_usb_audio snd_usbmidi_lib snd_rawmidi sctp libcrc32c tcp_lp wacom fuse lockd rfcomm bnep snd_hda_codec_hdmi snd_hda_codec_idt binfmt_misc arc4 uvcvideo snd_hda_intel videobuf2_core videodev snd_hda_codec ppdev media dell_wmi videobuf2_vmalloc sparse_keymap videobuf2_memops dell_laptop snd_hwdep snd_seq uinput dcdbas snd_seq_device btusb bluetooth iwlwifi snd_pcm par!
 port_pc 
+joydev parport snd_timer microcode mac80211 snd soundcore snd_page_alloc i2c_i801 cfg80211 iTCO_wdt iTCO_vendor_support rfkill e1000e sunrpc xts gf128mul dm_crypt sdhci_pci sdhci mmc_core wmi i915 drm_kms_helper drm i2c_algo_bit i2c_core video [last unloaded: scsi_wait_scan]
+[110417.280525] Pid: 3, comm: ksoftirqd/0 Tainted: P    B D    O 3.3.7-1.fc16.x86_64 #1
+[110417.280528] Call Trace:
+[110417.280535]  [<ffffffff81057adf>] warn_slowpath_common+0x7f/0xc0
+[110417.280539]  [<ffffffff81057b3a>] warn_slowpath_null+0x1a/0x20
+[110417.280544]  [<ffffffff811296d1>] __alloc_pages_nodemask+0x231/0x8f0
+[110417.280550]  [<ffffffff8151fd80>] ? ip_copy_metadata+0x1c0/0x1c0
+[110417.280555]  [<ffffffff8151f860>] ? ip_forward_options+0x1f0/0x1f0
+[110417.280559]  [<ffffffff81160a93>] alloc_pages_current+0xa3/0x110
+[110417.280563]  [<ffffffff81125514>] __get_free_pages+0x14/0x50
+[110417.280569]  [<ffffffff8116bb5f>] kmalloc_order_trace+0x3f/0xd0
+[110417.280573]  [<ffffffff8116ca87>] __kmalloc+0x177/0x1a0
+[110417.280578]  [<ffffffffa0642332>] ? pppol2tp_xmit+0x42/0x220 [l2tp_ppp]
+[110417.280583]  [<ffffffff814db0a7>] pskb_expand_head+0x87/0x310
+[110417.280588]  [<ffffffff8113dc59>] ? __mod_zone_page_state+0x49/0x50
+[110417.280591]  [<ffffffff814da0f5>] ? kfree_skb+0x45/0xc0
+[110417.280595]  [<ffffffffa06424dd>] pppol2tp_xmit+0x1ed/0x220 [l2tp_ppp]
+[110417.280600]  [<ffffffffa062dd5b>] ppp_push+0x15b/0x650 [ppp_generic]
+[110417.280604]  [<ffffffff814db264>] ? pskb_expand_head+0x244/0x310
+[110417.280608]  [<ffffffff8112860b>] ? free_compound_page+0x1b/0x20
+[110417.280612]  [<ffffffff8112d053>] ? __put_compound_page+0x23/0x30
+[110417.280615]  [<ffffffff8112d1d5>] ? put_compound_page+0x125/0x1c0
+[110417.280619]  [<ffffffffa062e89f>] ppp_xmit_process+0x46f/0x660 [ppp_generic]
+[110417.280624]  [<ffffffffa062ebc8>] ppp_start_xmit+0x138/0x1d0 [ppp_generic]
+[110417.280628]  [<ffffffff814e85b2>] dev_hard_start_xmit+0x332/0x6d0
+[110417.280632]  [<ffffffff8150447a>] sch_direct_xmit+0xfa/0x1d0
+[110417.280635]  [<ffffffff815045f6>] __qdisc_run+0xa6/0x130
+[110417.280639]  [<ffffffff814e6883>] net_tx_action+0xe3/0x1f0
+[110417.280643]  [<ffffffff8105f0c8>] __do_softirq+0xb8/0x230
+[110417.280646]  [<ffffffff8105f2fa>] run_ksoftirqd+0xba/0x170
+[110417.280649]  [<ffffffff8105f240>] ? __do_softirq+0x230/0x230
+[110417.280654]  [<ffffffff81079da3>] kthread+0x93/0xa0
+[110417.280658]  [<ffffffff815fd8e4>] kernel_thread_helper+0x4/0x10
+[110417.280663]  [<ffffffff81079d10>] ? kthread_freezable_should_stop+0x70/0x70
+[110417.280666]  [<ffffffff815fd8e0>] ? gs_change+0x13/0x13
diff --git a/tests/koops_stacktrace.at b/tests/koops_stacktrace.at
index d30e8b9..b0153bd 100644
--- a/tests/koops_stacktrace.at
+++ b/tests/koops_stacktrace.at
@@ -77,7 +77,8 @@ static void
 check(const char *path,
       const char *first_function_name,
       const char *last_function_name,
-      int frame_count)
+      int frame_count,
+      int taint_count)
 {
   char *error_message;
   char *full_input = sr_file_to_string(path, &error_message);
@@ -112,6 +113,23 @@ check(const char *path,
   assert(reason);
   free(reason);
 
+  int actual_taint_count =
+    stacktrace->taint_module_proprietary +
+    stacktrace->taint_module_out_of_tree +
+    stacktrace->taint_forced_module +
+    stacktrace->taint_forced_removal +
+    stacktrace->taint_smp_unsafe +
+    stacktrace->taint_mce +
+    stacktrace->taint_page_release +
+    stacktrace->taint_userspace +
+    stacktrace->taint_died_recently +
+    stacktrace->taint_acpi_overridden +
+    stacktrace->taint_warning +
+    stacktrace->taint_staging_driver +
+    stacktrace->taint_firmware_workaround;
+
+  assert(actual_taint_count == taint_count);
+
   sr_koops_stacktrace_free(stacktrace);
   free(full_input);
 }
@@ -119,19 +137,19 @@ check(const char *path,
 int
 main(void)
 {
-  check("../../kerneloopses/gitlog-01", "unwind_backtrace", "kthread", 15);
-  check("../../kerneloopses/gitlog-02", "unwind_backtrace", "cpu_idle", 27);
-  check("../../kerneloopses/gitlog-03", "lockdep_rcu_suspicious", "system_call_fastpath", 19);
-  check("../../kerneloopses/gitlog-04", "lockdep_rcu_suspicious", "addrconf_forward_change", 7);
-  check("../../kerneloopses/gitlog-05", "mark_held_locks", "sysenter_do_call", 26);
-  check("../../kerneloopses/gitlog-06", "lock_acquire", "kernel_thread_helper", 23);
-  check("../../kerneloopses/gitlog-07", "__slab_alloc.isra.50.constprop.56", "sysenter_do_call", 14);
-  check("../../kerneloopses/gitlog-08", "unwind_backtrace", "sys_write", 13);
+  check("../../kerneloopses/gitlog-01", "unwind_backtrace", "kthread", 15, 0);
+  check("../../kerneloopses/gitlog-02", "unwind_backtrace", "cpu_idle", 27, 0);
+  check("../../kerneloopses/gitlog-03", "lockdep_rcu_suspicious", "system_call_fastpath", 19, 0);
+  check("../../kerneloopses/gitlog-04", "lockdep_rcu_suspicious", "addrconf_forward_change", 7, 0);
+  check("../../kerneloopses/gitlog-05", "mark_held_locks", "sysenter_do_call", 26, 1);
+  check("../../kerneloopses/gitlog-06", "lock_acquire", "kernel_thread_helper", 23, 1);
+  check("../../kerneloopses/gitlog-07", "__slab_alloc.isra.50.constprop.56", "sysenter_do_call", 14, 0);
+  check("../../kerneloopses/gitlog-08", "unwind_backtrace", "sys_write", 13, 1);
 
-  check("../../kerneloopses/gitlog-09", "unwind_backtrace", "cpu_idle", 11);
-  check("../../kerneloopses/gitlog-10", NULL, NULL, 0);
-  check("../../kerneloopses/gitlog-11", "lockdep_rcu_suspicious", "out_of_memory", 12);
-  check("../../kerneloopses/gitlog-12", "unwind_backtrace", "regulator_get_voltage", 6);
+  check("../../kerneloopses/gitlog-09", "unwind_backtrace", "cpu_idle", 11, 1);
+  check("../../kerneloopses/gitlog-10", NULL, NULL, 0, 0);
+  check("../../kerneloopses/gitlog-11", "lockdep_rcu_suspicious", "out_of_memory", 12, 0);
+  check("../../kerneloopses/gitlog-12", "unwind_backtrace", "regulator_get_voltage", 6, 1);
 /*
   check("../../kerneloopses/gitlog-13", "", "", 0);
   check("../../kerneloopses/gitlog-14", "", "", 0);
@@ -154,8 +172,8 @@ main(void)
   check("../../kerneloopses/gitlog-31", "", "", 0);
 */
 
-  check("../../kerneloopses/rhbz-827868", "warn_slowpath_common", "gs_change", 32);
-  check("../../kerneloopses/rhbz-836206", "__might_sleep", "system_call_fastpath", 23);
+  check("../../kerneloopses/rhbz-827868", "warn_slowpath_common", "gs_change", 32, 0);
+  check("../../kerneloopses/rhbz-836206", "__might_sleep", "system_call_fastpath", 23, 0);
   return 0;
 }
 ]])
@@ -175,7 +193,7 @@ int
 main(void)
 {
   char *error_message;
-  char *full_input = sr_file_to_string("../../kerneloopses/rhbz-827868",
+  char *full_input = sr_file_to_string("../../kerneloopses/rhbz-827868-modified",
                                         &error_message);
 
   assert(full_input);
@@ -193,21 +211,10 @@ main(void)
   char *json = sr_koops_stacktrace_to_json(stacktrace);
   puts(json);
   assert(0 == strcmp(json,
-    "{   \"taint_module_proprietary\": false\n"
-    ",   \"taint_module_gpl\": false\n"
-    ",   \"taint_module_out_of_tree\": false\n"
-    ",   \"taint_forced_module\": false\n"
-    ",   \"taint_forced_removal\": false\n"
-    ",   \"taint_smp_unsafe\": false\n"
-    ",   \"taint_mce\": false\n"
-    ",   \"taint_page_release\": false\n"
-    ",   \"taint_userspace\": false\n"
-    ",   \"taint_died_recently\": false\n"
-    ",   \"taint_acpi_overridden\": false\n"
-    ",   \"taint_warning\": false\n"
-    ",   \"taint_staging_driver\": false\n"
-    ",   \"taint_firmware_workaround\": false\n"
-    ",   \"taint_virtual_box\": false\n"
+    "{   \"taint_flags\": [ \"module_proprietary\"\n"
+    "                   , \"page_release\"\n"
+    "                   , \"died_recently\"\n"
+    "                   , \"module_out_of_tree\" ]\n"
     ",   \"modules\":\n"
     "      [ \"vfat\"\n"
     "      , \"fat\"\n"
-- 
1.7.11.7



More information about the Crash-catcher mailing list