From patchwork Thu Nov 23 05:14:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kaiwan N Billimoria X-Patchwork-Id: 10072335 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 D4A086056E for ; Thu, 23 Nov 2017 05:14:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C6CFC298C5 for ; Thu, 23 Nov 2017 05:14:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BA84A29BA0; Thu, 23 Nov 2017 05:14:24 +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_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, 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 6D630298C5 for ; Thu, 23 Nov 2017 05:14:20 +0000 (UTC) Received: (qmail 21879 invoked by uid 550); 23 Nov 2017 05:14:18 -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 21824 invoked from network); 23 Nov 2017 05:14:17 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=message-id:subject:from:to:cc:date:mime-version :content-transfer-encoding; bh=3XbmrdPsx3owFiidhpmNeEVS04votzKQmFxksdXA1Wg=; b=jqSKqlx/wfddWyVYSMCh2HmMTm0+a3wtd48RpfQXslasNEOfMK6CcRM51L1CRG7loR Plx6/Y+aecDHohUw5AhYRQ3brB6guk6b+5N0ETbnS+YutTHE1CSiC2HCkg2bqQ3w67JC DuA0nTfsnJHsmzbbxvtBFLytLn6WnAuvnxtCxCqzvGU8S5XPDvl02yHDiS7ajiQHwRNl 69Kgs53FitlMsUvbQWEnSFzu51UuidY47z0lDWFG7dezQIgU0nFghDznd7huvMxfF7fh xYbkPJDHuwnLdliHlI/+7iLPIRtkS8fpI0WU+SjOyb7zfzNicvxlfs5WCCdU3AviOJPu zbuw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:message-id:subject:from:to:cc:date:mime-version :content-transfer-encoding; bh=3XbmrdPsx3owFiidhpmNeEVS04votzKQmFxksdXA1Wg=; b=GcmeXDfKBdIS2JluIapUTqFeb4dynUTgfGnJ7V7JDNb8/Ueiu2VBG8H2KTgOHHCz3z Y1MgJDmO5WD/O8HPZ5/gaBMdHJzUUgJUYTgrNV4paEYfBUT+sbW5XB6zcH2YCYyPl8kF s84gV6Wu8ggc7bNCSwebwHIPXPcD4KWcS7gE8ZM3xhY+RqRjPJ7viED5nboFkKuMXsGr jltLdozrklxfAE4ZTr4pQBU0K+xWci1KOxv48vgPuLx+XP/v7pSIgA7YJB5EA3mqwLLc z2IXUxSvo3R4Gwx+C5ob2v8v1+A36D34Mmh4XEkiZG+UnNmO84AkF7azl2UIggYdXviu El0w== X-Gm-Message-State: AJaThX7ljDqtpjRhJRzI3RCTEZ2XUCz2upV3ni2fjTBtaloMvPlzlZ9s 92k9786UcEZ9OealX9UicCk= X-Google-Smtp-Source: AGs4zMat7fqSZ+K94m7REgp28LR/GIPHkJh8CRwGm5V5WqX/4PYxB8UaIyt4tKKa50ZGlvqytvqWkA== X-Received: by 10.36.131.200 with SMTP id d191mr9935266ite.97.1511414044796; Wed, 22 Nov 2017 21:14:04 -0800 (PST) Message-ID: <1511414040.12425.11.camel@gmail.com> From: kaiwan.billimoria@gmail.com To: "Tobin C. Harding" Cc: linux-kernel@vger.kernel.org, "kernel-hardening@lists.openwall.com" Date: Thu, 23 Nov 2017 10:44:00 +0530 X-Mailer: Evolution 3.26.2 (3.26.2-1.fc27) Mime-Version: 1.0 Subject: [kernel-hardening] [PATCH 1/2] scripts: leaking_addresses: add support for 32-bit kernel addresses X-Virus-Scanned: ClamAV using ClamSMTP The current leaking_addresses.pl script only supports showing "leaked" 64-bit kernel virtual addresses. This patch adds support for showing "leaked" 32-bit kernel virtual addresses. It also takes into account Tobin's feedback on the previous iteration. (Note: this patch is meant to apply on the 'leaks' branch of Tobin's tree). Briefly, the way it works- once it detects we're running on an i'x'86 platform, (where x=3|4|5|6), it takes this arch into account for checking. The essential rationale: if virt-addr >= PAGE_OFFSET => it's a kernel virtual address. This version programatically queries and sets PAGE_OFFSET based on the /boot/config-$(uname -r) content. If, for any reason, this file cannot be used, we fallback to requesting the user to pass PAGE_OFFSET as a parameter. Pending/TODO: - support for ARM-32 Feedback welcome.. Signed-off-by: Kaiwan N Billimoria diff --git a/scripts/leaking_addresses.pl b/scripts/leaking_addresses.pl index 865c07649dff..0566f8055ec5 100755 --- a/scripts/leaking_addresses.pl +++ b/scripts/leaking_addresses.pl @@ -2,10 +2,10 @@ # # (c) 2017 Tobin C. Harding # (c) 2017 Kaiwan N Billimoria (ix86 support) - + # 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 32/64 bit kernel for potential leaking addresses. # - Scans dmesg output. # - Walks directory tree and parses each file (for each directory in @DIRS). # @@ -14,7 +14,7 @@ # # You may like to set kptr_restrict=2 before running script # (see Documentation/sysctl/kernel.txt). - +# use warnings; use strict; use POSIX; @@ -37,7 +37,7 @@ 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'); +my @SUPPORTED_ARCHITECTURES = ('x86_64', 'ppc64', 'i[3456]86'); # Command line options. my $help = 0; @@ -49,6 +49,12 @@ my $input_raw = ""; # Read raw results from file instead of scanning. 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 $page_offset_param = 0; # 32-bit: overrides value of PAGE_OFFSET_32BIT + +my $bit_size = 64; # Check 64-bit kernel addresses by default +my $kconfig_file = '/boot/config-'.`uname -r`; +$kconfig_file =~ s/\R*//g; +my $PAGE_OFFSET_32BIT = 0xc0000000; # Do not parse these files (absolute path). my @skip_parse_files_abs = ('/proc/kmsg', @@ -99,10 +105,11 @@ Options: -o, --output-raw= Save results for future processing. -i, --input-raw= Read results from file instead of scanning. - --raw Show raw results (default). - --suppress-dmesg Do not show dmesg results. - --squash-by-path Show one result per unique path. - --squash-by-filename Show one result per unique filename. + --raw Show raw results (default). + --suppress-dmesg Do not show dmesg results. + --squash-by-path Show one result per unique path. + --squash-by-filename Show one result per unique filename. + --page-offset= PAGE_OFFSET value (for 32-bit kernels). -d, --debug Display debugging output. -h, --help, --version Display this help and exit. @@ -117,7 +124,7 @@ Examples: # View summary report. $0 --input-raw scan.out --squash-by-filename -Scans the running (64 bit) kernel for potential leaking addresses. +Scans the running (32 or 64 bit) kernel for potential leaking addresses. EOM exit($exitcode); @@ -133,10 +140,16 @@ GetOptions( 'squash-by-path' => \$squash_by_path, 'squash-by-filename' => \$squash_by_filename, 'raw' => \$raw, + 'page-offset=o' => \$page_offset_param, ) or help(1); help(0) if ($help); +sub dprint +{ + printf(STDERR @_) if $debug; +} + if ($input_raw) { format_output($input_raw); exit(0); @@ -162,6 +175,24 @@ if (!is_supported_architecture()) { exit(129); } +dprint "Detected arch : $bit_size bits\n"; + +if ($bit_size == 32) { + # Parameter --page-offset passed? if Y, override with it + if ($page_offset_param != 0) { + $PAGE_OFFSET_32BIT = $page_offset_param; + } else { + $PAGE_OFFSET_32BIT = eval parse_kconfig($kconfig_file, "CONFIG_PAGE_OFFSET"); + if ($PAGE_OFFSET_32BIT == 0) { + printf "$P: Fatal Error :: couldn't parse CONFIG_PAGE_OFFSET, aborting...\n"; + printf " [Detail :: arch=32-bit, kconfig file=$kconfig_file]\n\n"; + printf "You can pass it as a parameter via the --page-offset= option switch.\n"; + exit(1); + } + } + dprint "PAGE_OFFSET = 0x%X\n", $PAGE_OFFSET_32BIT; +} + if ($output_raw) { open my $fh, '>', $output_raw or die "$0: $output_raw: $!\n"; select $fh; @@ -172,14 +203,9 @@ walk(@DIRS); exit 0; -sub dprint -{ - printf(STDERR @_) if $debug; -} - sub is_supported_architecture { - return (is_x86_64() or is_ppc64()); + return (is_x86_64() or is_ppc64() or is_ix86_32()); } sub is_x86_64 @@ -187,6 +213,7 @@ sub is_x86_64 my $archname = $Config{archname}; if ($archname =~ m/x86_64/) { + $bit_size = 64; return 1; } return 0; @@ -197,6 +224,19 @@ sub is_ppc64 my $archname = $Config{archname}; if ($archname =~ m/powerpc/ and $archname =~ m/64/) { + $bit_size = 64; + return 1; + } + return 0; +} + +# 32-bit x86: is_i'x'86_32() ; where is [3 or 4 or 5 or 6] +sub is_ix86_32 +{ + my $archname = $Config{archname}; + + if ($archname =~ m/i[3456]86-linux/) { + $bit_size = 32; return 1; } return 0; @@ -217,6 +257,14 @@ sub is_false_positive $match =~ '\bf{10}601000\b') { return 1; } + } elsif ($bit_size == 32) { + my $addr32 = eval hex($match); + if ($addr32 < $PAGE_OFFSET_32BIT ) { + return 1; + } + if ($match =~ '\b(0x)?(f|F){8}\b') { + return 1; + } } return 0; @@ -245,6 +293,8 @@ sub may_leak_address $address_re = '\b(0x)?ffff[[:xdigit:]]{12}\b'; } elsif (is_ppc64()) { $address_re = '\b(0x)?[89abcdef]00[[:xdigit:]]{13}\b'; + } elsif (is_ix86_32()) { + $address_re = '\b(0x)?[[:xdigit:]]{8}\b'; } while (/($address_re)/g) { @@ -501,3 +551,28 @@ sub add_to_cache } push @{$cache->{$key}}, $value; } + +sub parse_kconfig +{ + my ($file,$config) = @_; + my $str; + my $val=NULL; + + if (! -R $file) { + return NULL; + } + + open my $fh, "<", $file or return; + while (my $line = <$fh> ) { + if ($line =~ /^$config/) { + ($str,$val) = split /=/, $line; + } + } + close $fh; + + if ($val eq NULL) { + return NULL; + } + $val =~ s/\R*//g; + return $val; +}