verify_version() in kernel.c gets a struct syment for linux_banner using 
symbol_search() and uses the value member of the result as the address of 
linux_banner in some cases based on the type member's value in the same struct 
syment. A small number of coredumps with an unhandled type ('B' or 'b') for 
linux_banner result in the address of linux_banner being loaded from the actual 
linux_banner data. This fails because the first ulong of the linux_banner ASCII 
text is treated as a dumped kernel address and attempting to access that in the 
core fails.

Based on a suggestion from Kazu, continue to get the struct syment for 
linux_banner using symbol_search(). Also use get_symbol_type() for linux_banner 
and use the result of that to decide where to get the linux_banner address 
from, disregarding the syment type member. If get_symbol_type() reports a 
TYPE_CODE_ARRAY (and by default with a warning) use the syment value member as 
the linux_banner address. If get_symbol_type() reports a TYPE_CODE_PTR read the 
address of linux_banner using get_symbol_data().

The else block doesn't strictly require braced content for a single switch 
statement but braces are included to match style of locally similar cases.

Signed-off-by: David Mair <dm...@suse.com>
---
diff --git a/kernel.c b/kernel.c
index 988206b..6dcf414 100644
--- a/kernel.c
+++ b/kernel.c
@@ -1076,13 +1076,21 @@ verify_version(void)
if (!(sp = symbol_search("linux_banner")))
                error(FATAL, "linux_banner symbol does not exist?\n");
-       else if ((sp->type == 'R') || (sp->type == 'r') ||
-               (THIS_KERNEL_VERSION >= LINUX(2,6,11) && (sp->type == 'D' || 
sp->type == 'd')) ||
-                (machine_type("ARM") && sp->type == 'T') ||
-                (machine_type("ARM64")))
-               linux_banner = symbol_value("linux_banner");
-       else
-               get_symbol_data("linux_banner", sizeof(ulong), &linux_banner);
+       else {
+               switch (get_symbol_type("linux_banner", NULL, NULL))
+               {
+               case TYPE_CODE_ARRAY:
+                       linux_banner = sp->value;
+                       break;
+               case TYPE_CODE_PTR:
+                       get_symbol_data("linux_banner", sizeof(ulong), 
&linux_banner);
+                       break;
+               default:
+                       error(WARNING, "linux_banner is unknown type\n");
+                       linux_banner = sp->value;
+                       break;
+               }
+       }
if (!IS_KVADDR(linux_banner))
                error(WARNING, "invalid linux_banner pointer: %lx\n",

--
Crash-utility mailing list
Crash-utility@redhat.com
https://listman.redhat.com/mailman/listinfo/crash-utility
Contribution Guidelines: https://github.com/crash-utility/crash/wiki

Reply via email to