From patchwork Thu Jun 7 14:38:00 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yu-cheng Yu X-Patchwork-Id: 10452299 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 8AC1F60375 for ; Thu, 7 Jun 2018 14:41:47 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7AF24294F7 for ; Thu, 7 Jun 2018 14:41:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6F5F629508; Thu, 7 Jun 2018 14:41:47 +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=-2.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B658E294F7 for ; Thu, 7 Jun 2018 14:41:46 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id AC26B6B0283; Thu, 7 Jun 2018 10:41:33 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id 91E2A6B0285; Thu, 7 Jun 2018 10:41:33 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 7BF1C6B0286; Thu, 7 Jun 2018 10:41:33 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from mail-pf0-f200.google.com (mail-pf0-f200.google.com [209.85.192.200]) by kanga.kvack.org (Postfix) with ESMTP id 1F9E16B0283 for ; Thu, 7 Jun 2018 10:41:33 -0400 (EDT) Received: by mail-pf0-f200.google.com with SMTP id p16-v6so623266pfn.7 for ; Thu, 07 Jun 2018 07:41:33 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-original-authentication-results:x-gm-message-state:from:to:cc :subject:date:message-id:in-reply-to:references; bh=cvUokz4+g0U9RDNR/iyPTcSuh7Mw7z/5OXQ+YXlEqCM=; b=s9ri8WYMBTRDekJ4Q/VTwAms95Lw7Qb4XBD1zrOwkKE+4MQPl/Fgqvf+ZAl8NCfKp3 8ENs76oW5IPp/pSQ/Aiq4GLphlEY82WmqiHgD7+35AzGXtQnNGbev9N7QvpDNwZFrSh2 IZeBB+m8+TooDUvviZWjpH6Dv9Bi7T4GCnG8lXTXSoufyP3LguQVACBTkFry5UxyCx6r 28xKmiIxYOtJIf5RxR2AGbhqds3vxsBtN1m97ACVi8UUlHEKp4zVueqZI8bevoTKrDpE l2AsKNkfYHeBQ5x/EXQUQeoB2wumhpxKB1ozkoGFbv/CbB4BdilK5Dr5BG2dMvmOl+f0 qltw== X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of yu-cheng.yu@intel.com designates 192.55.52.43 as permitted sender) smtp.mailfrom=yu-cheng.yu@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com X-Gm-Message-State: APt69E13C3HgvWHcZU5ft1+XzThmB9AW1YyxWkSEBk12GK2gDprCPC5/ F49I/xNvk8Z9tdTvWHI46a8GoXorldsbBen7FkNtMTsWC8V9jmEhMnY3hImbcnPGqmYdA9qcHeN 6srnAtZD0MRSM2jPMcS01D3KT4fr7/cR3DU9aQFAySQT5Yt8PSQ879wq+QnmcgrHfsQ== X-Received: by 2002:a62:2281:: with SMTP id p1-v6mr2051259pfj.53.1528382492782; Thu, 07 Jun 2018 07:41:32 -0700 (PDT) X-Google-Smtp-Source: ADUXVKJg/apbbRgOqChGIpZv34STi55pLWgg+vZdgsCgBpWrvvTJk3p1X5N0DI5iLGfpHsIm+Xej X-Received: by 2002:a62:2281:: with SMTP id p1-v6mr2051169pfj.53.1528382491205; Thu, 07 Jun 2018 07:41:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1528382491; cv=none; d=google.com; s=arc-20160816; b=PTkg3dGTFZXLtRfWmf+qLa1RM2TAYXy4KmWda0ZIyZBmvgHPtJL5mTIJkpCJkNNfYJ IR/gDjTEVIikBKz4xuIqtiF9aA9l9ZDM2yfYSFk4ZdNpJW+qTdHN8mLA0gfcu9Kckt55 w996ehqufdwpIQly1/RAIBlVztGtzpPv8t+y4L10ecCGUQVwps6XVh1zuGemomAsBS4y t7oQJ33oI4HTaf6oVTUg7fwqm6qJ6Fb9zsR57/dDSbzzMYukJMUJhMZL/4Kfptrtn3Mv 287AXYZggKmahkc1mG3MpZVqGEvAKpcidsEnbi1FKJssKUiFZMBR2kRNSeP7HEGLR4WJ J8Dg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=cvUokz4+g0U9RDNR/iyPTcSuh7Mw7z/5OXQ+YXlEqCM=; b=psewN2kHZ5QtS/dDVkvopAbRdV1zoYBXHZoBY1tCVPoNmXq9KblgD1Lict4QQHK25y M9209vy+wg27iJwE78+0doWLwS9+iMQhVEvAKYWZSN04H+kRkbTnIPN9wsWdd8Xvn0rX O5A42gw8Z8XL6ycIU4AFqsundbaojyKp5+9edlK9k/ssC2rZk12SiUDgCn/qWyGQSx+T RV/UGwIXK8uc7mmuxaf0MmulThmsEM5x8joYl4cXCPXaoysziYc0mutXIaWx35fC0imh 1F3JPgfVxrbKe3aUpLq+YaAuWrpWRKbRu0zLm+cixydvbNyzgn9FkhgZto2P0MSTTYIh oC4Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of yu-cheng.yu@intel.com designates 192.55.52.43 as permitted sender) smtp.mailfrom=yu-cheng.yu@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: from mga05.intel.com (mga05.intel.com. [192.55.52.43]) by mx.google.com with ESMTPS id i74-v6si8716254pgc.188.2018.06.07.07.41.30 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 07 Jun 2018 07:41:31 -0700 (PDT) Received-SPF: pass (google.com: domain of yu-cheng.yu@intel.com designates 192.55.52.43 as permitted sender) client-ip=192.55.52.43; Authentication-Results: mx.google.com; spf=pass (google.com: domain of yu-cheng.yu@intel.com designates 192.55.52.43 as permitted sender) smtp.mailfrom=yu-cheng.yu@intel.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=intel.com X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga105.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Jun 2018 07:41:30 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.49,486,1520924400"; d="scan'208";a="62632625" Received: from 2b52.sc.intel.com ([143.183.136.51]) by orsmga001.jf.intel.com with ESMTP; 07 Jun 2018 07:41:30 -0700 From: Yu-cheng Yu To: linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, linux-arch@vger.kernel.org, x86@kernel.org, "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , "H.J. Lu" , Vedvyas Shanbhogue , "Ravi V. Shankar" , Dave Hansen , Andy Lutomirski , Jonathan Corbet , Oleg Nesterov , Arnd Bergmann , Mike Kravetz Cc: Yu-cheng Yu Subject: [PATCH 03/10] x86/cet: Signal handling for shadow stack Date: Thu, 7 Jun 2018 07:38:00 -0700 Message-Id: <20180607143807.3611-4-yu-cheng.yu@intel.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180607143807.3611-1-yu-cheng.yu@intel.com> References: <20180607143807.3611-1-yu-cheng.yu@intel.com> X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: X-Virus-Scanned: ClamAV using ClamSMTP Set and restore shadow stack pointer for signals. Signed-off-by: Yu-cheng Yu --- arch/x86/ia32/ia32_signal.c | 5 ++++ arch/x86/include/asm/cet.h | 7 +++++ arch/x86/include/uapi/asm/sigcontext.h | 4 +++ arch/x86/kernel/cet.c | 51 ++++++++++++++++++++++++++++++++++ arch/x86/kernel/signal.c | 11 ++++++++ 5 files changed, 78 insertions(+) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 86b1341cba9a..26a776baff7c 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -34,6 +34,7 @@ #include #include #include +#include /* * Do a signal return; undo the signal stack. @@ -74,6 +75,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, unsigned int tmpflags, err = 0; void __user *buf; u32 tmp; + u32 ssp; /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; @@ -104,9 +106,11 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, get_user_ex(tmp, &sc->fpstate); buf = compat_ptr(tmp); + get_user_ex(ssp, &sc->ssp); } get_user_catch(err); err |= fpu__restore_sig(buf, 1); + err |= cet_restore_signal((unsigned long)ssp); force_iret(); @@ -194,6 +198,7 @@ static int ia32_setup_sigcontext(struct sigcontext_32 __user *sc, put_user_ex(current->thread.trap_nr, &sc->trapno); put_user_ex(current->thread.error_code, &sc->err); put_user_ex(regs->ip, &sc->ip); + put_user_ex((u32)cet_get_shstk_ptr(), &sc->ssp); put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); put_user_ex(regs->flags, &sc->flags); put_user_ex(regs->sp, &sc->sp_at_signal); diff --git a/arch/x86/include/asm/cet.h b/arch/x86/include/asm/cet.h index 9d5bc1efc9b7..5507469cb803 100644 --- a/arch/x86/include/asm/cet.h +++ b/arch/x86/include/asm/cet.h @@ -17,14 +17,21 @@ struct cet_stat { #ifdef CONFIG_X86_INTEL_CET unsigned long cet_get_shstk_ptr(void); +int cet_push_shstk(int ia32, unsigned long ssp, unsigned long val); int cet_setup_shstk(void); void cet_disable_shstk(void); void cet_disable_free_shstk(struct task_struct *p); +int cet_restore_signal(unsigned long ssp); +int cet_setup_signal(int ia32, unsigned long addr); #else static inline unsigned long cet_get_shstk_ptr(void) { return 0; } +static inline int cet_push_shstk(int ia32, unsigned long ssp, + unsigned long val) { return 0; } static inline int cet_setup_shstk(void) { return 0; } static inline void cet_disable_shstk(void) {} static inline void cet_disable_free_shstk(struct task_struct *p) {} +static inline int cet_restore_signal(unsigned long ssp) { return 0; } +static inline int cet_setup_signal(int ia32, unsigned long addr) { return 0; } #endif #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/include/uapi/asm/sigcontext.h b/arch/x86/include/uapi/asm/sigcontext.h index 844d60eb1882..6c8997a0156a 100644 --- a/arch/x86/include/uapi/asm/sigcontext.h +++ b/arch/x86/include/uapi/asm/sigcontext.h @@ -230,6 +230,7 @@ struct sigcontext_32 { __u32 fpstate; /* Zero when no FPU/extended context */ __u32 oldmask; __u32 cr2; + __u32 ssp; }; /* @@ -262,6 +263,7 @@ struct sigcontext_64 { __u64 trapno; __u64 oldmask; __u64 cr2; + __u64 ssp; /* * fpstate is really (struct _fpstate *) or (struct _xstate *) @@ -320,6 +322,7 @@ struct sigcontext { struct _fpstate __user *fpstate; __u32 oldmask; __u32 cr2; + __u32 ssp; }; # else /* __x86_64__: */ struct sigcontext { @@ -377,6 +380,7 @@ struct sigcontext { __u64 trapno; __u64 oldmask; __u64 cr2; + __u64 ssp; struct _fpstate __user *fpstate; /* Zero when no FPU context */ # ifdef __ILP32__ __u32 __fpstate_pad; diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c index 8abbfd44322a..6f445ce94c83 100644 --- a/arch/x86/kernel/cet.c +++ b/arch/x86/kernel/cet.c @@ -17,6 +17,7 @@ #include #include #include +#include #define SHSTK_SIZE (0x8000 * (test_thread_flag(TIF_IA32) ? 4 : 8)) @@ -47,6 +48,24 @@ unsigned long cet_get_shstk_ptr(void) return ptr; } +int cet_push_shstk(int ia32, unsigned long ssp, unsigned long val) +{ + if (val >= TASK_SIZE) + return -EINVAL; + + if (IS_ENABLED(CONFIG_IA32_EMULATION) && ia32) { + if (!IS_ALIGNED(ssp, 4)) + return -EINVAL; + cet_set_shstk_ptr(ssp); + return write_user_shstk_32(ssp, (unsigned int)val); + } else { + if (!IS_ALIGNED(ssp, 8)) + return -EINVAL; + cet_set_shstk_ptr(ssp); + return write_user_shstk_64(ssp, val); + } +} + static unsigned long shstk_mmap(unsigned long addr, unsigned long len) { struct mm_struct *mm = current->mm; @@ -121,3 +140,35 @@ void cet_disable_free_shstk(struct task_struct *tsk) tsk->thread.cet.shstk_enabled = 0; } + +int cet_restore_signal(unsigned long ssp) +{ + if (!current->thread.cet.shstk_enabled) + return 0; + return cet_set_shstk_ptr(ssp); +} + +int cet_setup_signal(int ia32, unsigned long rstor_addr) +{ + unsigned long ssp; + struct cet_stat *cet = ¤t->thread.cet; + + if (!current->thread.cet.shstk_enabled) + return 0; + + ssp = cet_get_shstk_ptr(); + + /* + * Put the restorer address on the shstk + */ + if (ia32) + ssp -= sizeof(u32); + else + ssp -= sizeof(rstor_addr); + + if (ssp >= (cet->shstk_base + cet->shstk_size) || + ssp < cet->shstk_base) + return -EINVAL; + + return cet_push_shstk(ia32, ssp, rstor_addr); +} diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index da270b95fe4d..86fb897cae19 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -46,6 +46,7 @@ #include #include +#include #define COPY(x) do { \ get_user_ex(regs->x, &sc->x); \ @@ -102,6 +103,7 @@ static int restore_sigcontext(struct pt_regs *regs, void __user *buf; unsigned int tmpflags; unsigned int err = 0; + unsigned long ssp = 0; /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; @@ -148,9 +150,11 @@ static int restore_sigcontext(struct pt_regs *regs, get_user_ex(buf_val, &sc->fpstate); buf = (void __user *)buf_val; + get_user_ex(ssp, &sc->ssp); } get_user_catch(err); err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32)); + err |= cet_restore_signal(ssp); force_iret(); @@ -193,6 +197,7 @@ int setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate, put_user_ex(current->thread.trap_nr, &sc->trapno); put_user_ex(current->thread.error_code, &sc->err); put_user_ex(regs->ip, &sc->ip); + put_user_ex(cet_get_shstk_ptr(), &sc->ssp); #ifdef CONFIG_X86_32 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); put_user_ex(regs->flags, &sc->flags); @@ -742,6 +747,12 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) user_disable_single_step(current); failed = (setup_rt_frame(ksig, regs) < 0); + if (!failed) { + unsigned long rstor = (unsigned long)ksig->ka.sa.sa_restorer; + int ia32 = is_ia32_frame(ksig); + + failed = cet_setup_signal(ia32, rstor); + } if (!failed) { /* * Clear the direction flag as per the ABI for function entry.