From patchwork Thu Oct 19 06:34:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tobin Harding X-Patchwork-Id: 10016055 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 96C45602C8 for ; Thu, 19 Oct 2017 06:35:21 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8893428C6E for ; Thu, 19 Oct 2017 06:35:21 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7C26828C95; Thu, 19 Oct 2017 06:35:21 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.wl.linuxfoundation.org (Postfix) with SMTP id 2692D28C91 for ; Thu, 19 Oct 2017 06:35:19 +0000 (UTC) Received: (qmail 18377 invoked by uid 550); 19 Oct 2017 06:35:17 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 18341 invoked from network); 19 Oct 2017 06:35:16 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=tobin.cc; h=cc :date:from:message-id:subject:to:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=lC+z/7qM/FnIQQzDjusePGgJll8ksByU/5W+jkRvr 8I=; b=UjLgXHDumMIi9RSH4rnBmyj/b64HJbw2fJJVp9IcwFNSnPbV2MQj55uQy 9aOAzdksPoEPcrAV1YAbY+kVV7QlRhTDoUrjW4KxdivTGLQqKZ48ufKvqn4LlU5T cBnICtAHsedkP8S7+IfXWGyoVXFpQ8qQ+u4f2EUw2Igrl7PWFBVPGYYL0MmsZy0H Ankq2D+8hiYXha2IqF9jr0OHyawCWZgI2umV//t6zyYQiMSupPcEbCjDQ/4F5b/g eNYCbpFQK/WX9+51E2d4djoSNstM42Xr8Hungn+V8+UzdEnYjeWgJ+CxvqyY5EAo gLv/Fi4Swwj7AjwalJ024khvLDWug== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:date:from:message-id:subject:to :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=lC+z/7qM/FnIQQzDj usePGgJll8ksByU/5W+jkRvr8I=; b=OXmTf4aqUwLRlZjbfkYCcN7AfgvWbVGxW LAYQVzjRTMHiWf426o3FSBKgUjrXFsB4S+r2gJHgv6R1UiqJpKsiIkHgaY9b9s6/ QyGDnDOdWjLNh+HZpSXhm8P2GnUWY3uGQSO3ft4fNMP2JhJP9sMRsOEsPLDcrEIR IoQJdMWuUKJhGcHRZiDY/VR/eMndCxb7mTbFn/7JZQFZfuaBbVDYbS8641AUF6Fm YSy2E+uIuXyBQPiIf+WHYzje1O2EQCxIDeRHGbj1G4jvMJ14GZ8LZQxF69E4Bica 44SYjDKxkiSXaKaQwTBd4XswCntSG0/8wtEZ+zGfwsgcMavfZvnEQ== X-ME-Sender: From: "Tobin C. Harding" To: kernel-hardening@lists.openwall.com Cc: "Tobin C. Harding" , "Jason A. Donenfeld" , Theodore Ts'o , Linus Torvalds , Kees Cook , Paolo Bonzini , Tycho Andersen , "Roberts, William C" , Tejun Heo , Jordan Glover , Greg KH , Petr Mladek , Joe Perches , Ian Campbell , Sergey Senozhatsky , Catalin Marinas , Will Deacon , Steven Rostedt , Chris Fries , Dave Weinstein , Daniel Micay , Djalal Harouni , linux-kernel@vger.kernel.org Date: Thu, 19 Oct 2017 17:34:44 +1100 Message-Id: <1508394884-13869-1-git-send-email-me@tobin.cc> X-Mailer: git-send-email 2.7.4 Subject: [kernel-hardening] [RFC] scripts: add leaking_addresses.pl X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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"); + } + } + } +}