From patchwork Sun Oct 22 00:22:52 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Popov X-Patchwork-Id: 10021521 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 BDF4E600CC for ; Sun, 22 Oct 2017 00:24:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A7E40286F1 for ; Sun, 22 Oct 2017 00:24:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9CAAF288F6; Sun, 22 Oct 2017 00:24:00 +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.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED 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 87DF1286F1 for ; Sun, 22 Oct 2017 00:23:59 +0000 (UTC) Received: (qmail 15574 invoked by uid 550); 22 Oct 2017 00:23:26 -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 15468 invoked from network); 22 Oct 2017 00:23:22 -0000 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=bWtEMeDnU54axbi5/3xBE9IK1P5QORQhkCYdXW2y+TE=; b=W4muDklZuUhtMM5cTv3Rp5jswfn8ewRAA8k1lro9Pycj2LE81tdo5vAQCrylMpf22W meVPdDqwqkJy9pjuBQZisvJC9ghvClZIAgKUHzbr7mxaSy9Ds8kBvdVRiIe/999LHh7Y R7qL9WZiBKdmFM6ZQgJD+JlXGpTvnVZMqRNFvPzLbvDsQfcSpijesTIRtjD5ghvAC3Ij 8uCI/vKocpuztjeDhrLKKYjH9tprHg4GedwL8Em+EjTtkTax5fT++30yuWne+Lcz3h7C uVwrRSUPkvn8v62GhMqHDqtOlxubFaVU7REZSPNm4F57NCuXYpgUMYh7hlgRxdfbJRSV 64Ow== X-Gm-Message-State: AMCzsaXh7vDWlTB9ncZiRx4uo3EjQxrcZNaqixASf56axzBNto5fATW8 gftvhx5wX50UcA+PkuKpoRc3S8Zd X-Google-Smtp-Source: ABhQp+TuQhroZOyYRedk8LV7qyF5Yqa7wffm7Ud1AbE2xmFmXOKarTprppyUActo5n+B5zTs9up8gw== X-Received: by 10.46.67.25 with SMTP id q25mr3568004lja.146.1508631791068; Sat, 21 Oct 2017 17:23:11 -0700 (PDT) From: Alexander Popov To: kernel-hardening@lists.openwall.com, keescook@chromium.org, pageexec@freemail.hu, spender@grsecurity.net, Ingo Molnar , Andy Lutomirski , tycho@docker.com, Laura Abbott , Mark Rutland , Ard Biesheuvel , Borislav Petkov , Thomas Gleixner , "H . Peter Anvin" , Peter Zijlstra , x86@kernel.org, alex.popov@linux.com Date: Sun, 22 Oct 2017 03:22:52 +0300 Message-Id: <1508631773-2502-5-git-send-email-alex.popov@linux.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1508631773-2502-1-git-send-email-alex.popov@linux.com> References: <1508631773-2502-1-git-send-email-alex.popov@linux.com> Subject: [kernel-hardening] [PATCH RFC v5 4/5] fs/proc: Show STACKLEAK metrics in the /proc file system X-Virus-Scanned: ClamAV using ClamSMTP Introduce CONFIG_STACKLEAK_METRICS providing STACKLEAK information about tasks via the /proc file system. In particular, /proc//lowest_stack shows the current lowest_stack value and its final value from the previous syscall. That information can be useful for estimating the STACKLEAK performance impact for different workloads. Signed-off-by: Alexander Popov --- arch/Kconfig | 11 +++++++++++ arch/x86/entry/entry_32.S | 4 ++++ arch/x86/entry/entry_64.S | 4 ++++ arch/x86/include/asm/processor.h | 3 +++ arch/x86/kernel/asm-offsets.c | 3 +++ arch/x86/kernel/process_32.c | 3 +++ arch/x86/kernel/process_64.c | 3 +++ fs/proc/base.c | 14 ++++++++++++++ 8 files changed, 45 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index f2de598..c48d828 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -555,6 +555,17 @@ config STACKLEAK_TRACK_MIN_SIZE frame size greater than or equal to this parameter. If unsure, leave the default value 100. +config STACKLEAK_METRICS + bool "Show STACKLEAK metrics in the /proc file system" + depends on GCC_PLUGIN_STACKLEAK + depends on PROC_FS + help + If this is set, STACKLEAK metrics for every task are available in + the /proc file system. In particular, /proc//lowest_stack + shows the current lowest_stack value and its final value from the + previous syscall. That information can be useful for estimating + the STACKLEAK performance impact for your workloads. + config HAVE_CC_STACKPROTECTOR bool help diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index a7b0c52..4f3f2ff 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -115,6 +115,10 @@ ENTRY(erase_kstack) mov %esp, %ecx sub %edi, %ecx +#ifdef CONFIG_STACKLEAK_METRICS + mov %edi, TASK_prev_lowest_stack(%ebp) +#endif + cmp $THREAD_SIZE_asm, %ecx jb 3f ud2 diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 189d843..fbf7f1c 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -116,6 +116,10 @@ ENTRY(erase_kstack) mov %esp, %ecx sub %edi, %ecx +#ifdef CONFIG_STACKLEAK_METRICS + mov %rdi, TASK_prev_lowest_stack(%r11) +#endif + /* Check that the counter value is sane. */ cmp $THREAD_SIZE_asm, %rcx jb 3f diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index c6eaf2d..8e3f2ef 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -479,6 +479,9 @@ struct thread_struct { #ifdef CONFIG_GCC_PLUGIN_STACKLEAK unsigned long lowest_stack; +# ifdef CONFIG_STACKLEAK_METRICS + unsigned long prev_lowest_stack; +# endif #endif unsigned int sig_on_uaccess_err:1; diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c index 4ed7451..673495d 100644 --- a/arch/x86/kernel/asm-offsets.c +++ b/arch/x86/kernel/asm-offsets.c @@ -40,6 +40,9 @@ void common(void) { #ifdef CONFIG_GCC_PLUGIN_STACKLEAK OFFSET(TASK_lowest_stack, task_struct, thread.lowest_stack); OFFSET(TASK_thread_sp0, task_struct, thread.sp0); +# ifdef CONFIG_STACKLEAK_METRICS + OFFSET(TASK_prev_lowest_stack, task_struct, thread.prev_lowest_stack); +# endif #endif BLANK(); diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index c7345d2..0e4fa3c 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -139,6 +139,9 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp, #ifdef CONFIG_GCC_PLUGIN_STACKLEAK p->thread.lowest_stack = (unsigned long)task_stack_page(p) + 2 * sizeof(unsigned long); +# ifdef CONFIG_STACKLEAK_METRICS + p->thread.prev_lowest_stack = p->thread.lowest_stack; +# endif #endif if (unlikely(p->flags & PF_KTHREAD)) { diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 65ba73f..50d019c 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -286,6 +286,9 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long sp, #ifdef CONFIG_GCC_PLUGIN_STACKLEAK p->thread.lowest_stack = (unsigned long)task_stack_page(p) + 2 * sizeof(unsigned long); +# ifdef CONFIG_STACKLEAK_METRICS + p->thread.prev_lowest_stack = p->thread.lowest_stack; +# endif #endif savesegment(gs, p->thread.gsindex); diff --git a/fs/proc/base.c b/fs/proc/base.c index ad3b076..7c3e127 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2884,6 +2884,17 @@ static int proc_pid_patch_state(struct seq_file *m, struct pid_namespace *ns, } #endif /* CONFIG_LIVEPATCH */ +#ifdef CONFIG_STACKLEAK_METRICS +static int proc_lowest_stack(struct seq_file *m, struct pid_namespace *ns, + struct pid *pid, struct task_struct *task) +{ + seq_printf(m, "prev_lowest_stack: %pK\nlowest_stack: %pK\n", + (void *)task->thread.prev_lowest_stack, + (void *)task->thread.lowest_stack); + return 0; +} +#endif /* CONFIG_STACKLEAK_METRICS */ + /* * Thread groups */ @@ -2988,6 +2999,9 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_LIVEPATCH ONE("patch_state", S_IRUSR, proc_pid_patch_state), #endif +#ifdef CONFIG_STACKLEAK_METRICS + ONE("lowest_stack", S_IRUGO, proc_lowest_stack), +#endif }; static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)