Received: by 2002:a4a:301c:0:0:0:0:0 with SMTP id q28-v6csp1267807oof; Tue, 25 Sep 2018 10:21:32 -0700 (PDT) X-Google-Smtp-Source: ACcGV63WEZtnjSFPD5GSF3PGRRUSwVQ+1D3oPAss0vGKH2/+y9SwDgVMsGFinw3ct9dhZefRzfd6 X-Received: by 2002:a63:991a:: with SMTP id d26-v6mr1964168pge.159.1537896091892; Tue, 25 Sep 2018 10:21:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537896091; cv=none; d=google.com; s=arc-20160816; b=N0aYXpQpL4EO5XSyv4pbcv/52apiFGqMPqWQ3/ucUMYWikjxnqJ5ZJkwISeSavE1Uk 2SSutVMJjIbAOgVW1xoCFpfJk01B7tH96xhHvVzy/rzGZCCo/JpSDG9z1z43jJhRSRun XUcd4ylGgBRvP5nk9KPAYwLW4ocVDzDRSCqTnFKrLUSnvljoscCH6Po6srSB7EtxtIMg /WORB20fFjjvsdLx7MBwAurQuGIu+/9zAW6uI8X2yHoD+PlFv+8p4x/VRDgkUn5vP3Jc Onu+yE100HI9HZapPSaqY1CqDziS/QoIV8OGm/KXE8xUOFrx9Cya6VGDbma19OQ2PKvO vskA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:subject:references:in-reply-to:message-id :date:cc:to:from; bh=NIOb2wT6lAJLe/Gpd8Dc0jMaT3HkTFPXpFZo4cdl5vk=; b=QDWYoUS7c8+rEGCl1FSz7zVmbAIej5LPrVT7pW3bhP00DdhRKiOWyqZvsZnI/xKoPQ n2MK5NDLCqu+zHELph5MdLRwDwE+1lC/Nq3PTVa3aEeijUjSiKbECbxD9hBQ0W/h/t+r pM8x7/Q1NzhRNeNslMdHwmMV/rbujRPXUjv7Nl/R/sZRQtLFmkhfBNah9+a9AuYcRjUi 7TOTAhZoLi/OgBVnY2VnOovo3CmMEAQ9MXpBqmj2s+cS4nbKjVK3+z1IJoEP/IsN7gcT u9dWYl1+dBBRNcpF2S0eVYZ2aJ1ZaasOjeFnQazlqCVQdhT246B9U4xby/q0Nxqob4Oq NLQQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x37-v6si2806916pgl.544.2018.09.25.10.21.16; Tue, 25 Sep 2018 10:21:31 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728240AbeIYX3C (ORCPT + 99 others); Tue, 25 Sep 2018 19:29:02 -0400 Received: from out03.mta.xmission.com ([166.70.13.233]:44390 "EHLO out03.mta.xmission.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726400AbeIYX3B (ORCPT ); Tue, 25 Sep 2018 19:29:01 -0400 Received: from in01.mta.xmission.com ([166.70.13.51]) by out03.mta.xmission.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.87) (envelope-from ) id 1g4r0h-00056w-FS; Tue, 25 Sep 2018 11:20:31 -0600 Received: from [105.184.227.67] (helo=x220.Home) by in01.mta.xmission.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.87) (envelope-from ) id 1g4r0g-0001uD-9t; Tue, 25 Sep 2018 11:20:31 -0600 From: "Eric W. Biederman" To: linux-kernel@vger.kernel.org Cc: linux-api@vger.kernel.org, linux-arch@vger.kernel.org, Oleg Nesterov , Linus Torvalds , "Eric W. Biederman" Date: Tue, 25 Sep 2018 19:19:06 +0200 Message-Id: <20180925171906.19683-6-ebiederm@xmission.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <87h8idv6nw.fsf@xmission.com> References: <87h8idv6nw.fsf@xmission.com> X-XM-SPF: eid=1g4r0g-0001uD-9t;;;mid=<20180925171906.19683-6-ebiederm@xmission.com>;;;hst=in01.mta.xmission.com;;;ip=105.184.227.67;;;frm=ebiederm@xmission.com;;;spf=neutral X-XM-AID: U2FsdGVkX19oS2s1r2kIS992IYEvLew8EoEdANCMKPg= X-SA-Exim-Connect-IP: 105.184.227.67 X-SA-Exim-Mail-From: ebiederm@xmission.com X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on sa07.xmission.com X-Spam-Level: *** X-Spam-Status: No, score=3.5 required=8.0 tests=ALL_TRUSTED,BAYES_50, DCC_CHECK_NEGATIVE,TR_Symld_Words,XMNoVowels,XMSubLong autolearn=disabled version=3.4.1 X-Spam-Report: * -1.0 ALL_TRUSTED Passed through trusted hosts only via SMTP * 1.5 TR_Symld_Words too many words that have symbols inside * 1.5 XMNoVowels Alpha-numberic number with no vowels * 0.7 XMSubLong Long Subject * 0.8 BAYES_50 BODY: Bayes spam probability is 40 to 60% * [score: 0.5000] * -0.0 DCC_CHECK_NEGATIVE Not listed in DCC * [sa07 1397; Body=1 Fuz1=1 Fuz2=1] X-Spam-DCC: XMission; sa07 1397; Body=1 Fuz1=1 Fuz2=1 X-Spam-Combo: ***;linux-kernel@vger.kernel.org X-Spam-Relay-Country: X-Spam-Timing: total 353 ms - load_scoreonly_sql: 0.04 (0.0%), signal_user_changed: 2.7 (0.8%), b_tie_ro: 1.88 (0.5%), parse: 0.93 (0.3%), extract_message_metadata: 14 (4.0%), get_uri_detail_list: 2.8 (0.8%), tests_pri_-1000: 7 (2.0%), tests_pri_-950: 1.22 (0.3%), tests_pri_-900: 1.11 (0.3%), tests_pri_-400: 27 (7.6%), check_bayes: 26 (7.3%), b_tokenize: 11 (3.0%), b_tok_get_all: 7 (2.0%), b_comp_prob: 2.2 (0.6%), b_tok_touch_all: 3.3 (0.9%), b_finish: 0.60 (0.2%), tests_pri_0: 290 (82.3%), check_dkim_signature: 0.62 (0.2%), check_dkim_adsp: 2.7 (0.8%), tests_pri_500: 6 (1.6%), rewrite_mail: 0.00 (0.0%) Subject: [REVIEW][PATCH 6/6] signal: Use a smaller struct siginfo in the kernel X-Spam-Flag: No X-SA-Exim-Version: 4.2.1 (built Thu, 05 May 2016 13:38:54 -0600) X-SA-Exim-Scanned: Yes (on in01.mta.xmission.com) Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org We reserve 128 bytes for struct siginfo but only use about 48 bytes on 64bit and 32 bytes on 32bit. Someday we might use more but it is unlikely to be anytime soon. Userspace seems content with just enough bytes of siginfo to implement sigqueue. Or in the case of checkpoint/restart reinjecting signals the kernel has sent. Reducing the stack footprint and the work to copy siginfo around from 2 cachelines to 1 cachelines seems worth doing even if I don't have benchmarks to show a performance difference. Suggested-by: Linus Torvalds Signed-off-by: "Eric W. Biederman" --- include/linux/signal.h | 2 + include/linux/signal_types.h | 5 +-- kernel/signal.c | 82 ++++++++++++++++++++++++++++-------- 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/include/linux/signal.h b/include/linux/signal.h index 70031b10b918..706a499d1eb1 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -22,6 +22,8 @@ static inline void clear_siginfo(kernel_siginfo_t *info) memset(info, 0, sizeof(*info)); } +#define SI_EXPANSION_SIZE (sizeof(struct siginfo) - sizeof(struct kernel_siginfo)) + int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *from); int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from); diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h index 2a40a9c5e4ad..f8a90ae9c6ec 100644 --- a/include/linux/signal_types.h +++ b/include/linux/signal_types.h @@ -10,10 +10,7 @@ #include typedef struct kernel_siginfo { - union { - __SIGINFO; - int _si_pad[SI_MAX_SIZE/sizeof(int)]; - }; + __SIGINFO; } kernel_siginfo_t; /* diff --git a/kernel/signal.c b/kernel/signal.c index 161cad4e448c..1c2dd117fee0 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2844,27 +2844,48 @@ COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, } #endif +static const struct { + unsigned char limit, layout; +} sig_sicodes[] = { + [SIGILL] = { NSIGILL, SIL_FAULT }, + [SIGFPE] = { NSIGFPE, SIL_FAULT }, + [SIGSEGV] = { NSIGSEGV, SIL_FAULT }, + [SIGBUS] = { NSIGBUS, SIL_FAULT }, + [SIGTRAP] = { NSIGTRAP, SIL_FAULT }, +#if defined(SIGEMT) + [SIGEMT] = { NSIGEMT, SIL_FAULT }, +#endif + [SIGCHLD] = { NSIGCHLD, SIL_CHLD }, + [SIGPOLL] = { NSIGPOLL, SIL_POLL }, + [SIGSYS] = { NSIGSYS, SIL_SYS }, +}; + +static bool known_siginfo_layout(int sig, int si_code) +{ + if (si_code == SI_KERNEL) + return true; + else if ((si_code > SI_USER)) { + if (sig_specific_sicodes(sig)) { + if (si_code <= sig_sicodes[sig].limit) + return true; + } + else if (si_code <= NSIGPOLL) + return true; + } + else if (si_code >= SI_DETHREAD) + return true; + else if (si_code == SI_ASYNCNL) + return true; + return false; +} + enum siginfo_layout siginfo_layout(int sig, int si_code) { enum siginfo_layout layout = SIL_KILL; if ((si_code > SI_USER) && (si_code < SI_KERNEL)) { - static const struct { - unsigned char limit, layout; - } filter[] = { - [SIGILL] = { NSIGILL, SIL_FAULT }, - [SIGFPE] = { NSIGFPE, SIL_FAULT }, - [SIGSEGV] = { NSIGSEGV, SIL_FAULT }, - [SIGBUS] = { NSIGBUS, SIL_FAULT }, - [SIGTRAP] = { NSIGTRAP, SIL_FAULT }, -#if defined(SIGEMT) - [SIGEMT] = { NSIGEMT, SIL_FAULT }, -#endif - [SIGCHLD] = { NSIGCHLD, SIL_CHLD }, - [SIGPOLL] = { NSIGPOLL, SIL_POLL }, - [SIGSYS] = { NSIGSYS, SIL_SYS }, - }; - if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit)) { - layout = filter[sig].layout; + if ((sig < ARRAY_SIZE(sig_sicodes)) && + (si_code <= sig_sicodes[sig].limit)) { + layout = sig_sicodes[sig].layout; /* Handle the exceptions */ if ((sig == SIGBUS) && (si_code >= BUS_MCEERR_AR) && (si_code <= BUS_MCEERR_AO)) @@ -2889,17 +2910,42 @@ enum siginfo_layout siginfo_layout(int sig, int si_code) return layout; } +static inline char __user *si_expansion(const siginfo_t __user *info) +{ + return ((char __user *)info) + sizeof(struct kernel_siginfo); +} + int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *from) { + char __user *expansion = si_expansion(to); if (copy_to_user(to, from , sizeof(struct kernel_siginfo))) return -EFAULT; + if (clear_user(expansion, SI_EXPANSION_SIZE)) + return -EFAULT; return 0; } int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from) { - if (copy_from_user(to, from, sizeof(struct siginfo))) + if (copy_from_user(to, from, sizeof(struct kernel_siginfo))) return -EFAULT; + if (unlikely(!known_siginfo_layout(to->si_signo, to->si_code))) { + char __user *expansion = si_expansion(from); + char buf[SI_EXPANSION_SIZE]; + int i; + /* + * An unknown si_code might need more than + * sizeof(struct kernel_siginfo) bytes. Verify all of the + * extra bytes are 0. This guarantees copy_siginfo_to_user + * will return this data to userspace exactly. + */ + if (copy_from_user(&buf, expansion, SI_EXPANSION_SIZE)) + return -EFAULT; + for (i = 0; i < SI_EXPANSION_SIZE; i++) { + if (buf[i] != 0) + return -E2BIG; + } + } return 0; } -- 2.17.1