From patchwork Tue Mar 16 06:52:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chang S. Bae" X-Patchwork-Id: 42571 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9AAA83854817; Tue, 16 Mar 2021 06:57:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9AAA83854817 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1615877845; bh=y7vBL3q2IaYMLfPMwWpZkbW8/7hWjWQa9p30aOFK+sY=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=ih46FqjFDxBFdJ3xXY0PB7oQNGr8AavlkikYaI581qeQi3IWN31MHeo6DCdH3PQBo HfQmjWb7Qcv2TF/+zPqFL1surcMvu0Xr0uN+eprCf6dhjNHuDAuPzeAbEGqld0wtmB ANmsxMOueKW9afh7F6bvdbhoe5WgLq4MgspYD/B8= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id 685163858D29 for ; Tue, 16 Mar 2021 06:57:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 685163858D29 IronPort-SDR: 2bDUJMW7jefVXeVHafUyuCYnW/05nd++KmjQfJItI+ajmu2OInM8AbuKAmed3gePYzByKhYsR1 KS+rUlXtp20g== X-IronPort-AV: E=McAfee;i="6000,8403,9924"; a="169126405" X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="169126405" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Mar 2021 23:57:12 -0700 IronPort-SDR: rOPDJOAsOFDbRcEfR+EqNuSZh1wdhYTg+KOn6YNhaZXTxqe24dCh82+XZ59vNByO6rEyvF+VN5 K60J2nycGLRQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="511296073" Received: from chang-linux-3.sc.intel.com ([172.25.66.175]) by fmsmga001.fm.intel.com with ESMTP; 15 Mar 2021 23:57:11 -0700 To: bp@suse.de, tglx@linutronix.de, mingo@kernel.org, luto@kernel.org, x86@kernel.org Subject: [PATCH v7 1/6] uapi: Define the aux vector AT_MINSIGSTKSZ Date: Mon, 15 Mar 2021 23:52:10 -0700 Message-Id: <20210316065215.23768-2-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210316065215.23768-1-chang.seok.bae@intel.com> References: <20210316065215.23768-1-chang.seok.bae@intel.com> X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Chang S. Bae via Libc-alpha" From: "Chang S. Bae" Reply-To: "Chang S. Bae" Cc: linux-arch@vger.kernel.org, len.brown@intel.com, tony.luck@intel.com, libc-alpha@sourceware.org, ravi.v.shankar@intel.com, chang.seok.bae@intel.com, jannh@google.com, linux-kernel@vger.kernel.org, dave.hansen@intel.com, linux-api@vger.kernel.org, Dave.Martin@arm.com, linux-arm-kernel@lists.infradead.org Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Define the AT_MINSIGSTKSZ in generic Linux. It is already used as generic ABI in glibc's generic elf.h, and this define will prevent future namespace conflicts. In particular, x86 is also using this generic definition. Signed-off-by: Chang S. Bae Reviewed-by: Len Brown Cc: Carlos O'Donell Cc: Dave Martin Cc: libc-alpha@sourceware.org Cc: linux-arch@vger.kernel.org Cc: linux-api@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org --- Change from v6: * Revised the comment. (Borislav Petkov) Change from v5: * Reverted the arm64 change. (Dave Martin and Will Deacon) * Massaged the changelog. Change from v4: * Added as a new patch (Carlos O'Donell) --- include/uapi/linux/auxvec.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/uapi/linux/auxvec.h b/include/uapi/linux/auxvec.h index abe5f2b6581b..c7e502bf5a6f 100644 --- a/include/uapi/linux/auxvec.h +++ b/include/uapi/linux/auxvec.h @@ -33,5 +33,8 @@ #define AT_EXECFN 31 /* filename of program */ +#ifndef AT_MINSIGSTKSZ +#define AT_MINSIGSTKSZ 51 /* minimal stack size for signal delivery */ +#endif #endif /* _UAPI_LINUX_AUXVEC_H */ From patchwork Tue Mar 16 06:52:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chang S. Bae" X-Patchwork-Id: 42566 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 491303854800; Tue, 16 Mar 2021 06:57:19 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 491303854800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1615877839; bh=f2qgqz3w7M0dde+TyIJkrzcBMMbq9T8NSO5Oz3fo62Y=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=WEIUEWly9nxF7kNe/1d4xDktxMtdTmDFe8hAkB8ufafgYUEw/I5IdFO5BghX0a2W2 q6l5hrUrI3nAwKb1uWE32G7I77rYx4SWFq6VnPMwzBDGEnYtKofpyt0Kt1pOaFhtdD RG+qLpSQ94behQpLIbQjCEsz+ah09rG3jPYPa4vM= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id EFDA83858C27 for ; Tue, 16 Mar 2021 06:57:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org EFDA83858C27 IronPort-SDR: gSm8d06HFkwsJ6nip52zBOkKlApxqEDeZWdcv9+vwKlAJBu6p7NIY8xbrpmamK5aJF2hNZxDY/ OtQzuJOqKxhQ== X-IronPort-AV: E=McAfee;i="6000,8403,9924"; a="169126406" X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="169126406" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Mar 2021 23:57:12 -0700 IronPort-SDR: QDtTWaXEVK1zPnbQp+ZWu+Ef+lmjTDBtdmzHTL47mYiwsZgqK14FK3x5r6av65DHb+404k1htU e1u63ExRGjag== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="511296076" Received: from chang-linux-3.sc.intel.com ([172.25.66.175]) by fmsmga001.fm.intel.com with ESMTP; 15 Mar 2021 23:57:11 -0700 To: bp@suse.de, tglx@linutronix.de, mingo@kernel.org, luto@kernel.org, x86@kernel.org Subject: [PATCH v7 2/6] x86/signal: Introduce helpers to get the maximum signal frame size Date: Mon, 15 Mar 2021 23:52:11 -0700 Message-Id: <20210316065215.23768-3-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210316065215.23768-1-chang.seok.bae@intel.com> References: <20210316065215.23768-1-chang.seok.bae@intel.com> X-Spam-Status: No, score=-10.5 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Chang S. Bae via Libc-alpha" From: "Chang S. Bae" Reply-To: "Chang S. Bae" Cc: linux-arch@vger.kernel.org, len.brown@intel.com, tony.luck@intel.com, libc-alpha@sourceware.org, ravi.v.shankar@intel.com, chang.seok.bae@intel.com, jannh@google.com, linux-kernel@vger.kernel.org, dave.hansen@intel.com, linux-api@vger.kernel.org, Dave.Martin@arm.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Signal frames do not have a fixed format and can vary in size when a number of things change: support XSAVE features, 32 vs. 64-bit apps. Add the code to support a runtime method for userspace to dynamically discover how large a signal stack needs to be. Introduce a new variable, max_frame_size, and helper functions for the calculation to be used in a new user interface. Set max_frame_size to a system-wide worst-case value, instead of storing multiple app-specific values. Signed-off-by: Chang S. Bae Reviewed-by: Len Brown Acked-by: H.J. Lu Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- Changes from v2: * Renamed the fpstate size helper with cleanup (Borislav Petkov) * Moved the sigframe struct size defines to where used (Borislav Petkov) * Removed unneeded sentence in the changelog (Borislav Petkov) Change from v1: * Took stack alignment into account for sigframe size (Dave Martin) --- arch/x86/include/asm/fpu/signal.h | 2 ++ arch/x86/include/asm/sigframe.h | 2 ++ arch/x86/kernel/cpu/common.c | 3 ++ arch/x86/kernel/fpu/signal.c | 19 +++++++++++ arch/x86/kernel/signal.c | 57 +++++++++++++++++++++++++++++-- 5 files changed, 81 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/fpu/signal.h b/arch/x86/include/asm/fpu/signal.h index 7fb516b6893a..8b6631dffefd 100644 --- a/arch/x86/include/asm/fpu/signal.h +++ b/arch/x86/include/asm/fpu/signal.h @@ -29,6 +29,8 @@ unsigned long fpu__alloc_mathframe(unsigned long sp, int ia32_frame, unsigned long *buf_fx, unsigned long *size); +unsigned long fpu__get_fpstate_size(void); + extern void fpu__init_prepare_fx_sw_frame(void); #endif /* _ASM_X86_FPU_SIGNAL_H */ diff --git a/arch/x86/include/asm/sigframe.h b/arch/x86/include/asm/sigframe.h index 84eab2724875..5b1ed650b124 100644 --- a/arch/x86/include/asm/sigframe.h +++ b/arch/x86/include/asm/sigframe.h @@ -85,4 +85,6 @@ struct rt_sigframe_x32 { #endif /* CONFIG_X86_64 */ +void __init init_sigframe_size(void); + #endif /* _ASM_X86_SIGFRAME_H */ diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index ab640abe26b6..c49ef3ad34dc 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -58,6 +58,7 @@ #include #include #include +#include #include "cpu.h" @@ -1334,6 +1335,8 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c) fpu__init_system(c); + init_sigframe_size(); + #ifdef CONFIG_X86_32 /* * Regardless of whether PCID is enumerated, the SDM says diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index a4ec65317a7f..dbb304e48f16 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -507,6 +507,25 @@ fpu__alloc_mathframe(unsigned long sp, int ia32_frame, return sp; } + +unsigned long fpu__get_fpstate_size(void) +{ + unsigned long ret = xstate_sigframe_size(); + + /* + * This space is needed on (most) 32-bit kernels, or when a 32-bit + * app is running on a 64-bit kernel. To keep things simple, just + * assume the worst case and always include space for 'freg_state', + * even for 64-bit apps on 64-bit kernels. This wastes a bit of + * space, but keeps the code simple. + */ + if ((IS_ENABLED(CONFIG_IA32_EMULATION) || + IS_ENABLED(CONFIG_X86_32)) && use_fxsr()) + ret += sizeof(struct fregs_state); + + return ret; +} + /* * Prepare the SW reserved portion of the fxsave memory layout, indicating * the presence of the extended state information in the memory layout diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index ea794a083c44..800243afd1ef 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -212,6 +212,11 @@ do { \ * Set up a signal frame. */ +/* x86 ABI requires 16-byte alignment */ +#define FRAME_ALIGNMENT 16UL + +#define MAX_FRAME_PADDING (FRAME_ALIGNMENT - 1) + /* * Determine which stack to use.. */ @@ -222,9 +227,9 @@ static unsigned long align_sigframe(unsigned long sp) * Align the stack pointer according to the i386 ABI, * i.e. so that on function entry ((sp + 4) & 15) == 0. */ - sp = ((sp + 4) & -16ul) - 4; + sp = ((sp + 4) & -FRAME_ALIGNMENT) - 4; #else /* !CONFIG_X86_32 */ - sp = round_down(sp, 16) - 8; + sp = round_down(sp, FRAME_ALIGNMENT) - 8; #endif return sp; } @@ -663,6 +668,54 @@ SYSCALL_DEFINE0(rt_sigreturn) return 0; } +/* + * There are four different struct types for signal frame: sigframe_ia32, + * rt_sigframe_ia32, rt_sigframe_x32, and rt_sigframe. Use the worst case + * -- the largest size. It means the size for 64-bit apps is a bit more + * than needed, but this keeps the code simple. + */ +#if defined(CONFIG_X86_32) || defined(CONFIG_IA32_EMULATION) +# define MAX_FRAME_SIGINFO_UCTXT_SIZE sizeof(struct sigframe_ia32) +#else +# define MAX_FRAME_SIGINFO_UCTXT_SIZE sizeof(struct rt_sigframe) +#endif + +/* + * The FP state frame contains an XSAVE buffer which must be 64-byte aligned. + * If a signal frame starts at an unaligned address, extra space is required. + * This is the max alignment padding, conservatively. + */ +#define MAX_XSAVE_PADDING 63UL + +/* + * The frame data is composed of the following areas and laid out as: + * + * ------------------------- + * | alignment padding | + * ------------------------- + * | (f)xsave frame | + * ------------------------- + * | fsave header | + * ------------------------- + * | alignment padding | + * ------------------------- + * | siginfo + ucontext | + * ------------------------- + */ + +/* max_frame_size tells userspace the worst case signal stack size. */ +static unsigned long __ro_after_init max_frame_size; + +void __init init_sigframe_size(void) +{ + max_frame_size = MAX_FRAME_SIGINFO_UCTXT_SIZE + MAX_FRAME_PADDING; + + max_frame_size += fpu__get_fpstate_size() + MAX_XSAVE_PADDING; + + /* Userspace expects an aligned size. */ + max_frame_size = round_up(max_frame_size, FRAME_ALIGNMENT); +} + static inline int is_ia32_compat_frame(struct ksignal *ksig) { return IS_ENABLED(CONFIG_IA32_EMULATION) && From patchwork Tue Mar 16 06:52:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chang S. Bae" X-Patchwork-Id: 42568 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E88B13858C27; Tue, 16 Mar 2021 06:57:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E88B13858C27 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1615877842; bh=swF7UxzrsU+r6l5vyJDJrPQdX3OlcyA/KaPTANDdMfQ=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=X/uAEDKb/CzOryWCaAGQsS5F7PynfAFfjuhXLRRd+aME+zzB3WMaIeJHR6Dyc9hgx isV/TJiQmvAmGn9bNHqwcJIpKaTv4nHR57A/4naH5jwscPR1kK7KZG2i6iKddYuRtJ mQyu29/GWzWYYZkKAqS8rqVCiHGBDUcJvrSzA26k= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id 037FF3858C27 for ; Tue, 16 Mar 2021 06:57:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 037FF3858C27 IronPort-SDR: OqwwC8OJzw1pKfjhJhJSrsVVpJoN5Uwmxq7WH671njicqKPVIk7lrSMTT0AvaGmGtxIN+WaHvI FFIxU7ug9XbA== X-IronPort-AV: E=McAfee;i="6000,8403,9924"; a="169126407" X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="169126407" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Mar 2021 23:57:12 -0700 IronPort-SDR: NMYTvEyo2WZGBs1Dhzw2mzP54vYgwD0jU53YJqgcDdT38OtUnisYx4tBq1s8tYr/oe/VNS7hYW Jjjk4xXot8xA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="511296080" Received: from chang-linux-3.sc.intel.com ([172.25.66.175]) by fmsmga001.fm.intel.com with ESMTP; 15 Mar 2021 23:57:11 -0700 To: bp@suse.de, tglx@linutronix.de, mingo@kernel.org, luto@kernel.org, x86@kernel.org Subject: [PATCH v7 3/6] x86/elf: Support a new ELF aux vector AT_MINSIGSTKSZ Date: Mon, 15 Mar 2021 23:52:12 -0700 Message-Id: <20210316065215.23768-4-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210316065215.23768-1-chang.seok.bae@intel.com> References: <20210316065215.23768-1-chang.seok.bae@intel.com> X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Chang S. Bae via Libc-alpha" From: "Chang S. Bae" Reply-To: "Chang S. Bae" Cc: linux-arch@vger.kernel.org, len.brown@intel.com, tony.luck@intel.com, libc-alpha@sourceware.org, ravi.v.shankar@intel.com, chang.seok.bae@intel.com, jannh@google.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, Fenghua Yu , dave.hansen@intel.com, linux-api@vger.kernel.org, Dave.Martin@arm.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Historically, signal.h defines MINSIGSTKSZ (2KB) and SIGSTKSZ (8KB), for use by all architectures with sigaltstack(2). Over time, the hardware state size grew, but these constants did not evolve. Today, literal use of these constants on several architectures may result in signal stack overflow, and thus user data corruption. A few years ago, the ARM team addressed this issue by establishing getauxval(AT_MINSIGSTKSZ). This enables the kernel to supply at runtime value that is an appropriate replacement on the current and future hardware. Add getauxval(AT_MINSIGSTKSZ) support to x86, analogous to the support added for ARM in commit 94b07c1f8c39 ("arm64: signal: Report signal frame size to userspace via auxv"). Also, include a documentation to describe x86-specific auxiliary vectors. Reported-by: Florian Weimer Fixes: c2bc11f10a39 ("x86, AVX-512: Enable AVX-512 States Context Switch") Signed-off-by: Chang S. Bae Reviewed-by: Len Brown Cc: H.J. Lu Cc: Fenghua Yu Cc: Dave Martin Cc: Michael Ellerman Cc: x86@kernel.org Cc: libc-alpha@sourceware.org Cc: linux-arch@vger.kernel.org Cc: linux-api@vger.kernel.org Cc: linux-doc@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=153531 --- Changes from v6: * Revised the documentation and fixed the build issue. (Borislav Petkov) * Fixed the vertical alignment of '\'. (Borislav Petkov) Changes from v5: * Added a documentation. --- Documentation/x86/elf_auxvec.rst | 53 ++++++++++++++++++++++++++++++ Documentation/x86/index.rst | 1 + arch/x86/include/asm/elf.h | 4 +++ arch/x86/include/uapi/asm/auxvec.h | 4 +-- arch/x86/kernel/signal.c | 5 +++ 5 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 Documentation/x86/elf_auxvec.rst diff --git a/Documentation/x86/elf_auxvec.rst b/Documentation/x86/elf_auxvec.rst new file mode 100644 index 000000000000..6c75b26f5efb --- /dev/null +++ b/Documentation/x86/elf_auxvec.rst @@ -0,0 +1,53 @@ +.. SPDX-License-Identifier: GPL-2.0 + +================================== +x86-specific ELF Auxiliary Vectors +================================== + +This document describes the semantics of the x86 auxiliary vectors. + +Introduction +============ + +ELF Auxiliary vectors enable the kernel to efficiently provide +configuration specific parameters to userspace. In this example, a program +allocates an alternate stack based on the kernel-provided size:: + + #include + #include + #include + #include + #include + #include + + #ifndef AT_MINSIGSTKSZ + #define AT_MINSIGSTKSZ 51 + #endif + + .... + stack_t ss; + + ss.ss_sp = malloc(ss.ss_size); + assert(ss.ss_sp); + + ss.ss_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ; + ss.ss_flags = 0; + + if (sigaltstack(&ss, NULL)) + err(1, "sigaltstack"); + + +The exposed auxiliary vectors +============================= + +AT_SYSINFO is used for locating the vsyscall entry point. It is not +exported on 64-bit mode. + +AT_SYSINFO_EHDR is the start address of the page containing the vDSO. + +AT_MINSIGSTKSZ denotes the minimum stack size required by the kernel to +deliver a signal to user-space. AT_MINSIGSTKSZ comprehends the space +consumed by the kernel to accommodate the user context for the current +hardware configuration. It does not comprehend subsequent user-space stack +consumption, which must be added by the user. (e.g. Above, user-space adds +SIGSTKSZ to AT_MINSIGSTKSZ.) diff --git a/Documentation/x86/index.rst b/Documentation/x86/index.rst index 4693e192b447..d58614d5cde6 100644 --- a/Documentation/x86/index.rst +++ b/Documentation/x86/index.rst @@ -35,3 +35,4 @@ x86-specific Documentation sva sgx features + elf_auxvec diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index 9224d40cdefe..18d9b1117871 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -312,6 +312,7 @@ do { \ NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \ } \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \ } while (0) /* @@ -328,6 +329,7 @@ extern unsigned long task_size_32bit(void); extern unsigned long task_size_64bit(int full_addr_space); extern unsigned long get_mmap_base(int is_legacy); extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len); +extern unsigned long get_sigframe_size(void); #ifdef CONFIG_X86_32 @@ -349,6 +351,7 @@ do { \ if (vdso64_enabled) \ NEW_AUX_ENT(AT_SYSINFO_EHDR, \ (unsigned long __force)current->mm->context.vdso); \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \ } while (0) /* As a historical oddity, the x32 and x86_64 vDSOs are controlled together. */ @@ -357,6 +360,7 @@ do { \ if (vdso64_enabled) \ NEW_AUX_ENT(AT_SYSINFO_EHDR, \ (unsigned long __force)current->mm->context.vdso); \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \ } while (0) #define AT_SYSINFO 32 diff --git a/arch/x86/include/uapi/asm/auxvec.h b/arch/x86/include/uapi/asm/auxvec.h index 580e3c567046..6beb55bbefa4 100644 --- a/arch/x86/include/uapi/asm/auxvec.h +++ b/arch/x86/include/uapi/asm/auxvec.h @@ -12,9 +12,9 @@ /* entries in ARCH_DLINFO: */ #if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64) -# define AT_VECTOR_SIZE_ARCH 2 +# define AT_VECTOR_SIZE_ARCH 3 #else /* else it's non-compat x86-64 */ -# define AT_VECTOR_SIZE_ARCH 1 +# define AT_VECTOR_SIZE_ARCH 2 #endif #endif /* _ASM_X86_AUXVEC_H */ diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 800243afd1ef..0d24f64d0145 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -716,6 +716,11 @@ void __init init_sigframe_size(void) max_frame_size = round_up(max_frame_size, FRAME_ALIGNMENT); } +unsigned long get_sigframe_size(void) +{ + return max_frame_size; +} + static inline int is_ia32_compat_frame(struct ksignal *ksig) { return IS_ENABLED(CONFIG_IA32_EMULATION) && From patchwork Tue Mar 16 06:52:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chang S. Bae" X-Patchwork-Id: 42567 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5DB52385480F; Tue, 16 Mar 2021 06:57:21 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5DB52385480F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1615877841; bh=qfOUSaphwpiKELwI0/N/Q1BCB0woSgqt62FPK8beF5c=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=sNzgyFKC4AjDl0yBY7GiddsPgnPdqi9HDu7qNHt5/aMmui4LjVM1ODj50KDIYdOBH c9HtQeuuAknVqBhoAU+leLt5VL3K3U+IPeIKWSbtfIstOsg+aVryNN60sZCOpDooIT Q84klIZGDT0dQzrsAbMHz4ix+KzToaAAKusEm+jc= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id 8F769385BF99 for ; Tue, 16 Mar 2021 06:57:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8F769385BF99 IronPort-SDR: JrUE2If4ycBuQaMlVVEYhGLoi0MD+SkkPK/35bcSxiyD95Ibt/kxZxqR7T8KabkCZ+Juni3mcM b3a5FZysHKQQ== X-IronPort-AV: E=McAfee;i="6000,8403,9924"; a="169126408" X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="169126408" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Mar 2021 23:57:12 -0700 IronPort-SDR: EYIjEIIZkRC/ss4huiFmKexYFxB4fMZXc9S0tqodZ12MaAth+8Idhqi+j7dONcWReiat8kLdfW 20KL9SmixRnQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="511296083" Received: from chang-linux-3.sc.intel.com ([172.25.66.175]) by fmsmga001.fm.intel.com with ESMTP; 15 Mar 2021 23:57:12 -0700 To: bp@suse.de, tglx@linutronix.de, mingo@kernel.org, luto@kernel.org, x86@kernel.org Subject: [PATCH v7 4/6] selftest/sigaltstack: Use the AT_MINSIGSTKSZ aux vector if available Date: Mon, 15 Mar 2021 23:52:13 -0700 Message-Id: <20210316065215.23768-5-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210316065215.23768-1-chang.seok.bae@intel.com> References: <20210316065215.23768-1-chang.seok.bae@intel.com> X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Chang S. Bae via Libc-alpha" From: "Chang S. Bae" Reply-To: "Chang S. Bae" Cc: linux-arch@vger.kernel.org, len.brown@intel.com, tony.luck@intel.com, libc-alpha@sourceware.org, ravi.v.shankar@intel.com, chang.seok.bae@intel.com, jannh@google.com, linux-kernel@vger.kernel.org, dave.hansen@intel.com, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, Dave.Martin@arm.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" The SIGSTKSZ constant may not represent enough stack size in some architectures as the hardware state size grows. Use getauxval(AT_MINSIGSTKSZ) to increase the stack size. Signed-off-by: Chang S. Bae Reviewed-by: Len Brown Cc: linux-kselftest@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- Changes from v5: * Added as a new patch. --- tools/testing/selftests/sigaltstack/sas.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/sigaltstack/sas.c b/tools/testing/selftests/sigaltstack/sas.c index 8934a3766d20..c53b070755b6 100644 --- a/tools/testing/selftests/sigaltstack/sas.c +++ b/tools/testing/selftests/sigaltstack/sas.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "../kselftest.h" @@ -24,6 +25,11 @@ #define SS_AUTODISARM (1U << 31) #endif +#ifndef AT_MINSIGSTKSZ +#define AT_MINSIGSTKSZ 51 +#endif + +static unsigned int stack_size; static void *sstack, *ustack; static ucontext_t uc, sc; static const char *msg = "[OK]\tStack preserved"; @@ -47,7 +53,7 @@ void my_usr1(int sig, siginfo_t *si, void *u) #endif if (sp < (unsigned long)sstack || - sp >= (unsigned long)sstack + SIGSTKSZ) { + sp >= (unsigned long)sstack + stack_size) { ksft_exit_fail_msg("SP is not on sigaltstack\n"); } /* put some data on stack. other sighandler will try to overwrite it */ @@ -108,6 +114,10 @@ int main(void) stack_t stk; int err; + /* Make sure more than the required minimum. */ + stack_size = getauxval(AT_MINSIGSTKSZ) + SIGSTKSZ; + ksft_print_msg("[NOTE]\tthe stack size is %lu\n", stack_size); + ksft_print_header(); ksft_set_plan(3); @@ -117,7 +127,7 @@ int main(void) sigaction(SIGUSR1, &act, NULL); act.sa_sigaction = my_usr2; sigaction(SIGUSR2, &act, NULL); - sstack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, + sstack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); if (sstack == MAP_FAILED) { ksft_exit_fail_msg("mmap() - %s\n", strerror(errno)); @@ -139,7 +149,7 @@ int main(void) } stk.ss_sp = sstack; - stk.ss_size = SIGSTKSZ; + stk.ss_size = stack_size; stk.ss_flags = SS_ONSTACK | SS_AUTODISARM; err = sigaltstack(&stk, NULL); if (err) { @@ -161,7 +171,7 @@ int main(void) } } - ustack = mmap(NULL, SIGSTKSZ, PROT_READ | PROT_WRITE, + ustack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); if (ustack == MAP_FAILED) { ksft_exit_fail_msg("mmap() - %s\n", strerror(errno)); @@ -170,7 +180,7 @@ int main(void) getcontext(&uc); uc.uc_link = NULL; uc.uc_stack.ss_sp = ustack; - uc.uc_stack.ss_size = SIGSTKSZ; + uc.uc_stack.ss_size = stack_size; makecontext(&uc, switch_fn, 0); raise(SIGUSR1); From patchwork Tue Mar 16 06:52:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chang S. Bae" X-Patchwork-Id: 42569 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 811AF385481A; Tue, 16 Mar 2021 06:57:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 811AF385481A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1615877843; bh=DnweHu7lZvAHD3pL3n7cL1QPNQD0UZAUcVkO4W5jzT4=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=WMr7/OUp1PO1KJBDp6hS+HKhr6r5HRpyRYWsW9EmiKsbthgp99/9adH7uNAZkUfzu 2sh+7WMHcCom/5r2iNYN/6mZDhYqgSgGk3YYgFKFbNMOjGJ6nAHbT5CmuL0TgUT9XB GVg5VZcmMHRjISf62UYokdD9x/PKsVk2toxEgCcU= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id 483FF385BF99 for ; Tue, 16 Mar 2021 06:57:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 483FF385BF99 IronPort-SDR: radqvbw8OJQY4RJD6ZWAlLoa3vE/DO86UVgE/57T/qrp2W5SOe8l+Z0qa4bdstSeKx4iz2G4c4 4BrRBs2H+wOQ== X-IronPort-AV: E=McAfee;i="6000,8403,9924"; a="169126409" X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="169126409" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Mar 2021 23:57:12 -0700 IronPort-SDR: NaWqtLNwjoxz1cY7Ox75cbdrrOG+hk9XyQPDsHE5yNF2A4zKN/T9br7P9Zt0SeASMrJCAAyT2F JcJ6ZcB9cqoA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="511296086" Received: from chang-linux-3.sc.intel.com ([172.25.66.175]) by fmsmga001.fm.intel.com with ESMTP; 15 Mar 2021 23:57:12 -0700 To: bp@suse.de, tglx@linutronix.de, mingo@kernel.org, luto@kernel.org, x86@kernel.org Subject: [PATCH v7 5/6] x86/signal: Detect and prevent an alternate signal stack overflow Date: Mon, 15 Mar 2021 23:52:14 -0700 Message-Id: <20210316065215.23768-6-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210316065215.23768-1-chang.seok.bae@intel.com> References: <20210316065215.23768-1-chang.seok.bae@intel.com> X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Chang S. Bae via Libc-alpha" From: "Chang S. Bae" Reply-To: "Chang S. Bae" Cc: linux-arch@vger.kernel.org, len.brown@intel.com, tony.luck@intel.com, libc-alpha@sourceware.org, ravi.v.shankar@intel.com, chang.seok.bae@intel.com, jannh@google.com, linux-kernel@vger.kernel.org, dave.hansen@intel.com, linux-api@vger.kernel.org, Dave.Martin@arm.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" The kernel pushes context on to the userspace stack to prepare for the user's signal handler. When the user has supplied an alternate signal stack, via sigaltstack(2), it is easy for the kernel to verify that the stack size is sufficient for the current hardware context. Check if writing the hardware context to the alternate stack will exceed it's size. If yes, then instead of corrupting user-data and proceeding with the original signal handler, an immediate SIGSEGV signal is delivered. Instead of calling on_sig_stack(), directly check the new stack pointer whether in the bounds. While the kernel allows new source code to discover and use a sufficient alternate signal stack size, this check is still necessary to protect binaries with insufficient alternate signal stack size from data corruption. Suggested-by: Jann Horn Signed-off-by: Chang S. Bae Reviewed-by: Len Brown Reviewed-by: Jann Horn Cc: Andy Lutomirski Cc: Jann Horn Cc: x86@kernel.org Cc: linux-kernel@vger.kernel.org --- Changes from v5: * Fixed the overflow check. (Andy Lutomirski) * Updated the changelog. Changes from v3: * Updated the changelog (Borislav Petkov) Changes from v2: * Simplified the implementation (Jann Horn) --- arch/x86/kernel/signal.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 0d24f64d0145..9a62604fbf63 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -242,7 +242,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, unsigned long math_size = 0; unsigned long sp = regs->sp; unsigned long buf_fx = 0; - int onsigstack = on_sig_stack(sp); + bool onsigstack = on_sig_stack(sp); int ret; /* redzone */ @@ -251,8 +251,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (sas_ss_flags(sp) == 0) + if (sas_ss_flags(sp) == 0) { sp = current->sas_ss_sp + current->sas_ss_size; + /* On the alternate signal stack */ + onsigstack = true; + } } else if (IS_ENABLED(CONFIG_X86_32) && !onsigstack && regs->ss != __USER_DS && @@ -272,7 +275,8 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, * If we are on the alternate signal stack and would overflow it, don't. * Return an always-bogus address instead so we will die with SIGSEGV. */ - if (onsigstack && !likely(on_sig_stack(sp))) + if (onsigstack && unlikely(sp <= current->sas_ss_sp || + sp - current->sas_ss_sp > current->sas_ss_size)) return (void __user *)-1L; /* save i387 and extended state */ From patchwork Tue Mar 16 06:52:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Chang S. Bae" X-Patchwork-Id: 42570 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1743E385482C; Tue, 16 Mar 2021 06:57:24 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1743E385482C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1615877844; bh=KhiLzjwgnVz8j0QoDQtHcjbgjFu2k7T2BME9BRdS8S4=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=snjjT18FdxZWKtzOfvqj7qNsK+eTRqhJESlILC1lUoecMKov8BQVk5BsG2qbzQBXJ s1wZWwDh89atkIxuVDHaXkFJ97rYdRNakEvujoLtIaoBYAN09rCjQxH5E7fFwjEwRn oCe5ryG3ZbbKT0koUyrNtf2r6/pP5aGHeavPoCNQ= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mga17.intel.com (mga17.intel.com [192.55.52.151]) by sourceware.org (Postfix) with ESMTPS id 579F13858C27 for ; Tue, 16 Mar 2021 06:57:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 579F13858C27 IronPort-SDR: dFg3F6TVbppWAf3TMbpf2A1usgQMEi66H/iATSzeRhbQSL5VNOtssYF2H2YxmUC40ohg7m3kAU HRgdH9EHiK1Q== X-IronPort-AV: E=McAfee;i="6000,8403,9924"; a="169126410" X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="169126410" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Mar 2021 23:57:12 -0700 IronPort-SDR: Vb+RlfAxgnOJKXH1GrA4XtO0/DdzBF7w1NUXhEXYGZn8sdiTs9AcQycHbGoltm1IVefpupyg8U CytpmuGo5J0g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="511296089" Received: from chang-linux-3.sc.intel.com ([172.25.66.175]) by fmsmga001.fm.intel.com with ESMTP; 15 Mar 2021 23:57:12 -0700 To: bp@suse.de, tglx@linutronix.de, mingo@kernel.org, luto@kernel.org, x86@kernel.org Subject: [PATCH v7 6/6] selftest/x86/signal: Include test cases for validating sigaltstack Date: Mon, 15 Mar 2021 23:52:15 -0700 Message-Id: <20210316065215.23768-7-chang.seok.bae@intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210316065215.23768-1-chang.seok.bae@intel.com> References: <20210316065215.23768-1-chang.seok.bae@intel.com> X-Spam-Status: No, score=-11.1 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: "Chang S. Bae via Libc-alpha" From: "Chang S. Bae" Reply-To: "Chang S. Bae" Cc: linux-arch@vger.kernel.org, len.brown@intel.com, tony.luck@intel.com, libc-alpha@sourceware.org, ravi.v.shankar@intel.com, chang.seok.bae@intel.com, jannh@google.com, linux-kernel@vger.kernel.org, dave.hansen@intel.com, linux-kselftest@vger.kernel.org, linux-api@vger.kernel.org, Dave.Martin@arm.com Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" The test measures the kernel's signal delivery with different (enough vs. insufficient) stack sizes. Signed-off-by: Chang S. Bae Reviewed-by: Len Brown Cc: x86@kernel.org Cc: linux-kselftest@vger.kernel.org Cc: linux-kernel@vger.kernel.org --- Changes from v3: * Revised test messages again (Borislav Petkov) Changes from v2: * Revised test messages (Borislav Petkov) --- tools/testing/selftests/x86/Makefile | 2 +- tools/testing/selftests/x86/sigaltstack.c | 128 ++++++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/x86/sigaltstack.c diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index 333980375bc7..65bba2ae86ee 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile @@ -13,7 +13,7 @@ CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh $(CC) trivial_program.c -no-pie) TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt test_mremap_vdso \ check_initial_reg_state sigreturn iopl ioperm \ test_vsyscall mov_ss_trap \ - syscall_arg_fault fsgsbase_restore + syscall_arg_fault fsgsbase_restore sigaltstack TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \ test_FCMOV test_FCOMI test_FISTTP \ vdso_restorer diff --git a/tools/testing/selftests/x86/sigaltstack.c b/tools/testing/selftests/x86/sigaltstack.c new file mode 100644 index 000000000000..f689af75e979 --- /dev/null +++ b/tools/testing/selftests/x86/sigaltstack.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* sigaltstack()-enforced minimum stack */ +#define ENFORCED_MINSIGSTKSZ 2048 + +#ifndef AT_MINSIGSTKSZ +# define AT_MINSIGSTKSZ 51 +#endif + +static int nerrs; + +static bool sigalrm_expected; + +static unsigned long at_minstack_size; + +static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), + int flags) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO | flags; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + +static void clearhandler(int sig) +{ + struct sigaction sa; + + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + +static int setup_altstack(void *start, unsigned long size) +{ + stack_t ss; + + memset(&ss, 0, sizeof(ss)); + ss.ss_size = size; + ss.ss_sp = start; + + return sigaltstack(&ss, NULL); +} + +static jmp_buf jmpbuf; + +static void sigsegv(int sig, siginfo_t *info, void *ctx_void) +{ + if (sigalrm_expected) { + printf("[FAIL]\tWrong signal delivered: SIGSEGV (expected SIGALRM)."); + nerrs++; + } else { + printf("[OK]\tSIGSEGV signal delivered.\n"); + } + + siglongjmp(jmpbuf, 1); +} + +static void sigalrm(int sig, siginfo_t *info, void *ctx_void) +{ + if (!sigalrm_expected) { + printf("[FAIL]\tWrong signal delivered: SIGALRM (expected SIGSEGV)."); + nerrs++; + } else { + printf("[OK]\tSIGALRM signal delivered.\n"); + } +} + +static void test_sigaltstack(void *altstack, unsigned long size) +{ + if (setup_altstack(altstack, size)) + err(1, "sigaltstack()"); + + sigalrm_expected = (size > at_minstack_size) ? true : false; + + sethandler(SIGSEGV, sigsegv, 0); + sethandler(SIGALRM, sigalrm, SA_ONSTACK); + + if (!sigsetjmp(jmpbuf, 1)) { + printf("[RUN]\tTest an alternate signal stack of %ssufficient size.\n", + sigalrm_expected ? "" : "in"); + printf("\tRaise SIGALRM. %s is expected to be delivered.\n", + sigalrm_expected ? "It" : "SIGSEGV"); + raise(SIGALRM); + } + + clearhandler(SIGALRM); + clearhandler(SIGSEGV); +} + +int main(void) +{ + void *altstack; + + at_minstack_size = getauxval(AT_MINSIGSTKSZ); + + altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0); + if (altstack == MAP_FAILED) + err(1, "mmap()"); + + if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size) + test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1); + + test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ); + + return nerrs == 0 ? 0 : 1; +}