From patchwork Thu Aug 24 08:18:06 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 110888 Delivered-To: patch@linaro.org Received: by 10.140.95.78 with SMTP id h72csp5321276qge; Thu, 24 Aug 2017 01:25:20 -0700 (PDT) X-Received: by 10.84.232.11 with SMTP id h11mr6276669plk.126.1503563120557; Thu, 24 Aug 2017 01:25:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1503563120; cv=none; d=google.com; s=arc-20160816; b=t3oc5/mJeaukUT1nIlN5p6As3H00VWbPfha+7DuMRolEVT5qsWAr16XwQlWBFGQBTb j1zTJAf3TWGXIA+m/YxK+WHeWGJTahF/Fk4tGl4RLED7RlmnmfwjLoBPmbil4Eyrlr1o OBDFyY7PVb5hfeTXxSevptq4Q0dbrwwVzLJ1JaKbVVE8L0zG0rf6yZhUWf4UqbOfuuvU 5qk7nTTTYkDaduOWlONmnymxTRZLJZRAhph4psf/ERbp3V5XZdM/lGHPsM97Z8iaq6es 0TnTQ341S04xG5n2JpaEY86qLfBN5jk8aYLNEs2a49xlHXZN3dAAcmpF12KTLIiXkLS1 1r8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=mRBcSxdmyk/0X4RhkEisw7WceyZiGDUl+28BUWc39r8=; b=uVZInd7bgLAA8FDynSLPXjtM2GGWmoTUcjTaEGd8kptIe9wbqtx+4L0l8/olNHP/eC mQtnV8e8N4ObAkPNQDKH2VjE31QT/szEqfua9dR3mXV+SdYGpca9No36soGaefdbNezg Z7LpiCDstO8hcLezgV3UmYXExJXN8IuPtKTUAZXhXZ90NdSFipgQUlKD+1AvRYzWm8DB Yusjxm9r1dm5ArOlPjlDU4MfK9jS9w4itsS3tegmvvXnbrjiV63qzenqmVnCMnbUN6uX rnFpQKUouhGIfIijzTFIKzda+VIOqd4eHRGe30V7dyFh3cg5ENRxKzFL96G6gxgSegR7 HnZQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=X6YV4sMf; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b14si2271006pga.562.2017.08.24.01.25.20; Thu, 24 Aug 2017 01:25:20 -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; dkim=pass header.i=@linaro.org header.s=google header.b=X6YV4sMf; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751693AbdHXITE (ORCPT + 26 others); Thu, 24 Aug 2017 04:19:04 -0400 Received: from mail-pg0-f47.google.com ([74.125.83.47]:33909 "EHLO mail-pg0-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751484AbdHXISu (ORCPT ); Thu, 24 Aug 2017 04:18:50 -0400 Received: by mail-pg0-f47.google.com with SMTP id s14so13473498pgs.1 for ; Thu, 24 Aug 2017 01:18:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=mRBcSxdmyk/0X4RhkEisw7WceyZiGDUl+28BUWc39r8=; b=X6YV4sMfHWPqW8A90Xl/xIDYet4Q5Tbp95XIJG6oPWf1kEQA7sd1W57b2lIJeMxhrL eJyrusL5EOC4s/X0DwUbWdPuarEcbynt6+Hs7Gi8rtqUjFUvXZ2L3qNekHchHLVyfegS u6l3/5wLtcJxR2RBwKEvWrW6L+IBBVDNkSxp0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=mRBcSxdmyk/0X4RhkEisw7WceyZiGDUl+28BUWc39r8=; b=LGNuYQZGhMNvTbZWW6cvslQ4JidNRPqacTz/5QrPCbc7oMDdfBqku4PA2DBntlTC+O 6iz7lQouNVg+pplSLXU6eWYQF3ZIQin8b/WJD+o7GTzX+bFmY3ZQzuw7+ovACMqOGLiW gI6VYgkEs79AsUiUK0wP6MvajBeNW7crectZ04Ut9aSH9ZKyT3KoHRVmpWjUofTYbUP0 mNhxuw1uaucAD8J1rWVOwI19MG9MNb7MoEN8nQwNYrOHAugsu8evhQnpID8ak0lYC+Yf JaJ6LithuueDQkSO1msEwIEzMdIxKH03UZ5yp+cMsc4jqo0xgkWaYtElYNpDxC8Ac//L KYHQ== X-Gm-Message-State: AHYfb5inkZwGacYLjxkpCfTsNt/gpZECTpABJ+kGnqMVJhHVbLJOMYaA XkLoQnLcxxwxNBUL X-Received: by 10.99.117.68 with SMTP id f4mr5334183pgn.379.1503562729689; Thu, 24 Aug 2017 01:18:49 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id b7sm5872694pgr.11.2017.08.24.01.18.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 24 Aug 2017 01:18:49 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com, bauerman@linux.vnet.ibm.com, dhowells@redhat.com, vgoyal@redhat.com, herbert@gondor.apana.org.au, davem@davemloft.net, akpm@linux-foundation.org, mpe@ellerman.id.au, dyoung@redhat.com, bhe@redhat.com, arnd@arndb.de, ard.biesheuvel@linaro.org Cc: kexec@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, AKASHI Takahiro Subject: [PATCH 09/14] arm64: kexec_file: add sha256 digest check in purgatory Date: Thu, 24 Aug 2017 17:18:06 +0900 Message-Id: <20170824081811.19299-10-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20170824081811.19299-1-takahiro.akashi@linaro.org> References: <20170824081811.19299-1-takahiro.akashi@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Most of sha256 code is based on crypto/sha256-glue.c, particularly using non-neon version. Please note that we won't be able to re-use lib/mem*.S for purgatory because unaligned memory access is not allowed in purgatory where mmu is turned off. Since purgatory is not linked with the other part of kernel, care must be taken of selecting an appropriate set of compiler options in order to prevent undefined symbol references from being generated. Signed-off-by: AKASHI Takahiro Cc: Catalin Marinas Cc: Will Deacon Cc: Ard Biesheuvel --- arch/arm64/crypto/sha256-core.S_shipped | 2 + arch/arm64/purgatory/Makefile | 21 ++++++++- arch/arm64/purgatory/entry.S | 13 ++++++ arch/arm64/purgatory/purgatory.c | 20 +++++++++ arch/arm64/purgatory/sha256-core.S | 1 + arch/arm64/purgatory/sha256.c | 79 +++++++++++++++++++++++++++++++++ arch/arm64/purgatory/sha256.h | 1 + arch/arm64/purgatory/string.c | 32 +++++++++++++ arch/arm64/purgatory/string.h | 5 +++ 9 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 arch/arm64/purgatory/purgatory.c create mode 100644 arch/arm64/purgatory/sha256-core.S create mode 100644 arch/arm64/purgatory/sha256.c create mode 100644 arch/arm64/purgatory/sha256.h create mode 100644 arch/arm64/purgatory/string.c create mode 100644 arch/arm64/purgatory/string.h -- 2.14.1 diff --git a/arch/arm64/crypto/sha256-core.S_shipped b/arch/arm64/crypto/sha256-core.S_shipped index 3ce82cc860bc..9ce7419c9152 100644 --- a/arch/arm64/crypto/sha256-core.S_shipped +++ b/arch/arm64/crypto/sha256-core.S_shipped @@ -1210,6 +1210,7 @@ sha256_block_armv8: ret .size sha256_block_armv8,.-sha256_block_armv8 #endif +#ifndef __PURGATORY__ #ifdef __KERNEL__ .globl sha256_block_neon #endif @@ -2056,6 +2057,7 @@ sha256_block_neon: add sp,sp,#16*4+16 ret .size sha256_block_neon,.-sha256_block_neon +#endif #ifndef __KERNEL__ .comm OPENSSL_armcap_P,4,4 #endif diff --git a/arch/arm64/purgatory/Makefile b/arch/arm64/purgatory/Makefile index c2127a2cbd51..d9b38be31e0a 100644 --- a/arch/arm64/purgatory/Makefile +++ b/arch/arm64/purgatory/Makefile @@ -1,14 +1,33 @@ OBJECT_FILES_NON_STANDARD := y -purgatory-y := entry.o +purgatory-y := entry.o purgatory.o sha256.o sha256-core.o string.o targets += $(purgatory-y) PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) +# Purgatory is expected to be ET_REL, not an executable LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined \ -nostdlib -z nodefaultlib + targets += purgatory.ro +GCOV_PROFILE := n +KASAN_SANITIZE := n +KCOV_INSTRUMENT := n + +# Some kernel configurations may generate additional code containing +# undefined symbols, like _mcount for ftrace and __stack_chk_guard +# for stack-protector. Those should be removed from purgatory. + +CFLAGS_REMOVE_purgatory.o = -pg +CFLAGS_REMOVE_sha256.o = -pg +CFLAGS_REMOVE_string.o = -pg + +NO_PROTECTOR := $(call cc-option, -fno-stack-protector) +KBUILD_CFLAGS += $(NO_PROTECTOR) + +KBUILD_AFLAGS += -D__PURGATORY__ + $(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE $(call if_changed,ld) diff --git a/arch/arm64/purgatory/entry.S b/arch/arm64/purgatory/entry.S index bc4e6b3bf8a1..74d028b838bd 100644 --- a/arch/arm64/purgatory/entry.S +++ b/arch/arm64/purgatory/entry.S @@ -6,6 +6,11 @@ .text ENTRY(purgatory_start) + adr x19, .Lstack + mov sp, x19 + + bl purgatory + /* Start new image. */ ldr x17, arm64_kernel_entry ldr x0, arm64_dtb_addr @@ -15,6 +20,14 @@ ENTRY(purgatory_start) br x17 END(purgatory_start) +.ltorg + +.align 4 + .rept 256 + .quad 0 + .endr +.Lstack: + .data .align 3 diff --git a/arch/arm64/purgatory/purgatory.c b/arch/arm64/purgatory/purgatory.c new file mode 100644 index 000000000000..7fcbefa786bc --- /dev/null +++ b/arch/arm64/purgatory/purgatory.c @@ -0,0 +1,20 @@ +/* + * purgatory: Runs between two kernels + * + * Copyright (c) 2017 Linaro Limited + * Author: AKASHI Takahiro + */ + +#include "sha256.h" + +void purgatory(void) +{ + int ret; + + ret = verify_sha256_digest(); + if (ret) { + /* loop forever */ + for (;;) + ; + } +} diff --git a/arch/arm64/purgatory/sha256-core.S b/arch/arm64/purgatory/sha256-core.S new file mode 100644 index 000000000000..24f5ce25b61e --- /dev/null +++ b/arch/arm64/purgatory/sha256-core.S @@ -0,0 +1 @@ +#include "../crypto/sha256-core.S_shipped" diff --git a/arch/arm64/purgatory/sha256.c b/arch/arm64/purgatory/sha256.c new file mode 100644 index 000000000000..5d20d81767e3 --- /dev/null +++ b/arch/arm64/purgatory/sha256.c @@ -0,0 +1,79 @@ +#include +#include +#include + +/* + * Under KASAN, those are defined as un-instrumented version, __memxxx() + */ +#undef memcmp +#undef memcpy +#undef memset + +#include "string.h" +#include +#include +#include + +u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(.kexec-purgatory); +struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] + __section(.kexec-purgatory); + +asmlinkage void sha256_block_data_order(u32 *digest, const void *data, + unsigned int num_blks); + +static int sha256_init(struct shash_desc *desc) +{ + return sha256_base_init(desc); +} + +static int sha256_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + return sha256_base_do_update(desc, data, len, + (sha256_block_fn *)sha256_block_data_order); +} + +static int __sha256_base_finish(struct shash_desc *desc, u8 *out) +{ + /* we can't do crypto_shash_digestsize(desc->tfm) */ + unsigned int digest_size = 32; + struct sha256_state *sctx = shash_desc_ctx(desc); + __be32 *digest = (__be32 *)out; + int i; + + for (i = 0; digest_size > 0; i++, digest_size -= sizeof(__be32)) + put_unaligned_be32(sctx->state[i], digest++); + + *sctx = (struct sha256_state){}; + return 0; +} + +static int sha256_final(struct shash_desc *desc, u8 *out) +{ + sha256_base_do_finalize(desc, + (sha256_block_fn *)sha256_block_data_order); + + return __sha256_base_finish(desc, out); +} + +int verify_sha256_digest(void) +{ + char __sha256_desc[sizeof(struct shash_desc) + + sizeof(struct sha256_state)] CRYPTO_MINALIGN_ATTR; + struct shash_desc *desc = (struct shash_desc *)__sha256_desc; + struct kexec_sha_region *ptr, *end; + u8 digest[SHA256_DIGEST_SIZE]; + + sha256_init(desc); + + end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions); + for (ptr = purgatory_sha_regions; ptr < end; ptr++) + sha256_update(desc, (uint8_t *)(ptr->start), ptr->len); + + sha256_final(desc, digest); + + if (memcmp(digest, purgatory_sha256_digest, sizeof(digest))) + return 1; + + return 0; +} diff --git a/arch/arm64/purgatory/sha256.h b/arch/arm64/purgatory/sha256.h new file mode 100644 index 000000000000..54dc3c33c469 --- /dev/null +++ b/arch/arm64/purgatory/sha256.h @@ -0,0 +1 @@ +extern int verify_sha256_digest(void); diff --git a/arch/arm64/purgatory/string.c b/arch/arm64/purgatory/string.c new file mode 100644 index 000000000000..33233a210a65 --- /dev/null +++ b/arch/arm64/purgatory/string.c @@ -0,0 +1,32 @@ +#include + +void *memcpy(void *dst, const void *src, size_t len) +{ + int i; + + for (i = 0; i < len; i++) + ((u8 *)dst)[i] = ((u8 *)src)[i]; + + return NULL; +} + +void *memset(void *dst, int c, size_t len) +{ + int i; + + for (i = 0; i < len; i++) + ((u8 *)dst)[i] = (u8)c; + + return NULL; +} + +int memcmp(const void *src, const void *dst, size_t len) +{ + int i; + + for (i = 0; i < len; i++) + if (*(char *)src != *(char *)dst) + return 1; + + return 0; +} diff --git a/arch/arm64/purgatory/string.h b/arch/arm64/purgatory/string.h new file mode 100644 index 000000000000..cb5f68dd84ef --- /dev/null +++ b/arch/arm64/purgatory/string.h @@ -0,0 +1,5 @@ +#include + +int memcmp(const void *s1, const void *s2, size_t len); +void *memcpy(void *dst, const void *src, size_t len); +void *memset(void *dst, int c, size_t len);