Received: by 10.213.65.68 with SMTP id h4csp1152331imn; Wed, 21 Mar 2018 04:06:11 -0700 (PDT) X-Google-Smtp-Source: AG47ELsaW4V4lL5zy3280Lr4shmY1hes2xHPF2PelMgYgPMtSOrSBbuaQFOCIaJl9F+wpafjPjGm X-Received: by 10.99.171.11 with SMTP id p11mr12550650pgf.176.1521630371577; Wed, 21 Mar 2018 04:06:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521630371; cv=none; d=google.com; s=arc-20160816; b=Os/KtRIhTFThXWWbAxfv4iBfTINHRn+e579hsvEGnm0LTCgQEA5HKoQRZdo4Is8Vgj VMpdW4tC6uzGjYdYgAElTiCzjXKIWWkEruoqx1tIYBu3AywfP0uhP70/LUzERFdi4/9E PeRu0GRJzn4nq7m+Qp+8LD8F7RGCIhi4DB+CXnGgSfZPmSLvC+ZtL9grfo1qsyNLj+7i WrEWp7Bi1IPvc4Ty7kA4c4nEHga+Lf/vQb/WQtdHqzz1eDSvQV4jps0IuqkKnxLyVrrq zZts2klhM1ZBqGipvSzw2C5Ly4pQixU1wFjf9kiqFpVI9KRhCCu3M0mxKn2fFU/a4ETp cq8g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :content-language:in-reply-to:mime-version:user-agent:date :message-id:from:references:cc:to:subject:reply-to :arc-authentication-results; bh=QncFojneZRa8HX/pcW9CjeKe0cv81TsJuA4BIqUlRIo=; b=n1vcWY8UWEt4ymgtSPPlUCYkIr+NXLSGeOtVkvSsODgUNLdqztxJrs1pTw22yp2TU/ 3TlAOHUjJwMJAItcTSk31ZIcGV3sqa0nauu/H3MfBbvlWw5WBVLQDoyyV5ATCVDOk8AA fjNGhTVnjZx0IaQ9DR6ejGya9MK3QHALAfYCDk2PzqV2aYOxXjYqaJf6LSp/BNIVNc6L Rzrp+5bzyw13MahecCc9mVmCAo4f0Ph567qhZkt5Qarl44hZYjoxrxZCk5Lv3aih2DlB F9eYkXLb5dCex2ceymXc4R7B38GVTC+UroXMhoCV7NESEfL8vklaJqxNoLFy2FEL+3mr GvOw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w1-v6si3552599plk.597.2018.03.21.04.05.57; Wed, 21 Mar 2018 04:06:11 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751897AbeCULEU (ORCPT + 99 others); Wed, 21 Mar 2018 07:04:20 -0400 Received: from mail-lf0-f66.google.com ([209.85.215.66]:44707 "EHLO mail-lf0-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751737AbeCULEO (ORCPT ); Wed, 21 Mar 2018 07:04:14 -0400 Received: by mail-lf0-f66.google.com with SMTP id g203-v6so7174764lfg.11 for ; Wed, 21 Mar 2018 04:04:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:reply-to:subject:to:cc:references:from :message-id:date:user-agent:mime-version:in-reply-to :content-language:content-transfer-encoding; bh=QncFojneZRa8HX/pcW9CjeKe0cv81TsJuA4BIqUlRIo=; b=pbmPQ2vUNXWML/+kH0q1RKUr5QVCFIv8msXq6fU5KfqSvHkQotbY4x9dR+LOb2erNG Y/nhhRQehOOrT5OPnJgNDQ8WzK4BCVDQ4kyKSCVBc8O2j5kpGHDwxeqdTCeRY2RzumZN pWek0dEUl46PArKMdeU/tsLApbmIPaHHsOrxZP6zyeyk5wSl4cnf65UwlM+cCAOSSA7v 6ZopHgv9QD1o/iw8V5Nc4JgZB3LIhO4FvtTOts4ZKumoRJLXB55xgiWMk3u/vTrH4SEj qDQwIUdzQztUeDiimSZg3hkwtNaaFaFMFazOkcbbk5Zggq1i7U5XuZufcFYmhaVD3Tjs c5Ig== X-Gm-Message-State: AElRT7EBz1lgTyIhqjOyqVlre9ZkG1eN9HRUcf0jLNZJR93BHF4Gk3yT l5XMxFqGp3k3ynJ0UqY3xNk= X-Received: by 2002:a19:5317:: with SMTP id h23-v6mr11976731lfb.6.1521630252731; Wed, 21 Mar 2018 04:04:12 -0700 (PDT) Received: from [192.168.42.173] ([213.87.157.109]) by smtp.gmail.com with ESMTPSA id y15-v6sm971533lfj.33.2018.03.21.04.04.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Mar 2018 04:04:11 -0700 (PDT) Reply-To: alex.popov@linux.com Subject: Re: [PATCH RFC v9 2/7] x86/entry: Add STACKLEAK erasing the kernel stack at the end of syscalls To: Peter Zijlstra , Laura Abbott , Dave Hansen , Linus Torvalds , Kees Cook , Andy Lutomirski Cc: PaX Team , Brad Spengler , Ingo Molnar , Tycho Andersen , Mark Rutland , Ard Biesheuvel , Borislav Petkov , Richard Sandiford , Thomas Gleixner , "H . Peter Anvin" , "Dmitry V . Levin" , Emese Revfy , Jonathan Corbet , Andrey Ryabinin , "Kirill A . Shutemov" , Thomas Garnier , Andrew Morton , Alexei Starovoitov , Josef Bacik , Masami Hiramatsu , Nicholas Piggin , Al Viro , "David S . Miller" , Ding Tianhong , David Woodhouse , Josh Poimboeuf , Steven Rostedt , Dominik Brodowski , Juergen Gross , Greg Kroah-Hartman , Dan Williams , Mathias Krause , Vikas Shivappa , Kyle Huey , Dmitry Safonov , Will Deacon , Arnd Bergmann , x86@kernel.org, linux-kernel@vger.kernel.org, "kernel-hardening@lists.openwall.com" References: <1520107232-14111-1-git-send-email-alex.popov@linux.com> <1520107232-14111-3-git-send-email-alex.popov@linux.com> <94f268b2-31a4-620a-86ed-325d5bb33c57@redhat.com> <20180305202535.GX25201@hirez.programming.kicks-ass.net> From: Alexander Popov Message-ID: Date: Wed, 21 Mar 2018 14:04:07 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 In-Reply-To: <20180305202535.GX25201@hirez.programming.kicks-ass.net> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 05.03.2018 23:25, Peter Zijlstra wrote: > On Mon, Mar 05, 2018 at 11:43:19AM -0800, Laura Abbott wrote: >> On 03/05/2018 08:41 AM, Dave Hansen wrote: >>> On 03/03/2018 12:00 PM, Alexander Popov wrote: >>>> Documentation/x86/x86_64/mm.txt | 2 + >>>> arch/Kconfig | 27 ++++++++++ >>>> arch/x86/Kconfig | 1 + >>>> arch/x86/entry/entry_32.S | 88 +++++++++++++++++++++++++++++++ >>>> arch/x86/entry/entry_64.S | 108 +++++++++++++++++++++++++++++++++++++++ >>>> arch/x86/entry/entry_64_compat.S | 11 ++++ >>> >>> This is a *lot* of assembly. I wonder if you tried at all to get more >>> of this into C or whether you just inherited the assembly from the >>> original code? >>> >> >> This came up previously http://www.openwall.com/lists/kernel-hardening/2017/10/23/5 >> there were concerns about trusting C to do the right thing as well as >> speed. > > And therefore the answer to this obvious question should've been part of > the Changelog :-) > > Dave is last in a long line of people asking this same question. Hello! I've decided to share the details (and ask for advice) regardless of the destiny of this patch series. I've rewritten the assembly part in C, please see the code below. That is erase_kstack() function, which is called at the end of syscall just before returning to the userspace. The generated asm doesn't look nice (and might be somewhat slower), but I don't care now. The main obstacle: erase_kstack() must save and restore any modified registers, because it is called from the trampoline stack (introduced by Andy Lutomirski), when all registers except RDI are live. Laura had a similar issue with C code on ARM: http://www.openwall.com/lists/kernel-hardening/2017/10/10/3 I've solved that with no_caller_saved_registers attribute, which makes all registers callee-saved. But that attribute was introduced only in gcc-7. Does kernel have a solution for similar issues? Thanks! -------- >8 -------- #include #include #include #include #include /* This function must save and restore any modified registers */ __attribute__ ((no_caller_saved_registers)) asmlinkage void erase_kstack(void) { register unsigned long p = current->thread.lowest_stack; register unsigned long boundary = p & ~(THREAD_SIZE - 1); unsigned long poison = 0; unsigned long check_depth = STACKLEAK_POISON_CHECK_DEPTH / sizeof(unsigned long); /* * Two qwords at the bottom of the thread stack are reserved and * should not be poisoned (see CONFIG_SCHED_STACK_END_CHECK). */ boundary += 2 * sizeof(unsigned long); /* * Let's search for the poison value in the stack. * Start from the lowest_stack and go to the bottom. */ while (p >= boundary && poison <= check_depth) { if (*(unsigned long *)p == STACKLEAK_POISON) poison++; else poison = 0; p -= sizeof(unsigned long); } #ifdef CONFIG_STACKLEAK_METRICS current->thread.prev_lowest_stack = p; #endif /* * So let's write the poison value to the kernel stack. Start from * the address in p and move up till the new boundary. */ if (on_thread_stack()) boundary = current_stack_pointer; else boundary = current_top_of_stack(); BUG_ON(boundary - p >= THREAD_SIZE); while (p < boundary) { *(unsigned long *)p = STACKLEAK_POISON; p += sizeof(unsigned long); } /* Reset the lowest_stack value for the next syscall */ current->thread.lowest_stack = current_top_of_stack() - 256; }