From patchwork Wed Oct 11 03:48:16 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tobin Harding X-Patchwork-Id: 9998645 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 B49EA60230 for ; Wed, 11 Oct 2017 03:48:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9FE1B2889F for ; Wed, 11 Oct 2017 03:48:48 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 945A4288A3; Wed, 11 Oct 2017 03:48:48 +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 824FC2889E for ; Wed, 11 Oct 2017 03:48:46 +0000 (UTC) Received: (qmail 29969 invoked by uid 550); 11 Oct 2017 03:48:44 -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 29948 invoked from network); 11 Oct 2017 03:48:43 -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=dZ7pORfaC6xHNxV9EEsPGmURCdb2OgRujbhXAkiqO nw=; b=NCxFQg+o3gTK/xmoDh4j58uhamUOagkmGJVqzkOJV4ZtgmbAUFKldnWld 8h+YUb4XkBGKK1ZEGgdFffcX1gNxWynCr8hvPq5s7LQMYI6ZlmGTMmyokNKc9M3h bQ1pO0/qIkP5drQgYnpybGcjT1IY6iaak4zWA4PKAaB4BWc8AtFm3BviEQ6TsHUe VwUd9Tyy6LuaEuWgoHwRoaKxWJJi5xbzpiJtKx3yKOa095VR3EVZrPJ+TVXRC0Fq 67AqLS6gR6IGVoLVlaTHA5jfdhi8MWhtajp7Uo1cmW/Z8h3r5tF8RnRZfrzpJw/p +pKoWXTXneXnEGEyUY1IPmmxh+mfA== 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=dZ7pORfaC6xHNxV9E EsPGmURCdb2OgRujbhXAkiqOnw=; b=ivUDmoaT0HYLtQ2LCGkopJSI3PFNkf80h v85lLSy32TaSoP2ycjc0xWRmiHo0drt6yTl/oHKSW+1UA/YS3yKMWDtCg97t8XvK U3J9JEzdwQLzLzdmV9hYN/ni1bGJKNnL+SQpgxwCnUa/TBrHcDDhp8pm9c2khMSk PTHTAk6nfMAbdLxTnR53kHmJ9XLLQZPND/ZLe8KLS+4KiFtlDghCyBBVkDMwWiS7 jbVN8zD8Xe9b53Q2W7U5dT9FwdIIdjatGdKhOIozH2UV8w7UHRcUsStUC56PGXm6 z6nP5vZWa8//Ig/ZpXHB9zKpFJy6OTGQd7CzvUcZRL1p2wOLksDuQ== X-ME-Sender: From: "Tobin C. Harding" To: kernel-hardening@lists.openwall.com, kvm@vger.kernel.org, linux-kernel@vger.kernel.org Cc: "Tobin C. Harding" , 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 Date: Wed, 11 Oct 2017 14:48:16 +1100 Message-Id: <1507693696-3777-1-git-send-email-me@tobin.cc> X-Mailer: git-send-email 2.7.4 Subject: [kernel-hardening] [PATCH] printk: hash addresses printed with %p X-Virus-Scanned: ClamAV using ClamSMTP Currently there are many places in the kernel where addresses are being printed using an unadorned %p. Kernel pointers should be printed using %pK allowing some control via the kptr_restrict sysctl. Exposing addresses gives attackers sensitive information about the kernel layout in memory. We can reduce the attack surface by hashing all addresses printed with %p. This will of course break some users, forcing code printing needed addresses to be updated. For what it's worth, usage of unadorned %p can be broken down as follows git grep '%p[^KFfSsBRrbMmIiEUVKNhdDgCGO]' | wc -l arch: 2512 block: 20 crypto: 12 fs: 1221 include: 147 kernel: 109 lib: 77 mm: 120 net: 1516 security: 11 sound: 168 virt: 2 drivers: 8420 Add function ptr_to_id() to map an address to a unique identifier. This mapping is created by calling ptr_obfuscate() to hash the address. The hashing algorithm is carried out in two stages. First the address is xor'd by a random value then we multiply the xor production by a second random value. Signed-off-by: Tobin C. Harding --- This is version 2 of the series (of which I sent only the cover letter, failing to send the actual patches) [PATCH 0/3] add %pX specifier Implementing changes as suggested by Linus (in response to the cover letter). Patch 2 and 3 of the original series dropped. include/linux/printk.h | 17 +++++++++++++++++ lib/vsprintf.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/include/linux/printk.h b/include/linux/printk.h index e10f27468322..60c3d018efcf 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -41,6 +41,23 @@ static inline const char *printk_skip_headers(const char *buffer) return buffer; } +/* + * Obfuscates pointer (algorithm taken from kptr_obfuscate(). See kernel/kcmp.c) + * v is the pointer value, randval is some random value, oddval is some random + * odd value. + * + * The obfuscation is done in two steps. First we xor the kernel pointer with + * a random value, which puts pointer into a new position in a reordered space. + * Secondly we multiply the xor production with a large odd random number to + * permute its bits even more (the odd multiplier guarantees that the product + * is unique ever after the high bits are truncated, since any odd number is + * relative prime to 2^n). + */ +static inline long ptr_obfuscate(long v, long randval, long oddval) +{ + return (v ^ randval) * oddval; +} + #define CONSOLE_EXT_LOG_MAX 8192 /* printk's without a loglevel use this.. */ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 86c3385b9eb3..399cc090be75 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1591,6 +1591,35 @@ char *device_node_string(char *buf, char *end, struct device_node *dn, return widen_string(buf, buf - buf_start, end, spec); } +static long get_random_odd_long(void) +{ + long val = 0; + + while((val & 1) == 0) { + val = get_random_long(); + } + + return val; +} + +/* Maps a pointer to a unique identifier. */ +static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) +{ + long hashval; + static long randval = 0; + static long oddval = 0; + + if (oddval == 0 && randval == 0) { + randval = get_random_long(); + oddval = get_random_odd_long(); + } + + hashval = ptr_obfuscate((unsigned long)ptr, randval, oddval); + spec.base = 16; + + return number(buf, end, hashval, spec); +} + int kptr_restrict __read_mostly; /* @@ -1703,6 +1732,9 @@ int kptr_restrict __read_mostly; * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 * function pointers are really function descriptors, which contain a * pointer to the real address. + * + * Default behaviour (unadorned %p) is to hash the address, rendering it useful + * as a unique identifier. */ static noinline_for_stack char *pointer(const char *fmt, char *buf, char *end, void *ptr, @@ -1858,14 +1890,13 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, return device_node_string(buf, end, ptr, spec, fmt + 1); } } - spec.flags |= SMALL; if (spec.field_width == -1) { spec.field_width = default_width; spec.flags |= ZEROPAD; } spec.base = 16; - return number(buf, end, (unsigned long) ptr, spec); + return ptr_to_id(buf, end, ptr, spec); } /*