Skip to content

Commit 736e30a

Browse files
Li Zhengyupalmer-dabbelt
authored andcommitted
RISC-V: Add purgatory
This patch adds purgatory, the name and concept have been taken from kexec-tools. Purgatory runs between two kernels, and do verify sha256 hash to ensure the kernel to jump to is fine and has not been corrupted after loading. Makefile is modified based on x86 platform. Signed-off-by: Li Zhengyu <lizhengyu3@huawei.com> Link: https://lore.kernel.org/r/20220408100914.150110-6-lizhengyu3@huawei.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent 8acea45 commit 736e30a

6 files changed

Lines changed: 199 additions & 0 deletions

File tree

arch/riscv/Kbuild

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@
33
obj-y += kernel/ mm/ net/
44
obj-$(CONFIG_BUILTIN_DTB) += boot/dts/
55

6+
obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += purgatory/
7+
68
# for cleaning
79
subdir- += boot

arch/riscv/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,12 @@ config KEXEC_FILE
397397

398398
If you don't know what to do here, say Y.
399399

400+
config ARCH_HAS_KEXEC_PURGATORY
401+
def_bool KEXEC_FILE
402+
select BUILD_BIN2C
403+
depends on CRYPTO=y
404+
depends on CRYPTO_SHA256=y
405+
400406
config CRASH_DUMP
401407
bool "Build kdump crash kernel"
402408
help

arch/riscv/purgatory/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
purgatory.chk
3+
purgatory.ro
4+
kexec-purgatory.c

