From patchwork Tue Nov 17 03:17:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 11911391 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0439DC388F9 for ; Tue, 17 Nov 2020 03:19:28 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 830D624694 for ; Tue, 17 Nov 2020 03:19:27 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="YTSKFZK4"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="uFaM/YxQ" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 830D624694 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:To:From:Subject:References:Mime-Version:Message-Id: In-Reply-To:Date:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=0Job9qdeL50EZFmQc6CkWUw9aC0xPSw5nRdwhOgIyXE=; b=YTSKFZK4rRyFbpcwhM74r/cpq nvuqLpGoKkecGgByb4p2zu0ssBV95/2/qAfsDrVH6MamnO7X69DEBTZui2zy6JSy30zXUHQ/iGn7X l6d+OKfDLrYLVcaaw8a8PEHwrAM+mMPs2qf1M+zm6CwV+YYXSXiLwGsUwmkLtPGKjZqzngJvnGpYE 73y30UAVbPZk+isTyM1774tL1ty87lGuI6d0T+P9erUFZS7xnio9Mrcx1MbgR7XRBIbUUkUm2ti3i f8H/OR6gjSDWTVjydwhAGDK6ApedVxbk8i2nyJrkxo10oJ6YOw0scvtXkPSwWYC1b0JUCYrTVrX3h TdwoCZ2Ow==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kerV0-00049F-LE; Tue, 17 Nov 2020 03:17:42 +0000 Received: from mail-pf1-x44a.google.com ([2607:f8b0:4864:20::44a]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kerUx-00048M-LN for linux-arm-kernel@lists.infradead.org; Tue, 17 Nov 2020 03:17:40 +0000 Received: by mail-pf1-x44a.google.com with SMTP id a24so13761087pfo.3 for ; Mon, 16 Nov 2020 19:17:37 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=HuMspXIQ1vn0+ZumsLYjmGAwT+zGOwAT2v6OIPNSsT0=; b=uFaM/YxQUDATljb5DcWZr3qKob3St2pMqUOQg88VWbjSTsDum+IS9ohXmhW3Wn53vs Y2qB0OmWgOorDg1fGE4CaRg69UhOQVlD7OUTv3uiS0snh0qxfSJh2lM/LBvEecxi9rjC B7d5azTwTnP7uKwhJ5r52je5aAODT0p9ZV3HGuwfiOxfNcAlhawzfNaGCe3+IT/qRku0 ugijBxuOF1KZxc6MnxyPxffLzd4c3ETWF5drrrvFtUJaHDSLZOuQ8CscJy/cXIHA9z6o oRPk4Z8xgomZGSWmh6o7oZKlfU5l5w7BWKsbUwD3mMgOEXbQ9wZYWhwQWfHlCsfU1JjV UF6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=HuMspXIQ1vn0+ZumsLYjmGAwT+zGOwAT2v6OIPNSsT0=; b=DIFXTuWa4kRLNjWI2okVsH2T+RR7/j6CvGLrLTqjRrOtpUQrP/wx/gatuIBAOu9vEK 0AIajzVzqYmdLMvWbIeDAHhrtuNdDnRRgBNambHpuiVvrr3hYnWXjFtZO9mE80x9TyFk XLC3IjkylkTa2L59MJqm0kqfODoetWBHuKNdUjkhrFxElxrt6N41tDpynleFXxXyHpoI vtSFZyIOt6cbatTnXP74L/sJTm9Qt4Ed3l8gZQ3xXSLNkPGUzz0i8ArjcbQtgtdGas9z de75ayL+heyW80K7Qza+uEsk8bNgzTqJx2pHh6cak+6A4/ioura42dMbh1BxlFe2g3R3 vA1w== X-Gm-Message-State: AOAM531HtqJBXDDE2Lvxww2Pkfd6iicmm+Jyh/0jF/gou7H9b4zCCHUo q5oIxAhyihNrnKJM92AlZ8IaaDk= X-Google-Smtp-Source: ABdhPJznLr5RckPvsSEPyZ7t77ewqqdyK65KCvVE16OkknBRcsvR3X4WQUBiu8bqRK2IQsHfIpLlITE= X-Received: from pcc-desktop.svl.corp.google.com ([2620:15c:2ce:0:7220:84ff:fe09:385a]) (user=pcc job=sendgmr) by 2002:a17:902:a504:b029:d8:ebc7:a864 with SMTP id s4-20020a170902a504b02900d8ebc7a864mr6768825plq.60.1605583055418; Mon, 16 Nov 2020 19:17:35 -0800 (PST) Date: Mon, 16 Nov 2020 19:17:24 -0800 In-Reply-To: Message-Id: <198c8b68c76bf3ed73117d817c7cdf9bc0eb174f.1605582887.git.pcc@google.com> Mime-Version: 1.0 References: X-Mailer: git-send-email 2.29.2.299.gdc1121823c-goog Subject: [PATCH v17 1/3] arch: provide better documentation for the arch-specific SA_* flags From: Peter Collingbourne To: Catalin Marinas , Evgenii Stepanov , Kostya Serebryany , Vincenzo Frascino , Dave Martin , Will Deacon , Oleg Nesterov , "Eric W. Biederman" , "James E.J. Bottomley" X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201116_221739_767680_B931A4DE X-CRM114-Status: GOOD ( 14.35 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrey Konovalov , Helge Deller , Kevin Brodsky , linux-api@vger.kernel.org, David Spickett , Peter Collingbourne , Linux ARM Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Instead of documenting the arch-specific flag values in a comment at the top where they may be easily overlooked, document them in comments inline with the definitions in numerical order so that it is clear why specific values must be chosen for new generic flags and to reduce the likelihood of conflicts between generic and arch-specific flags. Signed-off-by: Peter Collingbourne Link: https://linux-review.googlesource.com/id/I40a129cf7c3a71ba1bfd6d936c544072ee3b7ce6 --- include/uapi/asm-generic/signal-defs.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h index 493953fe319b..44f070982752 100644 --- a/include/uapi/asm-generic/signal-defs.h +++ b/include/uapi/asm-generic/signal-defs.h @@ -17,9 +17,6 @@ * * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single * Unix names RESETHAND and NODEFER respectively. - * - * The following bits are used in architecture-specific SA_* definitions and - * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26. */ #ifndef SA_NOCLDSTOP #define SA_NOCLDSTOP 0x00000001 @@ -30,6 +27,20 @@ #ifndef SA_SIGINFO #define SA_SIGINFO 0x00000004 #endif +/* 0x00000008 used on alpha, mips, parisc */ +/* 0x00000010 used on alpha, parisc */ +/* 0x00000020 used on alpha, parisc, sparc */ +/* 0x00000040 used on alpha, parisc */ +/* 0x00000080 used on parisc */ +/* 0x00000100 used on sparc */ +/* 0x00000200 used on sparc */ +/* 0x00010000 used on mips */ +/* 0x01000000 used on x86 */ +/* 0x02000000 used on x86 */ +/* + * New architectures should not define the obsolete + * SA_RESTORER 0x04000000 + */ #ifndef SA_ONSTACK #define SA_ONSTACK 0x08000000 #endif @@ -46,11 +57,6 @@ #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND -/* - * New architectures should not define the obsolete - * SA_RESTORER 0x04000000 - */ - #ifndef SIG_BLOCK #define SIG_BLOCK 0 /* for blocking signals */ #endif From patchwork Tue Nov 17 03:17:25 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 11911389 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2A4B5C388F9 for ; Tue, 17 Nov 2020 03:18:30 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 94BDD24694 for ; Tue, 17 Nov 2020 03:18:29 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="d8+M7H3J"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="HSx4T7wa" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 94BDD24694 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:To:From:Subject:References:Mime-Version:Message-Id: In-Reply-To:Date:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=mdGRSNfBpNoEGQNkxZ3D2wloDLW7kR1xGR8ox1zFENM=; b=d8+M7H3JWr6+85YWGpvUies2M LxH6hS634AD1mv6hBYR3PU573BAOcP6jX5cohwfr9fqTHfu3jhON4nGuDa2+AUGO4v72FvvrHoDQJ 2jH63VogSphfT1qW5wki5slW6HhqPb38GJOiNJdroF/pfKLRrUF9g3u2NfauI647FhUsnqGxbr12w 4GOiQNS9JnAB3vjR561uCshRejgjj3hPEH8VGGrSz6UDQk1gQW30HCIubKxWkuVy/jNyem0e52sFD PVvrf21FcmT3/bK7lmOzRb7WYTssrIqOSJpjrVh9SpqD51hftFSxZghVWaVN01jFlaK5YD1FEoQuS QloVWiuPA==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kerV6-0004A6-Oa; Tue, 17 Nov 2020 03:17:48 +0000 Received: from mail-yb1-xb49.google.com ([2607:f8b0:4864:20::b49]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kerUz-00048N-AC for linux-arm-kernel@lists.infradead.org; Tue, 17 Nov 2020 03:17:42 +0000 Received: by mail-yb1-xb49.google.com with SMTP id w8so2863190ybq.4 for ; Mon, 16 Nov 2020 19:17:39 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=+/xhIY0o37SOCy7xplXuFsniKU4mnkPoK9rcWBJmUrk=; b=HSx4T7wa8IETmW2qd314AN06jL7a6fY0TcQqEnIyWddUkU1QWGQ09XzCd1a2N9M3up GtKmdYch+pokun+erjbbSd2lQ+WkprOeYLBC1zO8Og7j/pDBpwu2z9BaPK1tQVErme/W xYuixNHu8Q1K7RUrCpECVjVXoH3vEVJi1eGW/DfxVbuHEqfsjbkbKry8iYXhX1rWlbz9 LeIeucuhgbNmAuVOqm/fTod7+JrsuRrI2giGsg+xzbzeLsoI2QzJOW/1fNO+c6+KaE/s lvxEY6Dqt7I2xRwr36pGCUGyywyDhFtg2x6xCCIudF1iFoVxRxq4JAPC9DlgiX1ns/dc /u3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=+/xhIY0o37SOCy7xplXuFsniKU4mnkPoK9rcWBJmUrk=; b=KjOz8rZmwMhsAyN3O7peiJDW9Y5tfelumRXw4vavl95+h4r3WzTDBDG2vHaP3NqViu YAIdErrtRY/a7CE+gbAy63QbM7VIdEalO2bGERX3OJ9ECWTxqbP9T9hAAJzQ6XKbetbS a0FnvTuWQMq3eZHZKcHn/dxDOvJNnWljSHRJVhicX00429DRGgmFBnUjfmb9j+MaakTT BL6REpow1r0a8RWw235+7upBb/h4U+5MBqpsqdvI/UIILJxFDbniOTsmwHQZ4z097cuI K/RcQYdywZq+oF9gWd9uRHVYmJPc77zGII9MJNuvyYvVXGXEOcNEgFZ9eotPai3wZReP bBZQ== X-Gm-Message-State: AOAM531PIJ//lN2K+hzCpfnN0Nas4OHBOdGyQ/JOXutvZ/bJ3oksC8X7 ADScYZiFvjogsD6yvZ9XVruGDA8= X-Google-Smtp-Source: ABdhPJwRYjpupZkut/RoyUhkE1Q9L5yF98e/0p4cjPYwHL6vMYKZ0fqA4JVjgLKq9F6BXbGqaSNyIn8= X-Received: from pcc-desktop.svl.corp.google.com ([2620:15c:2ce:0:7220:84ff:fe09:385a]) (user=pcc job=sendgmr) by 2002:a25:b11e:: with SMTP id g30mr26756032ybj.71.1605583057711; Mon, 16 Nov 2020 19:17:37 -0800 (PST) Date: Mon, 16 Nov 2020 19:17:25 -0800 In-Reply-To: Message-Id: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.29.2.299.gdc1121823c-goog Subject: [PATCH v17 2/3] signal: define the SA_UNSUPPORTED bit in sa_flags From: Peter Collingbourne To: Catalin Marinas , Evgenii Stepanov , Kostya Serebryany , Vincenzo Frascino , Dave Martin , Will Deacon , Oleg Nesterov , "Eric W. Biederman" , "James E.J. Bottomley" X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201116_221741_436419_FD10B723 X-CRM114-Status: GOOD ( 18.04 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrey Konovalov , Helge Deller , Kevin Brodsky , linux-api@vger.kernel.org, David Spickett , Peter Collingbourne , Linux ARM Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Define a sa_flags bit, SA_UNSUPPORTED, which will never be supported in the uapi. The purpose of this flag bit is to allow userspace to distinguish an old kernel that does not clear unknown sa_flags bits from a kernel that supports every flag bit. In other words, if userspace does something like: act.sa_flags |= SA_UNSUPPORTED; sigaction(SIGSEGV, &act, 0); sigaction(SIGSEGV, 0, &oldact); and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means that the kernel cannot be trusted to have cleared unknown flag bits from sa_flags, so no assumptions about flag bit support can be made. Signed-off-by: Peter Collingbourne Reviewed-by: Dave Martin Link: https://linux-review.googlesource.com/id/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb --- v11: - clarify the commit message include/uapi/asm-generic/signal-defs.h | 7 +++++++ kernel/signal.c | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h index 44f070982752..c790f67304ba 100644 --- a/include/uapi/asm-generic/signal-defs.h +++ b/include/uapi/asm-generic/signal-defs.h @@ -14,6 +14,12 @@ * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NODEFER prevents the current signal from being masked in the handler. * SA_RESETHAND clears the handler when the signal is delivered. + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from + * sa_flags when read using the oldact argument to sigaction and rt_sigaction, + * so this bit allows flag bit support to be detected from userspace while + * allowing an old kernel to be distinguished from a kernel that supports every + * flag bit. * * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single * Unix names RESETHAND and NODEFER respectively. @@ -34,6 +40,7 @@ /* 0x00000080 used on parisc */ /* 0x00000100 used on sparc */ /* 0x00000200 used on sparc */ +#define SA_UNSUPPORTED 0x00000400 /* 0x00010000 used on mips */ /* 0x01000000 used on x86 */ /* 0x02000000 used on x86 */ diff --git a/kernel/signal.c b/kernel/signal.c index 8f5bd12ee41b..8f34819e80de 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3985,6 +3985,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact) if (oact) *oact = *k; + /* + * Make sure that we never accidentally claim to support SA_UNSUPPORTED, + * e.g. by having an architecture use the bit in their uapi. + */ + BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED); + /* * Clear unknown flag bits in order to allow userspace to detect missing * support for flag bits and to allow the kernel to use non-uapi bits From patchwork Tue Nov 17 03:17:26 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Collingbourne X-Patchwork-Id: 11911395 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.7 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_ADSP_CUSTOM_MED,DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B49EDC6369E for ; Tue, 17 Nov 2020 03:19:39 +0000 (UTC) Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3065E24694 for ; Tue, 17 Nov 2020 03:19:39 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="mxYFjmrr"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="pODDYnwR" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3065E24694 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=google.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=merlin.20170209; h=Sender:Content-Transfer-Encoding: Content-Type:Cc:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:To:From:Subject:References:Mime-Version:Message-Id: In-Reply-To:Date:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=LvFWgrtJnhFMoH1weZwXs25OFF84gaz7eEZWYePE0mo=; b=mxYFjmrrzpRHKtNWzVSNfFY2l aVdB6thiNUI8LI+B0TyFT36YyFDqyE/zU2vIxB/UPi6dC/tSpFGT7eFDef2j3w9Viisk080xjj4/E glNCH+Xfc+9zaRtun5fxG1S57YHrKbIxMKHZCcpSgQwwX6nllnOEZuJTNAPV/8QnwJbnoYXtpg+KP RAMdbs/0/np4EjmQsywVFK7/MiyXyLBulKQhjR6fqxvrvRpn4/oGuiYSG9KSH28xEotAwiZ+cPy1H gaLCvMgU4cbu+Q3pSX1ydd+LtOIbLGIfzM2dEqgLWAtU8NEeTVcxTrcfbTIWG1Kzzu6nqHXnqd6af 71Dnaeh4Q==; Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1kerVB-0004AQ-9c; Tue, 17 Nov 2020 03:17:53 +0000 Received: from mail-pl1-x64a.google.com ([2607:f8b0:4864:20::64a]) by merlin.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1kerV2-00048q-RK for linux-arm-kernel@lists.infradead.org; Tue, 17 Nov 2020 03:17:46 +0000 Received: by mail-pl1-x64a.google.com with SMTP id v8so10650423ply.0 for ; Mon, 16 Nov 2020 19:17:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=m5ATGGKYg6fHTMdCV7VLEomarz4DL8BUmiYpamxo3oY=; b=pODDYnwRjSspVcKu9lvFqWuaVJx32mQEyCR850LRrmbhPOZy+rP5QlKdSPuvUCkdpk yQf49n1uhPllDSZ18us8JtxhIfRi/EEA7NYhfZYvCHUe72Xr3kng/HKdFQcB78nv0TF9 pVNGD5zJi/unMJXcDFBeIV4vgdVPS/Gven0felrwcyVKzGqUtceZ2FbtNhT3DGdbQWFH HDhvaLUvzkZABH2N+qlJConr95NtRSX4+h2PBXWDPDsKZ5FEG8IUXDXxA1mC4ZhwRVog f37FsMqiDDXzvoPojl53U+KXVm4UDe5OYOoc7BsvGx6CLfbUQJmW7ys35VSZcRJNzVhI szeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=m5ATGGKYg6fHTMdCV7VLEomarz4DL8BUmiYpamxo3oY=; b=HsPOsyfpW7+FKOccvDjgEBL4if4D4bteCAwDWWt9Qa9/KTsWDbx7mjk7wE9E1x3V8W 91j1wbXksfKyOyQSIaU636vOmNstRe6DnHD8BsrjrIiQy8yJUI9AmyXzhuBaiw9fCyYC Vj6WMDvMmdFRkcUyF4S2eeuFR0xy/mwOVfeEQLiu2gvpvOw9MdFMZ63QLRowANKO2r5G 9Se/oR0PEtm76ccox9cCwIgsQYNqZ69UfLR5RF2cdgjs2I3yJS4egiJMBVqNt4qouPj7 2D6JgYjW+YZF1zUpw7ubmatsptk/h1g0OgyPkbz0+Sh8uWp8T9UewdBkqsjY/+oVlvHG D0hg== X-Gm-Message-State: AOAM533HT/L0VNbCBVjxR71KdtoBtHz8Wepui/LhWkV5d6FdcXd43RoR wsauV5C1r+euGQl8bNz5vEYdd7c= X-Google-Smtp-Source: ABdhPJx+ud9c+CWMlAfT0wEJsBiaJu7yQTLTwnwguGXz1OsZUPf9g9djosLKwJ6gPB7gcpPSxX7f/FQ= X-Received: from pcc-desktop.svl.corp.google.com ([2620:15c:2ce:0:7220:84ff:fe09:385a]) (user=pcc job=sendgmr) by 2002:a17:902:7088:b029:d6:8072:9ce1 with SMTP id z8-20020a1709027088b02900d680729ce1mr15785908plk.11.1605583059772; Mon, 16 Nov 2020 19:17:39 -0800 (PST) Date: Mon, 16 Nov 2020 19:17:26 -0800 In-Reply-To: Message-Id: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.29.2.299.gdc1121823c-goog Subject: [PATCH v17 3/3] arm64: expose FAR_EL1 tag bits in siginfo From: Peter Collingbourne To: Catalin Marinas , Evgenii Stepanov , Kostya Serebryany , Vincenzo Frascino , Dave Martin , Will Deacon , Oleg Nesterov , "Eric W. Biederman" , "James E.J. Bottomley" X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20201116_221745_193875_690BA445 X-CRM114-Status: GOOD ( 31.85 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrey Konovalov , Helge Deller , Kevin Brodsky , linux-api@vger.kernel.org, David Spickett , Peter Collingbourne , Linux ARM Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org The kernel currently clears the tag bits (i.e. bits 56-63) in the fault address exposed via siginfo.si_addr and sigcontext.fault_address. However, the tag bits may be needed by tools in order to accurately diagnose memory errors, such as HWASan [1] or future tools based on the Memory Tagging Extension (MTE). We should not stop clearing these bits in the existing fault address fields, because there may be existing userspace applications that are expecting the tag bits to be cleared. Instead, introduce a flag in sigaction.sa_flags, SA_EXPOSE_TAGBITS, and only expose the tag bits there if the signal handler has this flag set. [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html Signed-off-by: Peter Collingbourne Reviewed-by: Catalin Marinas Link: https://linux-review.googlesource.com/id/Ia8876bad8c798e0a32df7c2ce1256c4771c81446 --- v16: - add missing file v15: - switched to the SA_EXPOSE_TAGBITS approach proposed by Eric - rebased to 5.10-rc3 v14: - fix an inaccuracy in the commit message - add some comments to arch_addr_tag_bits_mask v13: - renamed si_xflags to si_faultflags - rebased to 5.10-rc2 v12: - add new fields to signal_compat.c test cases - rebased to 5.10-rc1 - mask out bits 63:60 for tag check faults v11: - add a comment explaining what the arch hook should do - rename ignored bits to tag bits v10: - rename the flag to SIFAULTFLAG_ADDR_IGNORED_BITS - use an arch hook to specify which bits are ignored, instead of passing them explicitly - while refactoring for the arch hook, noticed that my previous patches missed a case involving cache maintenance instructions, so expose the tag bits for that signal as well v9: - make the ignored bits fields generic - add some new dependent patches that prepare us to store the field in such a way that userspace can detect their presence v8: - rebase onto 5.8rc2 v7: - switch to a new siginfo field instead of using sigcontext - merge the patch back into one since the other patches are now unnecessary v6: - move fault address and fault code into the kernel_siginfo data structure - split the patch in three since it was getting large and now has generic and arch-specific parts v5: - add padding to fault_addr_top_byte_context in order to ensure the correct size and preserve sp alignment v4: - expose only the tag bits in the context instead of the entire FAR_EL1 - remove mention of the new context from the sigcontext.__reserved[] note v3: - add documentation to tagged-pointers.rst - update comments in sigcontext.h v2: - revert changes to hw_breakpoint.c - rename set_thread_esr to set_thread_far_esr Documentation/arm64/tagged-pointers.rst | 25 ++++++--- arch/arm64/include/asm/exception.h | 2 +- arch/arm64/include/asm/signal.h | 25 +++++++++ arch/arm64/include/asm/system_misc.h | 2 +- arch/arm64/include/asm/traps.h | 6 +-- arch/arm64/kernel/debug-monitors.c | 5 +- arch/arm64/kernel/entry-common.c | 2 - arch/arm64/kernel/ptrace.c | 7 +-- arch/arm64/kernel/sys_compat.c | 5 +- arch/arm64/kernel/traps.c | 29 ++++++----- arch/arm64/mm/fault.c | 68 ++++++++++++++----------- include/linux/signal.h | 14 +++++ include/linux/signal_types.h | 2 +- include/uapi/asm-generic/signal-defs.h | 3 ++ kernel/signal.c | 23 ++++++--- 15 files changed, 141 insertions(+), 77 deletions(-) create mode 100644 arch/arm64/include/asm/signal.h diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst index eab4323609b9..19d284b70384 100644 --- a/Documentation/arm64/tagged-pointers.rst +++ b/Documentation/arm64/tagged-pointers.rst @@ -53,12 +53,25 @@ visibility. Preserving tags --------------- -Non-zero tags are not preserved when delivering signals. This means that -signal handlers in applications making use of tags cannot rely on the -tag information for user virtual addresses being maintained for fields -inside siginfo_t. One exception to this rule is for signals raised in -response to watchpoint debug exceptions, where the tag information will -be preserved. +When delivering signals, non-zero tags are not preserved in +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in +sigaction.sa_flags when the signal handler was installed. This means +that signal handlers in applications making use of tags cannot rely +on the tag information for user virtual addresses being maintained +in these fields unless the flag was set. + +Due to architecture limitations, bits 63:60 of the fault address +are not preserved in response to synchronous tag check faults +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should +treat the values of these bits as undefined in order to accommodate +future architecture revisions which may preserve the bits. + +For signals raised in response to watchpoint debug exceptions, the +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS +flag setting. + +Non-zero tags are never preserved in sigcontext.fault_address +regardless of the SA_EXPOSE_TAGBITS flag setting. The architecture prevents the use of a tagged PC, so the upper byte will be set to a sign-extension of bit 55 on exception return. diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h index 99b9383cd036..2a8aa1884d8a 100644 --- a/arch/arm64/include/asm/exception.h +++ b/arch/arm64/include/asm/exception.h @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr) } asmlinkage void enter_from_user_mode(void); -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs); +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs); void do_undefinstr(struct pt_regs *regs); void do_bti(struct pt_regs *regs); asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr); diff --git a/arch/arm64/include/asm/signal.h b/arch/arm64/include/asm/signal.h new file mode 100644 index 000000000000..ef449f5f4ba8 --- /dev/null +++ b/arch/arm64/include/asm/signal.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ARM64_ASM_SIGNAL_H +#define __ARM64_ASM_SIGNAL_H + +#include +#include +#include + +static inline void __user *arch_untagged_si_addr(void __user *addr, + unsigned long sig, + unsigned long si_code) +{ + /* + * For historical reasons, all bits of the fault address are exposed as + * address bits for watchpoint exceptions. New architectures should + * handle the tag bits consistently. + */ + if (sig == SIGTRAP && si_code == TRAP_BRKPT) + return addr; + + return untagged_addr(addr); +} +#define arch_untagged_si_addr arch_untagged_si_addr + +#endif diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 1ab63cfbbaf1..673be2d1263c 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -22,7 +22,7 @@ void die(const char *msg, struct pt_regs *regs, int err); struct siginfo; void arm64_notify_die(const char *str, struct pt_regs *regs, - int signo, int sicode, void __user *addr, + int signo, int sicode, unsigned long far, int err); void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index d96dc2c7c09d..54f32a0675df 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -26,9 +26,9 @@ void register_undef_hook(struct undef_hook *hook); void unregister_undef_hook(struct undef_hook *hook); void force_signal_inject(int signal, int code, unsigned long address, unsigned int err); void arm64_notify_segfault(unsigned long addr); -void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str); -void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str); -void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str); +void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str); +void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str); +void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str); /* * Move regs->pc to next instruction and do necessary setup before it diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c index fa76151de6ff..4f3661eeb7ec 100644 --- a/arch/arm64/kernel/debug-monitors.c +++ b/arch/arm64/kernel/debug-monitors.c @@ -234,9 +234,8 @@ static void send_user_sigtrap(int si_code) if (interrupts_enabled(regs)) local_irq_enable(); - arm64_force_sig_fault(SIGTRAP, si_code, - (void __user *)instruction_pointer(regs), - "User debug trap"); + arm64_force_sig_fault(SIGTRAP, si_code, instruction_pointer(regs), + "User debug trap"); } static int single_step_handler(unsigned long unused, unsigned int esr, diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index 43d4c329775f..dbbddfbf4a72 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -22,7 +22,6 @@ static void notrace el1_abort(struct pt_regs *regs, unsigned long esr) unsigned long far = read_sysreg(far_el1); local_daif_inherit(regs); - far = untagged_addr(far); do_mem_abort(far, esr, regs); } NOKPROBE_SYMBOL(el1_abort); @@ -114,7 +113,6 @@ static void notrace el0_da(struct pt_regs *regs, unsigned long esr) user_exit_irqoff(); local_daif_restore(DAIF_PROCCTX); - far = untagged_addr(far); do_mem_abort(far, esr, regs); } NOKPROBE_SYMBOL(el0_da); diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index f49b349e16a3..8ac487c84e37 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -192,14 +192,11 @@ static void ptrace_hbptriggered(struct perf_event *bp, break; } } - arm64_force_sig_ptrace_errno_trap(si_errno, - (void __user *)bkpt->trigger, + arm64_force_sig_ptrace_errno_trap(si_errno, bkpt->trigger, desc); } #endif - arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT, - (void __user *)(bkpt->trigger), - desc); + arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT, bkpt->trigger, desc); } /* diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index 3c18c2454089..265fe3eb1069 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c @@ -68,7 +68,7 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags) */ long compat_arm_syscall(struct pt_regs *regs, int scno) { - void __user *addr; + unsigned long addr; switch (scno) { /* @@ -111,8 +111,7 @@ long compat_arm_syscall(struct pt_regs *regs, int scno) break; } - addr = (void __user *)instruction_pointer(regs) - - (compat_thumb_mode(regs) ? 2 : 4); + addr = instruction_pointer(regs) - (compat_thumb_mode(regs) ? 2 : 4); arm64_notify_die("Oops - bad compat syscall(2)", regs, SIGILL, ILL_ILLTRP, addr, scno); diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index 8af4e0e85736..f4ddbe9ed3f1 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -170,32 +170,32 @@ static void arm64_show_signal(int signo, const char *str) __show_regs(regs); } -void arm64_force_sig_fault(int signo, int code, void __user *addr, +void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str) { arm64_show_signal(signo, str); if (signo == SIGKILL) force_sig(SIGKILL); else - force_sig_fault(signo, code, addr); + force_sig_fault(signo, code, (void __user *)far); } -void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, +void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str) { arm64_show_signal(SIGBUS, str); - force_sig_mceerr(code, addr, lsb); + force_sig_mceerr(code, (void __user *)far, lsb); } -void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, +void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str) { arm64_show_signal(SIGTRAP, str); - force_sig_ptrace_errno_trap(errno, addr); + force_sig_ptrace_errno_trap(errno, (void __user *)far); } void arm64_notify_die(const char *str, struct pt_regs *regs, - int signo, int sicode, void __user *addr, + int signo, int sicode, unsigned long far, int err) { if (user_mode(regs)) { @@ -203,7 +203,7 @@ void arm64_notify_die(const char *str, struct pt_regs *regs, current->thread.fault_address = 0; current->thread.fault_code = err; - arm64_force_sig_fault(signo, sicode, addr, str); + arm64_force_sig_fault(signo, sicode, far, str); } else { die(str, regs, err); } @@ -374,7 +374,7 @@ void force_signal_inject(int signal, int code, unsigned long address, unsigned i signal = SIGKILL; } - arm64_notify_die(desc, regs, signal, code, (void __user *)address, err); + arm64_notify_die(desc, regs, signal, code, address, err); } /* @@ -385,7 +385,7 @@ void arm64_notify_segfault(unsigned long addr) int code; mmap_read_lock(current->mm); - if (find_vma(current->mm, addr) == NULL) + if (find_vma(current->mm, untagged_addr(addr)) == NULL) code = SEGV_MAPERR; else code = SEGV_ACCERR; @@ -448,12 +448,13 @@ NOKPROBE_SYMBOL(do_ptrauth_fault); static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) { - unsigned long address; + unsigned long tagged_address, address; int rt = ESR_ELx_SYS64_ISS_RT(esr); int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT; int ret = 0; - address = untagged_addr(pt_regs_read_reg(regs, rt)); + tagged_address = pt_regs_read_reg(regs, rt); + address = untagged_addr(tagged_address); switch (crm) { case ESR_ELx_SYS64_ISS_CRM_DC_CVAU: /* DC CVAU, gets promoted */ @@ -480,7 +481,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs) } if (ret) - arm64_notify_segfault(address); + arm64_notify_segfault(tagged_address); else arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE); } @@ -772,7 +773,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr) */ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr) { - void __user *pc = (void __user *)instruction_pointer(regs); + unsigned long pc = instruction_pointer(regs); current->thread.fault_address = 0; current->thread.fault_code = esr; diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 1ee94002801f..c5375cb7763d 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -40,7 +40,7 @@ #include struct fault_info { - int (*fn)(unsigned long addr, unsigned int esr, + int (*fn)(unsigned long far, unsigned int esr, struct pt_regs *regs); int sig; int code; @@ -385,8 +385,11 @@ static void set_thread_esr(unsigned long address, unsigned int esr) current->thread.fault_code = esr; } -static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs) +static void do_bad_area(unsigned long far, unsigned int esr, + struct pt_regs *regs) { + unsigned long addr = untagged_addr(far); + /* * If we are in kernel mode at this point, we have no context to * handle this fault with. @@ -395,8 +398,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re const struct fault_info *inf = esr_to_fault_info(esr); set_thread_esr(addr, esr); - arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr, - inf->name); + arm64_force_sig_fault(inf->sig, inf->code, far, inf->name); } else { __do_kernel_fault(addr, esr, regs); } @@ -448,7 +450,7 @@ static bool is_write_abort(unsigned int esr) return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM); } -static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, +static int __kprobes do_page_fault(unsigned long far, unsigned int esr, struct pt_regs *regs) { const struct fault_info *inf; @@ -456,6 +458,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, vm_fault_t fault; unsigned long vm_flags = VM_ACCESS_FLAGS; unsigned int mm_flags = FAULT_FLAG_DEFAULT; + unsigned long addr = untagged_addr(far); if (kprobe_page_fault(regs, esr)) return 0; @@ -567,8 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, * We had some memory, but were unable to successfully fix up * this page fault. */ - arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr, - inf->name); + arm64_force_sig_fault(SIGBUS, BUS_ADRERR, far, inf->name); } else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) { unsigned int lsb; @@ -576,8 +578,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, if (fault & VM_FAULT_HWPOISON_LARGE) lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); - arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb, - inf->name); + arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name); } else { /* * Something tried to access memory that isn't in our memory @@ -585,8 +586,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, */ arm64_force_sig_fault(SIGSEGV, fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR, - (void __user *)addr, - inf->name); + far, inf->name); } return 0; @@ -596,33 +596,35 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, return 0; } -static int __kprobes do_translation_fault(unsigned long addr, +static int __kprobes do_translation_fault(unsigned long far, unsigned int esr, struct pt_regs *regs) { + unsigned long addr = untagged_addr(far); + if (is_ttbr0_addr(addr)) - return do_page_fault(addr, esr, regs); + return do_page_fault(far, esr, regs); - do_bad_area(addr, esr, regs); + do_bad_area(far, esr, regs); return 0; } -static int do_alignment_fault(unsigned long addr, unsigned int esr, +static int do_alignment_fault(unsigned long far, unsigned int esr, struct pt_regs *regs) { - do_bad_area(addr, esr, regs); + do_bad_area(far, esr, regs); return 0; } -static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs) +static int do_bad(unsigned long far, unsigned int esr, struct pt_regs *regs) { return 1; /* "fault" */ } -static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) +static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs) { const struct fault_info *inf; - void __user *siaddr; + unsigned long siaddr; inf = esr_to_fault_info(esr); @@ -635,18 +637,23 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) } if (esr & ESR_ELx_FnV) - siaddr = NULL; + siaddr = 0; else - siaddr = (void __user *)addr; + siaddr = untagged_addr(far); arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr); return 0; } -static int do_tag_check_fault(unsigned long addr, unsigned int esr, +static int do_tag_check_fault(unsigned long far, unsigned int esr, struct pt_regs *regs) { - do_bad_area(addr, esr, regs); + /* + * The architecture specifies that bits 63:60 of FAR_EL1 are UNKNOWN for tag + * check faults. Mask them out now so that userspace doesn't see them. + */ + far &= (1UL << 60) - 1; + do_bad_area(far, esr, regs); return 0; } @@ -717,11 +724,12 @@ static const struct fault_info fault_info[] = { { do_bad, SIGKILL, SI_KERNEL, "unknown 63" }, }; -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs) { const struct fault_info *inf = esr_to_fault_info(esr); + unsigned long addr = untagged_addr(far); - if (!inf->fn(addr, esr, regs)) + if (!inf->fn(far, esr, regs)) return; if (!user_mode(regs)) { @@ -730,8 +738,7 @@ void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) show_pte(addr); } - arm64_notify_die(inf->name, regs, - inf->sig, inf->code, (void __user *)addr, esr); + arm64_notify_die(inf->name, regs, inf->sig, inf->code, addr, esr); } NOKPROBE_SYMBOL(do_mem_abort); @@ -744,8 +751,8 @@ NOKPROBE_SYMBOL(do_el0_irq_bp_hardening); void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) { - arm64_notify_die("SP/PC alignment exception", regs, - SIGBUS, BUS_ADRALN, (void __user *)addr, esr); + arm64_notify_die("SP/PC alignment exception", regs, SIGBUS, BUS_ADRALN, + addr, esr); } NOKPROBE_SYMBOL(do_sp_pc_abort); @@ -871,8 +878,7 @@ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr, arm64_apply_bp_hardening(); if (inf->fn(addr_if_watchpoint, esr, regs)) { - arm64_notify_die(inf->name, regs, - inf->sig, inf->code, (void __user *)pc, esr); + arm64_notify_die(inf->name, regs, inf->sig, inf->code, pc, esr); } debug_exception_exit(regs); diff --git a/include/linux/signal.h b/include/linux/signal.h index b256f9c65661..205526c4003a 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -469,4 +469,18 @@ struct seq_file; extern void render_sigset_t(struct seq_file *, const char *, sigset_t *); #endif +#ifndef arch_untagged_si_addr +/* + * Given a fault address and a signal and si_code which correspond to the + * _sigfault union member, returns the address that must appear in si_addr if + * the signal handler does not have SA_EXPOSE_TAGBITS enabled in sa_flags. + */ +static inline void __user *arch_untagged_si_addr(void __user *addr, + unsigned long sig, + unsigned long si_code) +{ + return addr; +} +#endif + #endif /* _LINUX_SIGNAL_H */ diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h index a7887ad84d36..68e06c75c5b2 100644 --- a/include/linux/signal_types.h +++ b/include/linux/signal_types.h @@ -78,6 +78,6 @@ struct ksignal { #define UAPI_SA_FLAGS \ (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \ - SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS) + SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS | __ARCH_UAPI_SA_FLAGS) #endif /* _LINUX_SIGNAL_TYPES_H */ diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h index c790f67304ba..fe929e7b77ca 100644 --- a/include/uapi/asm-generic/signal-defs.h +++ b/include/uapi/asm-generic/signal-defs.h @@ -20,6 +20,8 @@ * so this bit allows flag bit support to be detected from userspace while * allowing an old kernel to be distinguished from a kernel that supports every * flag bit. + * SA_EXPOSE_TAGBITS exposes an architecture-defined set of tag bits in + * siginfo.si_addr. * * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single * Unix names RESETHAND and NODEFER respectively. @@ -41,6 +43,7 @@ /* 0x00000100 used on sparc */ /* 0x00000200 used on sparc */ #define SA_UNSUPPORTED 0x00000400 +#define SA_EXPOSE_TAGBITS 0x00000800 /* 0x00010000 used on mips */ /* 0x01000000 used on x86 */ /* 0x02000000 used on x86 */ diff --git a/kernel/signal.c b/kernel/signal.c index 8f34819e80de..16be62e6d341 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1650,6 +1650,15 @@ void force_sigsegv(int sig) force_sig(SIGSEGV); } +static void __user *get_si_addr(void __user *addr, unsigned long sig, + unsigned long si_code) +{ + if (current->sighand->action[sig - 1].sa.sa_flags & SA_EXPOSE_TAGBITS) + return addr; + + return arch_untagged_si_addr(addr, sig, si_code); +} + int force_sig_fault_to_task(int sig, int code, void __user *addr ___ARCH_SI_TRAPNO(int trapno) ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr) @@ -1661,7 +1670,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr info.si_signo = sig; info.si_errno = 0; info.si_code = code; - info.si_addr = addr; + info.si_addr = get_si_addr(addr, sig, code); #ifdef __ARCH_SI_TRAPNO info.si_trapno = trapno; #endif @@ -1693,7 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr info.si_signo = sig; info.si_errno = 0; info.si_code = code; - info.si_addr = addr; + info.si_addr = get_si_addr(addr, sig, code); #ifdef __ARCH_SI_TRAPNO info.si_trapno = trapno; #endif @@ -1714,7 +1723,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb) info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = code; - info.si_addr = addr; + info.si_addr = get_si_addr(addr, SIGBUS, code); info.si_addr_lsb = lsb; return force_sig_info(&info); } @@ -1728,7 +1737,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct * info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = code; - info.si_addr = addr; + info.si_addr = get_si_addr(addr, SIGBUS, code); info.si_addr_lsb = lsb; return send_sig_info(info.si_signo, &info, t); } @@ -1742,7 +1751,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper) info.si_signo = SIGSEGV; info.si_errno = 0; info.si_code = SEGV_BNDERR; - info.si_addr = addr; + info.si_addr = get_si_addr(addr, SIGSEGV, SEGV_BNDERR); info.si_lower = lower; info.si_upper = upper; return force_sig_info(&info); @@ -1757,7 +1766,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey) info.si_signo = SIGSEGV; info.si_errno = 0; info.si_code = SEGV_PKUERR; - info.si_addr = addr; + info.si_addr = get_si_addr(addr, SIGSEGV, SEGV_PKUERR); info.si_pkey = pkey; return force_sig_info(&info); } @@ -1774,7 +1783,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr) info.si_signo = SIGTRAP; info.si_errno = errno; info.si_code = TRAP_HWBKPT; - info.si_addr = addr; + info.si_addr = get_si_addr(addr, SIGTRAP, TRAP_HWBKPT); return force_sig_info(&info); }