From patchwork Wed Mar 22 14:50:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Martin X-Patchwork-Id: 9639097 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 AA3E9601E9 for ; Wed, 22 Mar 2017 14:53:00 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9AFA727FA8 for ; Wed, 22 Mar 2017 14:53:00 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8FAE028475; Wed, 22 Mar 2017 14:53:00 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E675C27FA8 for ; Wed, 22 Mar 2017 14:52:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=Fuen5VDz189Ok/VRqGRRyJI03a70rQtz56gOPj6+Zcs=; b=LC9uyQaqVCoq4xzm2RNKFzGyAT wifDvDe65DrbiYe/bHFqTn8LXqTiRaBQ267fO7gbiHia2l3rUrMRhjWPQuuhfkBVuSzGVyAMNPRye RpRXQ8+Ox/6ooMPHj+epSmdtRM82wet8sAX7zMwiKEA/3fPiW/quW8wKBTB8184WNn0biXgJWpj++ Ndvom8WJ7Gcr0bVWG0voCw+epncxQNPoD+5M/ucIrH7EkWVv2paPtAmnyYymMVLnj9TUunZjir6zl 9r+cdXMquUP9+rNherR9jAYLlSZZWpRFPFqGbgBTVYoR3kDDumRi9DdyjpZBMB+Trrrf87kBwyFMI 6xK1isTg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cqhd8-0008GL-U1; Wed, 22 Mar 2017 14:52:54 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cqhcI-00076G-2p for linux-arm-kernel@lists.infradead.org; Wed, 22 Mar 2017 14:52:09 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 3F9C81597; Wed, 22 Mar 2017 07:51:45 -0700 (PDT) Received: from e103592.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id EC4AB3F575; Wed, 22 Mar 2017 07:51:43 -0700 (PDT) From: Dave Martin To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH v2 04/41] arm64: signal: Allocate extra sigcontext space as needed Date: Wed, 22 Mar 2017 14:50:34 +0000 Message-Id: <1490194274-30569-5-git-send-email-Dave.Martin@arm.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1490194274-30569-1-git-send-email-Dave.Martin@arm.com> References: <1490194274-30569-1-git-send-email-Dave.Martin@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170322_075202_711096_7CFA4B41 X-CRM114-Status: GOOD ( 16.76 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Florian Weimer , Ard Biesheuvel , Marc Zyngier , Catalin Marinas , Will Deacon , Szabolcs Nagy , Joseph Myers MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This patch modifies the context block allocator to create an extra_context expansion block as necessary, and adds the necessary code to populate, parse and decode this block. Signed-off-by: Dave Martin --- arch/arm64/include/uapi/asm/sigcontext.h | 27 ++++++++ arch/arm64/kernel/signal.c | 112 +++++++++++++++++++++++++------ 2 files changed, 120 insertions(+), 19 deletions(-) diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h index ee469be..1af8437 100644 --- a/arch/arm64/include/uapi/asm/sigcontext.h +++ b/arch/arm64/include/uapi/asm/sigcontext.h @@ -61,4 +61,31 @@ struct esr_context { __u64 esr; }; +/* + * Pointer to extra space for additional structures that don't fit in + * sigcontext.__reserved[]. Note: + * + * 1) fpsimd_context, esr_context and extra_context must be placed in + * sigcontext.__reserved[] if present. They cannot be placed in the + * extra space. Any other record can be placed either in the extra + * space or in sigcontext.__reserved[]. + * + * 2) There must not be more than one extra_context. + * + * 3) If extra_context is present, it must be followed immediately in + * sigcontext.__reserved[] by the terminating null _aarch64_ctx (i.e., + * extra_context must be the last record in sigcontext.__reserved[] + * except for the terminator). + * + * 4) The extra space must itself be terminated with a null + * _aarch64_ctx. + */ +#define EXTRA_MAGIC 0x45585401 + +struct extra_context { + struct _aarch64_ctx head; + void *data; /* 16-byte aligned pointer to the extra space */ + __u32 size; /* size in bytes of the extra space */ +}; + #endif /* _UAPI__ASM_SIGCONTEXT_H */ diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 411a42d..223bd52 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -56,18 +57,22 @@ struct rt_sigframe_user_layout { unsigned long fpsimd_offset; unsigned long esr_offset; + unsigned long extra_offset; unsigned long end_offset; }; static void init_user_layout(struct rt_sigframe_user_layout *user) { + const size_t __reserved_size = + sizeof(user->sigframe->uc.uc_mcontext.__reserved); + const size_t terminator_size = + round_up(sizeof(struct _aarch64_ctx), 16); + memset(user, 0, sizeof(*user)); user->size = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved); - - user->limit = user->size + - sizeof(user->sigframe->uc.uc_mcontext.__reserved) - - round_up(sizeof(struct _aarch64_ctx), 16); - /* ^ reserve space for terminator */ + user->limit = user->size + (__reserved_size - terminator_size - + sizeof(struct extra_context)); + /* Reserve space for extension and terminator ^ */ } static size_t sigframe_size(struct rt_sigframe_user_layout const *user) @@ -75,6 +80,49 @@ static size_t sigframe_size(struct rt_sigframe_user_layout const *user) return round_up(max(user->size, sizeof(struct rt_sigframe)), 16); } +/* Sanity limit on the maximum size of signal frame we'll try to generate. */ +/* This is NOT ABI. */ +#define SIGFRAME_MAXSZ SZ_64K + +static int __sigframe_alloc(struct rt_sigframe_user_layout *user, + unsigned long *offset, size_t size, bool extend) +{ + size_t padded_size = round_up(size, 16); + + if (padded_size > user->limit - user->size && + !user->extra_offset && + extend) { + int ret; + + ret = __sigframe_alloc(user, &user->extra_offset, + sizeof(struct extra_context), false); + if (ret) + return ret; + + /* + * Further allocations must go after the fixed-size + * part of the signal frame: + */ + user->size = round_up(sizeof(struct rt_sigframe), 16); + + /* + * Allow expansion up to SIGFRAME_MAXSZ, ensuring space for + * the terminator: + */ + user->limit = SIGFRAME_MAXSZ - + round_up(sizeof(struct _aarch64_ctx), 16); + } + + /* Still not enough space? Bad luck! */ + if (padded_size > user->limit - user->size) + return -ENOMEM; + + *offset = user->size; + user->size += padded_size; + + return 0; +} + /* * Allocate space for an optional record of bytes in the user * signal frame. The offset from the signal frame base address to the @@ -83,11 +131,26 @@ static size_t sigframe_size(struct rt_sigframe_user_layout const *user) static int sigframe_alloc(struct rt_sigframe_user_layout *user, unsigned long *offset, size_t size) { - size_t padded_size = round_up(size, 16); + return __sigframe_alloc(user, offset, size, true); +} - *offset = user->size; - user->size += padded_size; +/* Allocate the null terminator record and prevent further allocations */ +static int sigframe_alloc_end(struct rt_sigframe_user_layout *user) +{ + int ret; + const size_t terminator_size = + round_up(sizeof(struct _aarch64_ctx), 16); + + /* Un-reserve the space reserved for the terminator: */ + user->limit += terminator_size; + + ret = sigframe_alloc(user, &user->end_offset, + sizeof(struct _aarch64_ctx)); + if (ret) + return ret; + /* Prevent further allocation: */ + user->limit = user->size; return 0; } @@ -314,17 +377,7 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) return err; } - /* - * Allocate space for the terminator record. - * HACK: here we undo the reservation of space for the end record. - * This bodge should be replaced with a cleaner approach later on. - */ - user->limit = offsetof(struct rt_sigframe, uc.uc_mcontext.__reserved) + - sizeof(user->sigframe->uc.uc_mcontext.__reserved); - - err = sigframe_alloc(user, &user->end_offset, - sizeof(struct _aarch64_ctx)); - return err; + return sigframe_alloc_end(user); } @@ -365,6 +418,27 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user, __put_user_error(current->thread.fault_code, &esr_ctx->esr, err); } + if (err == 0 && user->extra_offset) { + struct extra_context __user *extra = + apply_user_offset(user, user->extra_offset); + struct _aarch64_ctx __user *end = + (struct _aarch64_ctx __user *)((char __user *)extra + + round_up(sizeof(*extra), 16)); + void __user *extra_data = apply_user_offset(user, + round_up(sizeof(struct rt_sigframe), 16)); + u32 extra_size = round_up(user->size, 16) - + round_up(sizeof(struct rt_sigframe), 16); + + __put_user_error(EXTRA_MAGIC, &extra->head.magic, err); + __put_user_error(sizeof(*extra), &extra->head.size, err); + __put_user_error(extra_data, &extra->data, err); + __put_user_error(extra_size, &extra->size, err); + + /* Add the terminator */ + __put_user_error(0, &end->magic, err); + __put_user_error(0, &end->size, err); + } + /* set the "end" magic */ if (err == 0) { struct _aarch64_ctx __user *end =