mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
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 $suppress_dmesg = 0; # Don't show dmesg in output.
|
||||||
my $squash_by_path = 0; # Summary report grouped by absolute path.
|
my $squash_by_path = 0; # Summary report grouped by absolute path.
|
||||||
my $squash_by_filename = 0; # Summary report grouped by filename.
|
my $squash_by_filename = 0; # Summary report grouped by filename.
|
||||||
|
my $kallsyms_file = ""; # Kernel symbols file.
|
||||||
my $kernel_config_file = ""; # Kernel configuration file.
|
my $kernel_config_file = ""; # Kernel configuration file.
|
||||||
my $opt_32bit = 0; # Scan 32-bit kernel.
|
my $opt_32bit = 0; # Scan 32-bit kernel.
|
||||||
my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
|
my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
|
||||||
|
|
||||||
|
my @kallsyms = ();
|
||||||
|
|
||||||
# Skip these absolute paths.
|
# Skip these absolute paths.
|
||||||
my @skip_abs = (
|
my @skip_abs = (
|
||||||
'/proc/kmsg',
|
'/proc/kmsg',
|
||||||
@ -96,6 +99,8 @@ Options:
|
|||||||
--squash-by-path Show one result per unique path.
|
--squash-by-path Show one result per unique path.
|
||||||
--squash-by-filename Show one result per unique filename.
|
--squash-by-filename Show one result per unique filename.
|
||||||
--kernel-config-file=<file> Kernel configuration file (e.g /boot/config)
|
--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.
|
--32-bit Scan 32-bit kernel.
|
||||||
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
|
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
|
||||||
-d, --debug Display debugging output.
|
-d, --debug Display debugging output.
|
||||||
@ -116,6 +121,7 @@ GetOptions(
|
|||||||
'squash-by-path' => \$squash_by_path,
|
'squash-by-path' => \$squash_by_path,
|
||||||
'squash-by-filename' => \$squash_by_filename,
|
'squash-by-filename' => \$squash_by_filename,
|
||||||
'raw' => \$raw,
|
'raw' => \$raw,
|
||||||
|
'kallsyms=s' => \$kallsyms_file,
|
||||||
'kernel-config-file=s' => \$kernel_config_file,
|
'kernel-config-file=s' => \$kernel_config_file,
|
||||||
'32-bit' => \$opt_32bit,
|
'32-bit' => \$opt_32bit,
|
||||||
'page-offset-32-bit=o' => \$page_offset_32bit,
|
'page-offset-32-bit=o' => \$page_offset_32bit,
|
||||||
@ -156,6 +162,25 @@ if ($output_raw) {
|
|||||||
select $fh;
|
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();
|
parse_dmesg();
|
||||||
walk(@DIRS);
|
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
|
sub parse_file
|
||||||
{
|
{
|
||||||
my ($file) = @_;
|
my ($file) = @_;
|
||||||
@ -456,6 +500,15 @@ sub parse_file
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (! -T $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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user