Skip to content

Commit 67bbd2f

Browse files
committed
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 <[email protected]> Reviewed-by: Tycho Andersen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 3e389d4 commit 67bbd2f

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

scripts/leaking_addresses.pl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,13 @@
5252
my $suppress_dmesg = 0; # Don't show dmesg in output.
5353
my $squash_by_path = 0; # Summary report grouped by absolute path.
5454
my $squash_by_filename = 0; # Summary report grouped by filename.
55+
my $kallsyms_file = ""; # Kernel symbols file.
5556
my $kernel_config_file = ""; # Kernel configuration file.
5657
my $opt_32bit = 0; # Scan 32-bit kernel.
5758
my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
5859

60+
my @kallsyms = ();
61+
5962
# Skip these absolute paths.
6063
my @skip_abs = (
6164
'/proc/kmsg',
@@ -96,6 +99,8 @@ sub help
9699
--squash-by-path Show one result per unique path.
97100
--squash-by-filename Show one result per unique filename.
98101
--kernel-config-file=<file> Kernel configuration file (e.g /boot/config)
102+
--kallsyms=<file> Read kernel symbol addresses from file (for
103+
scanning binary files).
99104
--32-bit Scan 32-bit kernel.
100105
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
101106
-d, --debug Display debugging output.
@@ -116,6 +121,7 @@ sub help
116121
'squash-by-path' => \$squash_by_path,
117122
'squash-by-filename' => \$squash_by_filename,
118123
'raw' => \$raw,
124+
'kallsyms=s' => \$kallsyms_file,
119125
'kernel-config-file=s' => \$kernel_config_file,
120126
'32-bit' => \$opt_32bit,
121127
'page-offset-32-bit=o' => \$page_offset_32bit,
@@ -156,6 +162,25 @@ sub help
156162
select $fh;
157163
}
158164

165+
if ($kallsyms_file) {
166+
open my $fh, '<', $kallsyms_file or die "$0: $kallsyms_file: $!\n";
167+
while (<$fh>) {
168+
chomp;
169+
my @entry = split / /, $_;
170+
my $addr_text = $entry[0];
171+
if ($addr_text !~ /^0/) {
172+
# TODO: Why is hex() so impossibly slow?
173+
my $addr = hex($addr_text);
174+
my $symbol = $entry[2];
175+
# Only keep kernel text addresses.
176+
my $long = pack("J", $addr);
177+
my $entry = [$long, $symbol];
178+
push @kallsyms, $entry;
179+
}
180+
}
181+
close $fh;
182+
}
183+
159184
parse_dmesg();
160185
walk(@DIRS);
161186

@@ -447,6 +472,25 @@ sub timed_parse_file
447472
}
448473
}
449474

475+
sub parse_binary
476+
{
477+
my ($file) = @_;
478+
479+
open my $fh, "<:raw", $file or return;
480+
local $/ = undef;
481+
my $bytes = <$fh>;
482+
close $fh;
483+
484+
foreach my $entry (@kallsyms) {
485+
my $addr = $entry->[0];
486+
my $symbol = $entry->[1];
487+
my $offset = index($bytes, $addr);
488+
if ($offset != -1) {
489+
printf("$file: $symbol @ $offset\n");
490+
}
491+
}
492+
}
493+
450494
sub parse_file
451495
{
452496
my ($file) = @_;
@@ -456,6 +500,15 @@ sub parse_file
456500
}
457501

458502
if (! -T $file) {
503+
if ($file =~ m|^/sys/kernel/btf/| or
504+
$file =~ m|^/sys/devices/pci| or
505+
$file =~ m|^/sys/firmware/efi/efivars/| or
506+
$file =~ m|^/proc/bus/pci/|) {
507+
return;
508+
}
509+
if (scalar @kallsyms > 0) {
510+
parse_binary($file);
511+
}
459512
return;
460513
}
461514

0 commit comments

Comments
 (0)