summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/leaking_addresses.pl93
1 files changed, 82 insertions, 11 deletions
diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
index e5b418cca185..05906f6cf6b9 100755
--- a/scripts/leaking_addresses.pl
+++ b/scripts/leaking_addresses.pl
@@ -3,7 +3,7 @@
# (c) 2017 Tobin C. Harding <me@tobin.cc>
# 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.
# - Walks directory tree and parses each file (for each directory in @DIRS).
#
@@ -31,10 +31,9 @@ my @DIRS = ('/proc', '/sys');
# Timer for parsing each file, in seconds.
my $TIMEOUT = 10;
-# Script can only grep for kernel addresses on the following architectures. If
-# your architecture is not listed here and has a grep'able kernel address please
-# consider submitting a patch.
-my @SUPPORTED_ARCHITECTURES = ('x86_64', 'ppc64');
+# Kernel addresses vary by architecture. We can only auto-detect the following
+# architectures (using `uname -m`). (flag --32-bit overrides auto-detection.)
+my @SUPPORTED_ARCHITECTURES = ('x86_64', 'ppc64', 'x86');
# Command line options.
my $help = 0;
@@ -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_filename = 0; # Summary report grouped by filename.
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).
my @skip_parse_files_abs = ('/proc/kmsg',
@@ -101,10 +102,12 @@ 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)
+ --32-bit Scan 32-bit kernel.
+ --page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
-d, --debug Display debugging output.
-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
exit($exitcode);
@@ -121,6 +124,8 @@ GetOptions(
'squash-by-filename' => \$squash_by_filename,
'raw' => \$raw,
'kernel-config-file=s' => \$kernel_config_file,
+ '32-bit' => \$opt_32bit,
+ 'page-offset-32-bit=o' => \$page_offset_32bit,
) or help(1);
help(0) if ($help);
@@ -136,7 +141,7 @@ if (!$input_raw and ($squash_by_path or $squash_by_filename)) {
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 "\nCurrently we support: \n\n";
foreach(@SUPPORTED_ARCHITECTURES) {
@@ -144,6 +149,9 @@ if (!is_supported_architecture()) {
}
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`;
printf("Machine hardware name (`uname -m`): %s\n", $archname);
@@ -167,7 +175,28 @@ sub dprint
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
@@ -258,6 +287,12 @@ sub is_false_positive
{
my ($match) = @_;
+ if (is_32bit()) {
+ return is_false_positive_32bit($match);
+ }
+
+ # 64 bit false positives.
+
if ($match =~ '\b(0x)?(f|F){16}\b' or
$match =~ '\b(0x)?0{16}\b') {
return 1;
@@ -270,6 +305,40 @@ sub is_false_positive
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
{
my ($match) = @_;
@@ -311,11 +380,13 @@ sub may_leak_address
sub get_address_re
{
- if (is_x86_64()) {
- return get_x86_64_re();
- } elsif (is_ppc64()) {
+ if (is_ppc64()) {
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