Commit 1410fe4e authored by Tobin C. Harding's avatar Tobin C. Harding

leaking_addresses: add 32-bit support

Currently script only supports x86_64 and ppc64.  It would be nice to be
able to scan 32-bit machines also.  We can add support for 32-bit
architectures by modifying how we check for false positives, taking
advantage of the page offset used by the kernel, and using the correct
regular expression.

Support for 32-bit machines is enabled by the observation that the kernel
addresses on 32-bit machines are larger [in value] than the page offset.
We can use this to filter false positives when scanning the kernel for
leaking addresses.

Programmatic determination of the running architecture is not
immediately obvious (current 32-bit machines return various strings from
`uname -m`).  We therefore provide a flag to enable scanning of 32-bit
kernels.  Also we can check the kernel config file for the offset and if
not found default to 0xc0000000.  A command line option to parse in the
page offset is also provided.  We do automatically detect architecture
if running on ix86.

Add support for 32-bit kernels.  Add a command line option for page
offset.
Suggested-by: default avatarKaiwan N Billimoria <kaiwan.billimoria@gmail.com>
Signed-off-by: default avatarTobin C. Harding <me@tobin.cc>
parent 5eb0da05
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# (c) 2017 Tobin C. Harding <me@tobin.cc> # (c) 2017 Tobin C. Harding <me@tobin.cc>
# Licensed under the terms of the GNU GPL License version 2 # Licensed under the terms of the GNU GPL License version 2
# #
# leaking_addresses.pl: Scan 64 bit kernel for potential leaking addresses. # leaking_addresses.pl: Scan the kernel for potential leaking addresses.
# - Scans dmesg output. # - Scans dmesg output.
# - Walks directory tree and parses each file (for each directory in @DIRS). # - Walks directory tree and parses each file (for each directory in @DIRS).
# #
...@@ -31,10 +31,9 @@ my @DIRS = ('/proc', '/sys'); ...@@ -31,10 +31,9 @@ my @DIRS = ('/proc', '/sys');
# Timer for parsing each file, in seconds. # Timer for parsing each file, in seconds.
my $TIMEOUT = 10; my $TIMEOUT = 10;
# Script can only grep for kernel addresses on the following architectures. If # Kernel addresses vary by architecture. We can only auto-detect the following
# your architecture is not listed here and has a grep'able kernel address please # architectures (using `uname -m`). (flag --32-bit overrides auto-detection.)
# consider submitting a patch. my @SUPPORTED_ARCHITECTURES = ('x86_64', 'ppc64', 'x86');
my @SUPPORTED_ARCHITECTURES = ('x86_64', 'ppc64');
# Command line options. # Command line options.
my $help = 0; my $help = 0;
...@@ -46,6 +45,8 @@ my $suppress_dmesg = 0; # Don't show dmesg in output. ...@@ -46,6 +45,8 @@ 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 $kernel_config_file = ""; # Kernel configuration 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.
# Do not parse these files (absolute path). # Do not parse these files (absolute path).
my @skip_parse_files_abs = ('/proc/kmsg', my @skip_parse_files_abs = ('/proc/kmsg',
...@@ -101,10 +102,12 @@ Options: ...@@ -101,10 +102,12 @@ 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)
--32-bit Scan 32-bit kernel.
--page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
-d, --debug Display debugging output. -d, --debug Display debugging output.
-h, --help, --version Display this help and exit. -h, --help, --version Display this help and exit.
Scans the running (64 bit) kernel for potential leaking addresses. Scans the running kernel for potential leaking addresses.
EOM EOM
exit($exitcode); exit($exitcode);
...@@ -121,6 +124,8 @@ GetOptions( ...@@ -121,6 +124,8 @@ GetOptions(
'squash-by-filename' => \$squash_by_filename, 'squash-by-filename' => \$squash_by_filename,
'raw' => \$raw, 'raw' => \$raw,
'kernel-config-file=s' => \$kernel_config_file, 'kernel-config-file=s' => \$kernel_config_file,
'32-bit' => \$opt_32bit,
'page-offset-32-bit=o' => \$page_offset_32bit,
) or help(1); ) or help(1);
help(0) if ($help); help(0) if ($help);
...@@ -136,7 +141,7 @@ if (!$input_raw and ($squash_by_path or $squash_by_filename)) { ...@@ -136,7 +141,7 @@ if (!$input_raw and ($squash_by_path or $squash_by_filename)) {
exit(128); exit(128);
} }
if (!is_supported_architecture()) { if (!(is_supported_architecture() or $opt_32bit or $page_offset_32bit)) {
printf "\nScript does not support your architecture, sorry.\n"; printf "\nScript does not support your architecture, sorry.\n";
printf "\nCurrently we support: \n\n"; printf "\nCurrently we support: \n\n";
foreach(@SUPPORTED_ARCHITECTURES) { foreach(@SUPPORTED_ARCHITECTURES) {
...@@ -144,6 +149,9 @@ if (!is_supported_architecture()) { ...@@ -144,6 +149,9 @@ if (!is_supported_architecture()) {
} }
printf("\n"); printf("\n");
printf("If you are running a 32-bit architecture you may use:\n");
printf("\n\t--32-bit or --page-offset-32-bit=<page offset>\n\n");
my $archname = `uname -m`; my $archname = `uname -m`;
printf("Machine hardware name (`uname -m`): %s\n", $archname); printf("Machine hardware name (`uname -m`): %s\n", $archname);
...@@ -167,7 +175,28 @@ sub dprint ...@@ -167,7 +175,28 @@ sub dprint
sub is_supported_architecture sub is_supported_architecture
{ {
return (is_x86_64() or is_ppc64()); return (is_x86_64() or is_ppc64() or is_ix86_32());
}
sub is_32bit
{
# Allow --32-bit or --page-offset-32-bit to override
if ($opt_32bit or $page_offset_32bit) {
return 1;
}
return is_ix86_32();
}
sub is_ix86_32
{
my $arch = `uname -m`;
chomp $arch;
if ($arch =~ m/i[3456]86/) {
return 1;
}
return 0;
} }
sub is_arch sub is_arch
...@@ -258,6 +287,12 @@ sub is_false_positive ...@@ -258,6 +287,12 @@ sub is_false_positive
{ {
my ($match) = @_; my ($match) = @_;
if (is_32bit()) {
return is_false_positive_32bit($match);
}
# 64 bit false positives.
if ($match =~ '\b(0x)?(f|F){16}\b' or if ($match =~ '\b(0x)?(f|F){16}\b' or
$match =~ '\b(0x)?0{16}\b') { $match =~ '\b(0x)?0{16}\b') {
return 1; return 1;
...@@ -270,6 +305,40 @@ sub is_false_positive ...@@ -270,6 +305,40 @@ sub is_false_positive
return 0; return 0;
} }
sub is_false_positive_32bit
{
my ($match) = @_;
state $page_offset = get_page_offset();
if ($match =~ '\b(0x)?(f|F){8}\b') {
return 1;
}
if (hex($match) < $page_offset) {
return 1;
}
return 0;
}
# returns integer value
sub get_page_offset
{
my $page_offset;
my $default_offset = 0xc0000000;
# Allow --page-offset-32bit to override.
if ($page_offset_32bit != 0) {
return $page_offset_32bit;
}
$page_offset = get_kernel_config_option('CONFIG_PAGE_OFFSET');
if (!$page_offset) {
return $default_offset;
}
return $page_offset;
}
sub is_in_vsyscall_memory_region sub is_in_vsyscall_memory_region
{ {
my ($match) = @_; my ($match) = @_;
...@@ -311,11 +380,13 @@ sub may_leak_address ...@@ -311,11 +380,13 @@ sub may_leak_address
sub get_address_re sub get_address_re
{ {
if (is_x86_64()) { if (is_ppc64()) {
return get_x86_64_re();
} elsif (is_ppc64()) {
return '\b(0x)?[89abcdef]00[[:xdigit:]]{13}\b'; return '\b(0x)?[89abcdef]00[[:xdigit:]]{13}\b';
} elsif (is_32bit()) {
return '\b(0x)?[[:xdigit:]]{8}\b';
} }
return get_x86_64_re();
} }
sub get_x86_64_re sub get_x86_64_re
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment