leaking_addresses: Provide mechanism to scan binary files
Introduce --kallsyms argument for scanning binary files for known symbol addresses. This would have found the exposure in /sys/kernel/notes: $ scripts/leaking_addresses.pl --kallsyms=<(sudo cat /proc/kallsyms) /sys/kernel/notes: hypercall_page @ 156 /sys/kernel/notes: xen_hypercall_set_trap_table @ 156 /sys/kernel/notes: startup_xen @ 132 Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Reviewed-by: Tycho Andersen <tandersen@netflix.com> Link: https://lore.kernel.org/r/20240222220053.1475824-4-keescook@chromium.org Signed-off-by: Kees Cook <keescook@chromium.org>
This commit is contained in:
parent
3e389d457b
commit
67bbd2f007
|
@ -52,10 +52,13 @@ my $input_raw = ""; # Read raw results from file instead of scanning.
|
|||
my $suppress_dmesg = 0; # Don't show dmesg in output.
|
||||
my $squash_by_path = 0; # Summary report grouped by absolute path.
|
||||
my $squash_by_filename = 0; # Summary report grouped by filename.
|
||||
my $kallsyms_file = ""; # Kernel symbols file.
|
||||
my $kernel_config_file = ""; # Kernel configuration file.
|
||||
my $opt_32bit = 0; # Scan 32-bit kernel.
|
||||
my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
|
||||
|
||||
my @kallsyms = ();
|
||||
|
||||
# Skip these absolute paths.
|
||||
my @skip_abs = (
|
||||
'/proc/kmsg',
|
||||
|
@ -96,6 +99,8 @@ Options:
|
|||
--squash-by-path Show one result per unique path.
|
||||
--squash-by-filename Show one result per unique filename.
|
||||
--kernel-config-file=<file> Kernel configuration file (e.g /boot/config)
|
||||
--kallsyms=<file> Read kernel symbol addresses from file (for
|
||||
scanning binary files).
|
||||
--32-bit Scan 32-bit kernel.
|
||||
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
|
||||
-d, --debug Display debugging output.
|
||||
|
@ -116,6 +121,7 @@ GetOptions(
|
|||
'squash-by-path' => \$squash_by_path,
|
||||
'squash-by-filename' => \$squash_by_filename,
|
||||
'raw' => \$raw,
|
||||
'kallsyms=s' => \$kallsyms_file,
|
||||
'kernel-config-file=s' => \$kernel_config_file,
|
||||
'32-bit' => \$opt_32bit,
|
||||
'page-offset-32-bit=o' => \$page_offset_32bit,
|
||||
|
@ -156,6 +162,25 @@ if ($output_raw) {
|
|||
select $fh;
|
||||
}
|
||||
|
||||
if ($kallsyms_file) {
|
||||
open my $fh, '<', $kallsyms_file or die "$0: $kallsyms_file: $!\n";
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
my @entry = split / /, $_;
|
||||
my $addr_text = $entry[0];
|
||||
if ($addr_text !~ /^0/) {
|
||||
# TODO: Why is hex() so impossibly slow?
|
||||
my $addr = hex($addr_text);
|
||||
my $symbol = $entry[2];
|
||||
# Only keep kernel text addresses.
|
||||
my $long = pack("J", $addr);
|
||||
my $entry = [$long, $symbol];
|
||||
push @kallsyms, $entry;
|
||||
}
|
||||
}
|
||||
close $fh;
|
||||
}
|
||||
|
||||
parse_dmesg();
|
||||
walk(@DIRS);
|
||||
|
||||
|
@ -447,6 +472,25 @@ sub timed_parse_file
|
|||
}
|
||||
}
|
||||
|
||||
sub parse_binary
|
||||
{
|
||||
my ($file) = @_;
|
||||
|
||||
open my $fh, "<:raw", $file or return;
|
||||
local $/ = undef;
|
||||
my $bytes = <$fh>;
|
||||
close $fh;
|
||||
|
||||
foreach my $entry (@kallsyms) {
|
||||
my $addr = $entry->[0];
|
||||
my $symbol = $entry->[1];
|
||||
my $offset = index($bytes, $addr);
|
||||
if ($offset != -1) {
|
||||
printf("$file: $symbol @ $offset\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub parse_file
|
||||
{
|
||||
my ($file) = @_;
|
||||
|
@ -456,6 +500,15 @@ sub parse_file
|
|||
}
|
||||
|
||||
if (! -T $file) {
|
||||
if ($file =~ m|^/sys/kernel/btf/| or
|
||||
$file =~ m|^/sys/devices/pci| or
|
||||
$file =~ m|^/sys/firmware/efi/efivars/| or
|
||||
$file =~ m|^/proc/bus/pci/|) {
|
||||
return;
|
||||
}
|
||||
if (scalar @kallsyms > 0) {
|
||||
parse_binary($file);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue