Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp4119164pxf; Tue, 16 Mar 2021 06:18:18 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzhxAuqnMAhApMqXErMxXCPEDz8rT47ofhJBIqjawSLoo8IpauCLtoWjZxKrfCaHn487SJa X-Received: by 2002:a17:906:8a65:: with SMTP id hy5mr30267784ejc.250.1615900698175; Tue, 16 Mar 2021 06:18:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1615900698; cv=none; d=google.com; s=arc-20160816; b=zjBvRXFMarU1bRllBmJkvbNoUx/OopZRL0aIk230GSAVT9TolchSXjYL6Mv4upCNAy APfQx//emSCtu6aCAb3N3qiqFfBhM1igdjr6kMlVwQuwp8cZUh2dYfsxpSdBwPjKSQRG t3lOSS/td96w0HdFKwZwppF6ajUmURKrd45M4Dehs2FRrU8LaWelpDK2UX2xjT1YU2Iy GhW14OMMF22CsNybVFU04OTBGcFYWRThBRJHeF7attYW1cO3eRuHUEeCEXyGZhpliuFQ gQAVX1jz3qwa6rw0OQnkywxjLs2v3Ccb9p95rILwMskDqck8eiXjS0lUH5ZnILqpCbAJ LWcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from:ironport-sdr:ironport-sdr; bh=DnweHu7lZvAHD3pL3n7cL1QPNQD0UZAUcVkO4W5jzT4=; b=RAadEvtiU7n0XYXDMnKjiOyqbtHOwsAuz2paA9jv6hkiptEwjLKGLOwWJ+xeWOKlck GSLGnxOr7ceC6jgosQcKfaeAj66Xi4nfVyIL9ttFSz/kzmVC77jL8IeIv85JxpfvBnuS XJQjvOtyvsT9Kg+fIV40eQ/v9aQUTmf8cZ8szH68dg5qvdsLrTnzXpADIaEXav84dFOG LA/Xlts8l6Wp8ys6/6bQXR3XKxGqeRLYi1s7T4lqFFtTQ6yaz8K8s47PmJNEpqHeWcUq 2WRLpcB0LoPaxSGm3CwOV4l3F+5YW/5arbNqG98gpRRbTKPw5AM2JQBXe9iBRVEZ49VF em7Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id l1si14317146ejh.597.2021.03.16.06.17.55; Tue, 16 Mar 2021 06:18:18 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235820AbhCPG5x (ORCPT + 99 others); Tue, 16 Mar 2021 02:57:53 -0400 Received: from mga03.intel.com ([134.134.136.65]:31159 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233790AbhCPG5N (ORCPT ); Tue, 16 Mar 2021 02:57:13 -0400 IronPort-SDR: Dq0y7RTLxeF2B/Ed0CXgq+68qXxh0HXwr09Kvce2GQOmVQKa2xSPWTDdShqTlqhKR0X0Ki2HSh wFnRCNjDPwqw== X-IronPort-AV: E=McAfee;i="6000,8403,9924"; a="189260174" X-IronPort-AV: E=Sophos;i="5.81,251,1610438400"; d="scan'208";a="189260174" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga103.jf.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 From: "Chang S. Bae" To: bp@suse.de, tglx@linutronix.de, mingo@kernel.org, luto@kernel.org, x86@kernel.org Cc: len.brown@intel.com, dave.hansen@intel.com, hjl.tools@gmail.com, Dave.Martin@arm.com, jannh@google.com, mpe@ellerman.id.au, carlos@redhat.com, tony.luck@intel.com, ravi.v.shankar@intel.com, libc-alpha@sourceware.org, linux-arch@vger.kernel.org, linux-api@vger.kernel.org, linux-kernel@vger.kernel.org, chang.seok.bae@intel.com 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> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 */ -- 2.17.1