summaryrefslogtreecommitdiffstats
path: root/scripts/leaking_addresses.pl
diff options
context:
space:
mode:
authorTobin C. Harding <me@tobin.cc>2018-01-28 23:00:16 -0500
committerTobin C. Harding <me@tobin.cc>2018-04-06 18:50:34 -0400
commit1410fe4eea22959bd31c05e4c1846f1718300bde (patch)
tree28b82ea47ec50a4eb718119206301e95128c419b /scripts/leaking_addresses.pl
parent5eb0da0568a241f72732eb2143538fb14879a52c (diff)
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: Kaiwan N Billimoria <kaiwan.billimoria@gmail.com> Signed-off-by: Tobin C. Harding <me@tobin.cc>
Diffstat (limited to 'scripts/leaking_addresses.pl')
-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 @@
3# (c) 2017 Tobin C. Harding <me@tobin.cc> 3# (c) 2017 Tobin C. Harding <me@tobin.cc>
4# Licensed under the terms of the GNU GPL License version 2 4# Licensed under the terms of the GNU GPL License version 2
5# 5#
6# leaking_addresses.pl: Scan 64 bit kernel for potential leaking addresses. 6# leaking_addresses.pl: Scan the kernel for potential leaking addresses.
7# - Scans dmesg output. 7# - Scans dmesg output.
8# - Walks directory tree and parses each file (for each directory in @DIRS). 8# - Walks directory tree and parses each file (for each directory in @DIRS).
9# 9#
@@ -31,10 +31,9 @@ my @DIRS = ('/proc', '/sys');
31# Timer for parsing each file, in seconds. 31# Timer for parsing each file, in seconds.
32my $TIMEOUT = 10; 32my $TIMEOUT = 10;
33 33
34# Script can only grep for kernel addresses on the following architectures. If 34# Kernel addresses vary by architecture. We can only auto-detect the following
35# your architecture is not listed here and has a grep'able kernel address please 35# architectures (using `uname -m`). (flag --32-bit overrides auto-detection.)
36# consider submitting a patch. 36my @SUPPORTED_ARCHITECTURES = ('x86_64', 'ppc64', 'x86');
37my @SUPPORTED_ARCHITECTURES = ('x86_64', 'ppc64');
38 37
39# Command line options. 38# Command line options.
40my $help = 0; 39my $help = 0;
@@ -46,6 +45,8 @@ my $suppress_dmesg = 0; # Don't show dmesg in output.
46my $squash_by_path = 0; # Summary report grouped by absolute path. 45my $squash_by_path = 0; # Summary report grouped by absolute path.
47my $squash_by_filename = 0; # Summary report grouped by filename. 46my $squash_by_filename = 0; # Summary report grouped by filename.
48my $kernel_config_file = ""; # Kernel configuration file. 47my $kernel_config_file = ""; # Kernel configuration file.
48my $opt_32bit = 0; # Scan 32-bit kernel.
49my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
49 50
50# Do not parse these files (absolute path). 51# Do not parse these files (absolute path).
51my @skip_parse_files_abs = ('/proc/kmsg', 52my @skip_parse_files_abs = ('/proc/kmsg',
@@ -101,10 +102,12 @@ Options:
101 --squash-by-path Show one result per unique path. 102 --squash-by-path Show one result per unique path.
102 --squash-by-filename Show one result per unique filename. 103 --squash-by-filename Show one result per unique filename.
103 --kernel-config-file=<file> Kernel configuration file (e.g /boot/config) 104 --kernel-config-file=<file> Kernel configuration file (e.g /boot/config)
105 --32-bit Scan 32-bit kernel.
106 --page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
104 -d, --debug Display debugging output. 107 -d, --debug Display debugging output.
105 -h, --help, --version Display this help and exit. 108 -h, --help, --version Display this help and exit.
106 109
107Scans the running (64 bit) kernel for potential leaking addresses. 110Scans the running kernel for potential leaking addresses.
108 111
109EOM 112EOM
110 exit($exitcode); 113 exit($exitcode);
@@ -121,6 +124,8 @@ GetOptions(
121 'squash-by-filename' => \$squash_by_filename, 124 'squash-by-filename' => \$squash_by_filename,
122 'raw' => \$raw, 125 'raw' => \$raw,
123 'kernel-config-file=s' => \$kernel_config_file, 126 'kernel-config-file=s' => \$kernel_config_file,
127 '32-bit' => \$opt_32bit,
128 'page-offset-32-bit=o' => \$page_offset_32bit,
124) or help(1); 129) or help(1);
125 130
126help(0) if ($help); 131help(0) if ($help);
@@ -136,7 +141,7 @@ if (!$input_raw and ($squash_by_path or $squash_by_filename)) {
136 exit(128); 141 exit(128);
137} 142}
138 143
139if (!is_supported_architecture()) { 144if (!(is_supported_architecture() or $opt_32bit or $page_offset_32bit)) {
140 printf "\nScript does not support your architecture, sorry.\n"; 145 printf "\nScript does not support your architecture, sorry.\n";
141 printf "\nCurrently we support: \n\n"; 146 printf "\nCurrently we support: \n\n";
142 foreach(@SUPPORTED_ARCHITECTURES) { 147 foreach(@SUPPORTED_ARCHITECTURES) {
@@ -144,6 +149,9 @@ if (!is_supported_architecture()) {
144 } 149 }
145 printf("\n"); 150 printf("\n");
146 151
152 printf("If you are running a 32-bit architecture you may use:\n");
153 printf("\n\t--32-bit or --page-offset-32-bit=<page offset>\n\n");
154
147 my $archname = `uname -m`; 155 my $archname = `uname -m`;
148 printf("Machine hardware name (`uname -m`): %s\n", $archname); 156 printf("Machine hardware name (`uname -m`): %s\n", $archname);
149 157
@@ -167,7 +175,28 @@ sub dprint
167 175
168sub is_supported_architecture 176sub is_supported_architecture
169{ 177{
170 return (is_x86_64() or is_ppc64()); 178 return (is_x86_64() or is_ppc64() or is_ix86_32());
179}
180
181sub is_32bit
182{
183 # Allow --32-bit or --page-offset-32-bit to override
184 if ($opt_32bit or $page_offset_32bit) {
185 return 1;
186 }
187
188 return is_ix86_32();
189}
190
191sub is_ix86_32
192{
193 my $arch = `uname -m`;
194
195 chomp $arch;
196 if ($arch =~ m/i[3456]86/) {
197 return 1;
198 }
199 return 0;
171} 200}
172 201
173sub is_arch 202sub is_arch
@@ -258,6 +287,12 @@ sub is_false_positive
258{ 287{
259 my ($match) = @_; 288 my ($match) = @_;
260 289
290 if (is_32bit()) {
291 return is_false_positive_32bit($match);
292 }
293
294 # 64 bit false positives.
295
261 if ($match =~ '\b(0x)?(f|F){16}\b' or 296 if ($match =~ '\b(0x)?(f|F){16}\b' or
262 $match =~ '\b(0x)?0{16}\b') { 297 $match =~ '\b(0x)?0{16}\b') {
263 return 1; 298 return 1;
@@ -270,6 +305,40 @@ sub is_false_positive
270 return 0; 305 return 0;
271} 306}
272 307
308sub is_false_positive_32bit
309{
310 my ($match) = @_;
311 state $page_offset = get_page_offset();
312
313 if ($match =~ '\b(0x)?(f|F){8}\b') {
314 return 1;
315 }
316
317 if (hex($match) < $page_offset) {
318 return 1;
319 }
320
321 return 0;
322}
323
324# returns integer value
325sub get_page_offset
326{
327 my $page_offset;
328 my $default_offset = 0xc0000000;
329
330 # Allow --page-offset-32bit to override.
331 if ($page_offset_32bit != 0) {
332 return $page_offset_32bit;
333 }
334
335 $page_offset = get_kernel_config_option('CONFIG_PAGE_OFFSET');
336 if (!$page_offset) {
337 return $default_offset;
338 }
339 return $page_offset;
340}
341
273sub is_in_vsyscall_memory_region 342sub is_in_vsyscall_memory_region
274{ 343{
275 my ($match) = @_; 344 my ($match) = @_;
@@ -311,11 +380,13 @@ sub may_leak_address
311 380
312sub get_address_re 381sub get_address_re
313{ 382{
314 if (is_x86_64()) { 383 if (is_ppc64()) {
315 return get_x86_64_re();
316 } elsif (is_ppc64()) {
317 return '\b(0x)?[89abcdef]00[[:xdigit:]]{13}\b'; 384 return '\b(0x)?[89abcdef]00[[:xdigit:]]{13}\b';
385 } elsif (is_32bit()) {
386 return '\b(0x)?[[:xdigit:]]{8}\b';
318 } 387 }
388
389 return get_x86_64_re();
319} 390}
320 391
321sub get_x86_64_re 392sub get_x86_64_re