arch/riscv/purgatory/Makefile

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
OBJECT_FILES_NON_STANDARD := y
3+
4+
purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o
5+
6+
targets += $(purgatory-y)
7+
PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
8+
9+
$(obj)/string.o: $(srctree)/lib/string.c FORCE
10+
$(call if_changed_rule,cc_o_c)
11+
12+
$(obj)/ctype.o: $(srctree)/lib/ctype.c FORCE
13+
$(call if_changed_rule,cc_o_c)
14+
15+
$(obj)/memcpy.o: $(srctree)/arch/riscv/lib/memcpy.S FORCE
16+
$(call if_changed_rule,as_o_S)
17+
18+
$(obj)/memset.o: $(srctree)/arch/riscv/lib/memset.S FORCE
19+
$(call if_changed_rule,as_o_S)
20+
21+
$(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE
22+
$(call if_changed_rule,cc_o_c)
23+
24+
CFLAGS_sha256.o := -D__DISABLE_EXPORTS
25+
CFLAGS_string.o := -D__DISABLE_EXPORTS
26+
CFLAGS_ctype.o := -D__DISABLE_EXPORTS
27+
28+
# When linking purgatory.ro with -r unresolved symbols are not checked,
29+
# also link a purgatory.chk binary without -r to check for unresolved symbols.
30+
PURGATORY_LDFLAGS := -e purgatory_start -z nodefaultlib
31+
LDFLAGS_purgatory.ro := -r $(PURGATORY_LDFLAGS)
32+
LDFLAGS_purgatory.chk := $(PURGATORY_LDFLAGS)
33+
targets += purgatory.ro purgatory.chk
34+
35+
# Sanitizer, etc. runtimes are unavailable and cannot be linked here.
36+
GCOV_PROFILE := n
37+
KASAN_SANITIZE := n
38+
UBSAN_SANITIZE := n
39+
KCSAN_SANITIZE := n
40+
KCOV_INSTRUMENT := n
41+
42+
# These are adjustments to the compiler flags used for objects that
43+
# make up the standalone purgatory.ro
44+
45+
PURGATORY_CFLAGS_REMOVE := -mcmodel=kernel
46+
PURGATORY_CFLAGS := -mcmodel=medany -ffreestanding -fno-zero-initialized-in-bss
47+
PURGATORY_CFLAGS += $(DISABLE_STACKLEAK_PLUGIN) -DDISABLE_BRANCH_PROFILING
48+
PURGATORY_CFLAGS += -fno-stack-protector -g0
49+
50+
# Default KBUILD_CFLAGS can have -pg option set when FTRACE is enabled. That
51+
# in turn leaves some undefined symbols like __fentry__ in purgatory and not
52+
# sure how to relocate those.
53+
ifdef CONFIG_FUNCTION_TRACER
54+
PURGATORY_CFLAGS_REMOVE += $(CC_FLAGS_FTRACE)
55+
endif
56+
57+
ifdef CONFIG_STACKPROTECTOR
58+
PURGATORY_CFLAGS_REMOVE += -fstack-protector
59+
endif
60+
61+
ifdef CONFIG_STACKPROTECTOR_STRONG
62+
PURGATORY_CFLAGS_REMOVE += -fstack-protector-strong
63+
endif
64+
65+
CFLAGS_REMOVE_purgatory.o += $(PURGATORY_CFLAGS_REMOVE)
66+
CFLAGS_purgatory.o += $(PURGATORY_CFLAGS)
67+
68+
CFLAGS_REMOVE_sha256.o += $(PURGATORY_CFLAGS_REMOVE)
69+
CFLAGS_sha256.o += $(PURGATORY_CFLAGS)
70+
71+
CFLAGS_REMOVE_string.o += $(PURGATORY_CFLAGS_REMOVE)
72+
CFLAGS_string.o += $(PURGATORY_CFLAGS)
73+
74+
CFLAGS_REMOVE_ctype.o += $(PURGATORY_CFLAGS_REMOVE)
75+
CFLAGS_ctype.o += $(PURGATORY_CFLAGS)
76+
77+
AFLAGS_REMOVE_entry.o += -Wa,-gdwarf-2
78+
AFLAGS_REMOVE_memcpy.o += -Wa,-gdwarf-2
79+
AFLAGS_REMOVE_memset.o += -Wa,-gdwarf-2
80+
81+
$(obj)/purgatory.ro: $(PURGATORY_OBJS) FORCE
82+
$(call if_changed,ld)
83+
84+
$(obj)/purgatory.chk: $(obj)/purgatory.ro FORCE
85+
$(call if_changed,ld)
86+
87+
targets += kexec-purgatory.c
88+
89+
quiet_cmd_bin2c = BIN2C $@
90+
cmd_bin2c = $(objtree)/scripts/bin2c kexec_purgatory < $< > $@
91+
92+
$(obj)/kexec-purgatory.c: $(obj)/purgatory.ro $(obj)/purgatory.chk FORCE
93+
$(call if_changed,bin2c)
94+
95+
obj-$(CONFIG_ARCH_HAS_KEXEC_PURGATORY) += kexec-purgatory.o

arch/riscv/purgatory/entry.S

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* purgatory: Runs between two kernels
4+
*
5+
* Copyright (C) 2022 Huawei Technologies Co, Ltd.
6+
*
7+
* Author: Li Zhengyu (lizhengyu3@huawei.com)
8+
*
9+
*/
10+
11+
.macro size, sym:req
12+
.size \sym, . - \sym
13+
.endm
14+
15+
.text
16+
17+
.globl purgatory_start
18+
purgatory_start:
19+
20+
lla sp, .Lstack
21+
mv s0, a0 /* The hartid of the current hart */
22+
mv s1, a1 /* Phys address of the FDT image */
23+
24+
jal purgatory
25+
26+
/* Start new image. */
27+
mv a0, s0
28+
mv a1, s1
29+
ld a2, riscv_kernel_entry
30+
jr a2
31+
32+
size purgatory_start
33+
34+
.align 4
35+
.rept 256
36+
.quad 0
37+
.endr
38+
.Lstack:
39+
40+
.data
41+
42+
.globl riscv_kernel_entry
43+
riscv_kernel_entry:
44+
.quad 0
45+
size riscv_kernel_entry
46+
47+
.end

arch/riscv/purgatory/purgatory.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* purgatory: Runs between two kernels
4+
*
5+
* Copyright (C) 2022 Huawei Technologies Co, Ltd.
6+
*
7+
* Author: Li Zhengyu (lizhengyu3@huawei.com)
8+
*
9+
*/
10+
11+
#include <linux/purgatory.h>
12+
#include <linux/kernel.h>
13+
#include <linux/string.h>
14+
#include <asm/string.h>
15+
16+
u8 purgatory_sha256_digest[SHA256_DIGEST_SIZE] __section(".kexec-purgatory");
17+
18+
struct kexec_sha_region purgatory_sha_regions[KEXEC_SEGMENT_MAX] __section(".kexec-purgatory");
19+
20+
static int verify_sha256_digest(void)
21+
{
22+
struct kexec_sha_region *ptr, *end;
23+
struct sha256_state ss;
24+
u8 digest[SHA256_DIGEST_SIZE];
25+
26+
sha256_init(&ss);
27+
end = purgatory_sha_regions + ARRAY_SIZE(purgatory_sha_regions);
28+
for (ptr = purgatory_sha_regions; ptr < end; ptr++)
29+
sha256_update(&ss, (uint8_t *)(ptr->start), ptr->len);
30+
sha256_final(&ss, digest);
31+
if (memcmp(digest, purgatory_sha256_digest, sizeof(digest)) != 0)
32+
return 1;
33+
return 0;
34+
}
35+
36+
/* workaround for a warning with -Wmissing-prototypes */
37+
void purgatory(void);
38+
39+
void purgatory(void)
40+
{
41+
if (verify_sha256_digest())
42+
for (;;)
43+
/* loop forever */
44+
;
45+
}

0 commit comments

Comments
 (0)