[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1508394884-13869-1-git-send-email-me@tobin.cc>
Date: Thu, 19 Oct 2017 17:34:44 +1100
From: "Tobin C. Harding" <me@...in.cc>
To: kernel-hardening@...ts.openwall.com
Cc: "Tobin C. Harding" <me@...in.cc>,
"Jason A. Donenfeld" <Jason@...c4.com>,
Theodore Ts'o <tytso@....edu>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Kees Cook <keescook@...omium.org>,
Paolo Bonzini <pbonzini@...hat.com>,
Tycho Andersen <tycho@...ker.com>,
"Roberts, William C" <william.c.roberts@...el.com>,
Tejun Heo <tj@...nel.org>,
Jordan Glover <Golden_Miller83@...tonmail.ch>,
Greg KH <gregkh@...uxfoundation.org>,
Petr Mladek <pmladek@...e.com>, Joe Perches <joe@...ches.com>,
Ian Campbell <ijc@...lion.org.uk>,
Sergey Senozhatsky <sergey.senozhatsky@...il.com>,
Catalin Marinas <catalin.marinas@....com>,
Will Deacon <wilal.deacon@....com>,
Steven Rostedt <rostedt@...dmis.org>,
Chris Fries <cfries@...gle.com>,
Dave Weinstein <olorin@...gle.com>,
Daniel Micay <danielmicay@...il.com>,
Djalal Harouni <tixxdz@...il.com>, linux-kernel@...r.kernel.org
Subject: [RFC] scripts: add leaking_addresses.pl
Currently we are leaking addresses from the kernel to user space. This
script as an attempt to find those leakages. Script parses `dmesg`
output and /proc and /sys files for suspicious entries.
Signed-off-by: Tobin C. Harding <me@...in.cc>
---
My usual disclaimer; I am a long way from being a Perl monger, any tips,
however trivial, most welcome.
Parses dmesg output first then;
Algorithm walks the directory tree of /proc and /sys, opens each file
for reading and parses file line by line. We therefore need to skip
certain files;
- binary files.
- relay large files of fixed format that _definitely_ won't leak.
- non-readable files.
Since I do not know procfs or sysfs extensively I set `DEBUG = 1` within
the script (causes output of file name before parsing) and checked each
file it choked on. Obviously this means there are going to be a bunch of
other files not present on my system. Either more files to skip or a
suggestion of a better way to do this most appreciated.
Like I said, happy to take suggestions, abuse, tweaks etc
Thanks in advance for taking the time to look at this. Oh, I didn't
comment on my regex skills, no further comment required ;)
thanks,
Tobin.
scripts/leaking_addresses.pl | 139 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 139 insertions(+)
create mode 100755 scripts/leaking_addresses.pl
diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl
new file mode 100755
index 000000000000..940547b716e3
--- /dev/null
+++ b/scripts/leaking_addresses.pl
@@ -0,0 +1,139 @@
+#!/usr/bin/env perl
+#
+# leaking_addresses.pl scan kernel for potential leaking addresses.
+
+use warnings;
+use strict;
+use File::Basename;
+use feature 'say';
+
+my $DEBUG = 0;
+my @dirs = ('/proc', '/sys');
+
+parse_dmesg();
+
+foreach(@dirs)
+{
+ walk($_);
+}
+
+exit 0;
+
+#
+# TODO
+#
+# - Add support for 32 bit architectures.
+#
+sub may_leak_address
+{
+ my $line = $_[0];
+ my $regex = 'ffff[a-fA-F0-9]{12}';
+ my $mask = 'ffffffffffffffff';
+
+ if ($line =~ /$mask/) {
+ return
+ }
+
+ if ($line =~ /$regex/) {
+ return 1;
+ }
+ return;
+}
+
+sub parse_dmesg
+{
+ my $line;
+ open my $cmd, '-|', 'dmesg';
+ while ($line = <$cmd>) {
+ if (may_leak_address($line)) {
+ print 'dmesg: ' . $line;
+ }
+ }
+ close $cmd;
+}
+
+# We should skip these files
+sub skip_file
+{
+ my $path = $_[0];
+
+ my @skip_paths = ('/proc/kmsg', '/proc/kcore', '/proc/kallsyms',
+ '/proc/fs/ext4/sdb1/mb_groups', '/sys/kernel/debug/tracing/trace_pipe',
+ '/sys/kernel/security/apparmor/revision');
+ my @skip_files = ('pagemap', 'events', 'access','registers', 'snapshot_raw',
+ 'trace_pipe_raw', 'trace_pipe');
+
+ foreach(@skip_paths) {
+ if ($_ eq $_[0]) {
+ return 1;
+ }
+ }
+
+ my($filename, $dirs, $suffix) = fileparse($path);
+
+ foreach(@skip_files) {
+ if ($_ eq $filename) {
+ return 1;
+ }
+ }
+
+ return;
+}
+
+sub parse_file
+{
+ my $file = $_[0];
+
+ if (! -R $file) {
+ return;
+ }
+
+ if (skip_file($file)) {
+ if ($DEBUG == 1) {
+ print "skipping file: $file\n";
+ }
+ return;
+ }
+ if ($DEBUG == 1) {
+ print "parsing $file\n";
+ }
+
+ open my $fh, $file or return;
+
+ while( my $line = <$fh>) {
+ if (may_leak_address($line)) {
+ print $file . ': ' . $line;
+ }
+ }
+
+ close $fh;
+}
+
+# Recursively walk directory tree
+sub walk
+{
+ my @dirs = ($_[0]);
+ my %seen;
+
+ while (my $pwd = shift @dirs) {
+ if (!opendir(DIR,"$pwd")) {
+ print STDERR "Cannot open $pwd\n";
+ next;
+ }
+ my @files = readdir(DIR);
+ closedir(DIR);
+ foreach my $file (@files) {
+ next if ($file eq '.' or $file eq '..');
+
+ my $path = "$pwd/$file";
+ next if (-l $path);
+
+ if (-d $path and !$seen{$path}) {
+ $seen{$path} = 1;
+ push @dirs, "$path";
+ } else {
+ parse_file("$path");
+ }
+ }
+ }
+}
--
2.7.4
Powered by blists - more mailing lists