Skip to content

Commit

Permalink
In verify_version() don't require specific syment type values for lin…
Browse files Browse the repository at this point in the history
…ux_banner symbol to get its address

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 <dmair@suse.com>
  • Loading branch information
dmair1 authored and k-hagio committed Sep 20, 2023
1 parent 3253e5a commit 27f3ccd
Showing 1 changed file with 15 additions and 7 deletions.
22 changes: 15 additions & 7 deletions kernel.c
Expand Up @@ -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",
Expand Down

0 comments on commit 27f3ccd

Please sign in to comment.