diff options
Diffstat (limited to 'arch/riscv')
24 files changed, 151 insertions, 88 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index babc8a0d3d2e..ca3b5541ae93 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -31,6 +31,7 @@ config RISCV select GENERIC_SMP_IDLE_THREAD select GENERIC_ATOMIC64 if !64BIT select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_SECCOMP_FILTER select HAVE_ASM_MODVERSIONS select HAVE_MEMBLOCK_NODE_MAP select HAVE_DMA_CONTIGUOUS if MMU @@ -290,6 +291,19 @@ menu "Kernel features" source "kernel/Kconfig.hz" +config SECCOMP + bool "Enable seccomp to safely compute untrusted bytecode" + help + This kernel feature is useful for number crunching applications + that may need to compute untrusted bytecode during their + execution. By using pipes or other transports made available to + the process as file descriptors supporting the read/write + syscalls, it's possible to isolate those applications in + their own address space using seccomp. Once seccomp is + enabled via prctl(PR_SET_SECCOMP), it cannot be disabled + and the task is only allowed to execute a few safe syscalls + defined by each seccomp mode. + endmenu menu "Boot options" diff --git a/arch/riscv/boot/Makefile b/arch/riscv/boot/Makefile index 433ccbcabb23..a474f98ce4fa 100644 --- a/arch/riscv/boot/Makefile +++ b/arch/riscv/boot/Makefile @@ -29,6 +29,18 @@ loader.o: $(src)/loader.S $(obj)/Image $(obj)/loader: $(obj)/loader.o $(obj)/Image $(obj)/loader.lds FORCE $(Q)$(LD) -T $(obj)/loader.lds -o $@ $(obj)/loader.o +$(obj)/Image.bz2: $(obj)/Image FORCE + $(call if_changed,bzip2) + +$(obj)/Image.lz4: $(obj)/Image FORCE + $(call if_changed,lz4) + +$(obj)/Image.lzma: $(obj)/Image FORCE + $(call if_changed,lzma) + +$(obj)/Image.lzo: $(obj)/Image FORCE + $(call if_changed,lzo) + install: $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \ $(obj)/Image System.map "$(INSTALL_PATH)" diff --git a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi index afa43c7ea369..70a1891e7cd0 100644 --- a/arch/riscv/boot/dts/sifive/fu540-c000.dtsi +++ b/arch/riscv/boot/dts/sifive/fu540-c000.dtsi @@ -162,6 +162,13 @@ clocks = <&prci PRCI_CLK_TLCLK>; status = "disabled"; }; + dma: dma@3000000 { + compatible = "sifive,fu540-c000-pdma"; + reg = <0x0 0x3000000 0x0 0x8000>; + interrupt-parent = <&plic0>; + interrupts = <23 24 25 26 27 28 29 30>; + #dma-cells = <1>; + }; uart1: serial@10011000 { compatible = "sifive,fu540-c000-uart", "sifive,uart0"; reg = <0x0 0x10011000 0x0 0x1000>; diff --git a/arch/riscv/include/asm/asm-prototypes.h b/arch/riscv/include/asm/asm-prototypes.h index c9fecd120d18..dd62b691c443 100644 --- a/arch/riscv/include/asm/asm-prototypes.h +++ b/arch/riscv/include/asm/asm-prototypes.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _ASM_RISCV_PROTOTYPES_H +#define _ASM_RISCV_PROTOTYPES_H #include <linux/ftrace.h> #include <asm-generic/asm-prototypes.h> diff --git a/arch/riscv/include/asm/current.h b/arch/riscv/include/asm/current.h index 44dcf7fc15ee..dd973efe5d7c 100644 --- a/arch/riscv/include/asm/current.h +++ b/arch/riscv/include/asm/current.h @@ -7,8 +7,8 @@ */ -#ifndef __ASM_CURRENT_H -#define __ASM_CURRENT_H +#ifndef _ASM_RISCV_CURRENT_H +#define _ASM_RISCV_CURRENT_H #include <linux/bug.h> #include <linux/compiler.h> @@ -34,4 +34,4 @@ static __always_inline struct task_struct *get_current(void) #endif /* __ASSEMBLY__ */ -#endif /* __ASM_CURRENT_H */ +#endif /* _ASM_RISCV_CURRENT_H */ diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h index c6dcc5291f97..ace8a6e2d11d 100644 --- a/arch/riscv/include/asm/ftrace.h +++ b/arch/riscv/include/asm/ftrace.h @@ -1,6 +1,9 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (C) 2017 Andes Technology Corporation */ +#ifndef _ASM_RISCV_FTRACE_H +#define _ASM_RISCV_FTRACE_H + /* * The graph frame test is not possible if CONFIG_FRAME_POINTER is not enabled. * Check arch/riscv/kernel/mcount.S for detail. @@ -64,3 +67,5 @@ do { \ */ #define MCOUNT_INSN_SIZE 8 #endif + +#endif /* _ASM_RISCV_FTRACE_H */ diff --git a/arch/riscv/include/asm/futex.h b/arch/riscv/include/asm/futex.h index 418564b96dc4..fdfaf7f3df7c 100644 --- a/arch/riscv/include/asm/futex.h +++ b/arch/riscv/include/asm/futex.h @@ -4,8 +4,8 @@ * Copyright (c) 2018 Jim Wilson (jimw@sifive.com) */ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H +#ifndef _ASM_RISCV_FUTEX_H +#define _ASM_RISCV_FUTEX_H #include <linux/futex.h> #include <linux/uaccess.h> @@ -118,4 +118,4 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return ret; } -#endif /* _ASM_FUTEX_H */ +#endif /* _ASM_RISCV_FUTEX_H */ diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h index 7ecb7c6a57b1..1bb0cd04aec3 100644 --- a/arch/riscv/include/asm/hwcap.h +++ b/arch/riscv/include/asm/hwcap.h @@ -5,8 +5,8 @@ * Copyright (C) 2012 ARM Ltd. * Copyright (C) 2017 SiFive */ -#ifndef __ASM_HWCAP_H -#define __ASM_HWCAP_H +#ifndef _ASM_RISCV_HWCAP_H +#define _ASM_RISCV_HWCAP_H #include <uapi/asm/hwcap.h> @@ -23,4 +23,5 @@ enum { extern unsigned long elf_hwcap; #endif -#endif + +#endif /* _ASM_RISCV_HWCAP_H */ diff --git a/arch/riscv/include/asm/image.h b/arch/riscv/include/asm/image.h index 344db5244547..7b0f92ba0acc 100644 --- a/arch/riscv/include/asm/image.h +++ b/arch/riscv/include/asm/image.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_IMAGE_H -#define __ASM_IMAGE_H +#ifndef _ASM_RISCV_IMAGE_H +#define _ASM_RISCV_IMAGE_H #define RISCV_IMAGE_MAGIC "RISCV\0\0\0" #define RISCV_IMAGE_MAGIC2 "RSC\x05" @@ -62,4 +62,4 @@ struct riscv_image_header { u32 res4; }; #endif /* __ASSEMBLY__ */ -#endif /* __ASM_IMAGE_H */ +#endif /* _ASM_RISCV_IMAGE_H */ diff --git a/arch/riscv/include/asm/kprobes.h b/arch/riscv/include/asm/kprobes.h index 96e30ef637e8..56a98ea30731 100644 --- a/arch/riscv/include/asm/kprobes.h +++ b/arch/riscv/include/asm/kprobes.h @@ -6,9 +6,9 @@ * Copyright (C) 2017 SiFive */ -#ifndef _RISCV_KPROBES_H -#define _RISCV_KPROBES_H +#ifndef _ASM_RISCV_KPROBES_H +#define _ASM_RISCV_KPROBES_H #include <asm-generic/kprobes.h> -#endif /* _RISCV_KPROBES_H */ +#endif /* _ASM_RISCV_KPROBES_H */ diff --git a/arch/riscv/include/asm/mmiowb.h b/arch/riscv/include/asm/mmiowb.h index 5d7e3a2b4e3b..bb4091ff4a21 100644 --- a/arch/riscv/include/asm/mmiowb.h +++ b/arch/riscv/include/asm/mmiowb.h @@ -11,4 +11,4 @@ #include <asm-generic/mmiowb.h> -#endif /* ASM_RISCV_MMIOWB_H */ +#endif /* _ASM_RISCV_MMIOWB_H */ diff --git a/arch/riscv/include/asm/pci.h b/arch/riscv/include/asm/pci.h index 5ac8daa1cc36..1c473a1bd986 100644 --- a/arch/riscv/include/asm/pci.h +++ b/arch/riscv/include/asm/pci.h @@ -3,8 +3,8 @@ * Copyright (C) 2016 SiFive */ -#ifndef __ASM_RISCV_PCI_H -#define __ASM_RISCV_PCI_H +#ifndef _ASM_RISCV_PCI_H +#define _ASM_RISCV_PCI_H #include <linux/types.h> #include <linux/slab.h> @@ -34,4 +34,4 @@ static inline int pci_proc_domain(struct pci_bus *bus) } #endif /* CONFIG_PCI */ -#endif /* __ASM_PCI_H */ +#endif /* _ASM_RISCV_PCI_H */ diff --git a/arch/riscv/include/asm/seccomp.h b/arch/riscv/include/asm/seccomp.h new file mode 100644 index 000000000000..bf7744ee3b3d --- /dev/null +++ b/arch/riscv/include/asm/seccomp.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _ASM_SECCOMP_H +#define _ASM_SECCOMP_H + +#include <asm/unistd.h> + +#include <asm-generic/seccomp.h> + +#endif /* _ASM_SECCOMP_H */ diff --git a/arch/riscv/include/asm/sparsemem.h b/arch/riscv/include/asm/sparsemem.h index b58ba2d9ed6e..45a7018a8118 100644 --- a/arch/riscv/include/asm/sparsemem.h +++ b/arch/riscv/include/asm/sparsemem.h @@ -1,11 +1,11 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_SPARSEMEM_H -#define __ASM_SPARSEMEM_H +#ifndef _ASM_RISCV_SPARSEMEM_H +#define _ASM_RISCV_SPARSEMEM_H #ifdef CONFIG_SPARSEMEM #define MAX_PHYSMEM_BITS CONFIG_PA_BITS #define SECTION_SIZE_BITS 27 #endif /* CONFIG_SPARSEMEM */ -#endif /* __ASM_SPARSEMEM_H */ +#endif /* _ASM_RISCV_SPARSEMEM_H */ diff --git a/arch/riscv/include/asm/spinlock_types.h b/arch/riscv/include/asm/spinlock_types.h index 888cbf8e7111..f398e7638dd6 100644 --- a/arch/riscv/include/asm/spinlock_types.h +++ b/arch/riscv/include/asm/spinlock_types.h @@ -22,4 +22,4 @@ typedef struct { #define __ARCH_RW_LOCK_UNLOCKED { 0 } -#endif +#endif /* _ASM_RISCV_SPINLOCK_TYPES_H */ diff --git a/arch/riscv/include/asm/thread_info.h b/arch/riscv/include/asm/thread_info.h index 905372d7eeb8..1dd12a0cbb2b 100644 --- a/arch/riscv/include/asm/thread_info.h +++ b/arch/riscv/include/asm/thread_info.h @@ -75,6 +75,7 @@ struct thread_info { #define TIF_MEMDIE 5 /* is terminating due to OOM killer */ #define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing */ +#define TIF_SECCOMP 8 /* syscall secure computing */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) @@ -82,11 +83,13 @@ struct thread_info { #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) #define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) +#define _TIF_SECCOMP (1 << TIF_SECCOMP) #define _TIF_WORK_MASK \ (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED) #define _TIF_SYSCALL_WORK \ - (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) + (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT | \ + _TIF_SECCOMP) #endif /* _ASM_RISCV_THREAD_INFO_H */ diff --git a/arch/riscv/include/uapi/asm/elf.h b/arch/riscv/include/uapi/asm/elf.h index 644a00ce6e2e..d696d6610231 100644 --- a/arch/riscv/include/uapi/asm/elf.h +++ b/arch/riscv/include/uapi/asm/elf.h @@ -9,8 +9,8 @@ * (at your option) any later version. */ -#ifndef _UAPI_ASM_ELF_H -#define _UAPI_ASM_ELF_H +#ifndef _UAPI_ASM_RISCV_ELF_H +#define _UAPI_ASM_RISCV_ELF_H #include <asm/ptrace.h> @@ -95,4 +95,4 @@ typedef union __riscv_fp_state elf_fpregset_t; #define R_RISCV_32_PCREL 57 -#endif /* _UAPI_ASM_ELF_H */ +#endif /* _UAPI_ASM_RISCV_ELF_H */ diff --git a/arch/riscv/include/uapi/asm/hwcap.h b/arch/riscv/include/uapi/asm/hwcap.h index 4e7646077056..dee98ee28318 100644 --- a/arch/riscv/include/uapi/asm/hwcap.h +++ b/arch/riscv/include/uapi/asm/hwcap.h @@ -5,8 +5,8 @@ * Copyright (C) 2012 ARM Ltd. * Copyright (C) 2017 SiFive */ -#ifndef __UAPI_ASM_HWCAP_H -#define __UAPI_ASM_HWCAP_H +#ifndef _UAPI_ASM_RISCV_HWCAP_H +#define _UAPI_ASM_RISCV_HWCAP_H /* * Linux saves the floating-point registers according to the ISA Linux is @@ -22,4 +22,4 @@ #define COMPAT_HWCAP_ISA_D (1 << ('D' - 'A')) #define COMPAT_HWCAP_ISA_C (1 << ('C' - 'A')) -#endif +#endif /* _UAPI_ASM_RISCV_HWCAP_H */ diff --git a/arch/riscv/include/uapi/asm/ucontext.h b/arch/riscv/include/uapi/asm/ucontext.h index 411dd7b52ed6..44eb993950e5 100644 --- a/arch/riscv/include/uapi/asm/ucontext.h +++ b/arch/riscv/include/uapi/asm/ucontext.h @@ -5,8 +5,8 @@ * * This file was copied from arch/arm64/include/uapi/asm/ucontext.h */ -#ifndef _UAPI__ASM_UCONTEXT_H -#define _UAPI__ASM_UCONTEXT_H +#ifndef _UAPI_ASM_RISCV_UCONTEXT_H +#define _UAPI_ASM_RISCV_UCONTEXT_H #include <linux/types.h> @@ -31,4 +31,4 @@ struct ucontext { struct sigcontext uc_mcontext; }; -#endif /* _UAPI__ASM_UCONTEXT_H */ +#endif /* _UAPI_ASM_RISCV_UCONTEXT_H */ diff --git a/arch/riscv/kernel/cpu.c b/arch/riscv/kernel/cpu.c index 7da3c6a93abd..40a3c442ac5f 100644 --- a/arch/riscv/kernel/cpu.c +++ b/arch/riscv/kernel/cpu.c @@ -46,51 +46,12 @@ int riscv_of_processor_hartid(struct device_node *node) #ifdef CONFIG_PROC_FS -static void print_isa(struct seq_file *f, const char *orig_isa) +static void print_isa(struct seq_file *f, const char *isa) { - static const char *ext = "mafdcsu"; - const char *isa = orig_isa; - const char *e; - - /* - * Linux doesn't support rv32e or rv128i, and we only support booting - * kernels on harts with the same ISA that the kernel is compiled for. - */ -#if defined(CONFIG_32BIT) - if (strncmp(isa, "rv32i", 5) != 0) - return; -#elif defined(CONFIG_64BIT) - if (strncmp(isa, "rv64i", 5) != 0) - return; -#endif - - /* Print the base ISA, as we already know it's legal. */ + /* Print the entire ISA as it is */ seq_puts(f, "isa\t\t: "); - seq_write(f, isa, 5); - isa += 5; - - /* - * Check the rest of the ISA string for valid extensions, printing those - * we find. RISC-V ISA strings define an order, so we only print the - * extension bits when they're in order. Hide the supervisor (S) - * extension from userspace as it's not accessible from there. - */ - for (e = ext; *e != '\0'; ++e) { - if (isa[0] == e[0]) { - if (isa[0] != 's') - seq_write(f, isa, 1); - - isa++; - } - } + seq_write(f, isa, strlen(isa)); seq_puts(f, "\n"); - - /* - * If we were given an unsupported ISA in the device tree then print - * a bit of info describing what went wrong. - */ - if (isa[0] != '\0') - pr_info("unsupported ISA \"%s\" in device tree\n", orig_isa); } static void print_mmu(struct seq_file *f, const char *mmu_type) diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index 89aecba63f49..a1349ca64669 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -228,8 +228,25 @@ check_syscall_nr: /* Check to make sure we don't jump to a bogus syscall number. */ li t0, __NR_syscalls la s0, sys_ni_syscall - /* Syscall number held in a7 */ - bgeu a7, t0, 1f + /* + * The tracer can change syscall number to valid/invalid value. + * We use syscall_set_nr helper in syscall_trace_enter thus we + * cannot trust the current value in a7 and have to reload from + * the current task pt_regs. + */ + REG_L a7, PT_A7(sp) + /* + * Syscall number held in a7. + * If syscall number is above allowed value, redirect to ni_syscall. + */ + bge a7, t0, 1f + /* + * Check if syscall is rejected by tracer or seccomp, i.e., a7 == -1. + * If yes, we pretend it was executed. + */ + li t1, -1 + beq a7, t1, ret_from_syscall_rejected + /* Call syscall */ la s0, sys_call_table slli t0, a7, RISCV_LGPTR add s0, s0, t0 @@ -240,6 +257,12 @@ check_syscall_nr: ret_from_syscall: /* Set user a0 to kernel a0 */ REG_S a0, PT_A0(sp) + /* + * We didn't execute the actual syscall. + * Seccomp already set return value for the current task pt_regs. + * (If it was configured with SECCOMP_RET_ERRNO/TRACE) + */ +ret_from_syscall_rejected: /* Trace syscalls, but only if requested by the user. */ REG_L t0, TASK_TI_FLAGS(tp) andi t0, t0, _TIF_SYSCALL_WORK diff --git a/arch/riscv/kernel/ptrace.c b/arch/riscv/kernel/ptrace.c index 1252113ef8b2..0f84628b9385 100644 --- a/arch/riscv/kernel/ptrace.c +++ b/arch/riscv/kernel/ptrace.c @@ -154,6 +154,16 @@ __visible void do_syscall_trace_enter(struct pt_regs *regs) if (tracehook_report_syscall_entry(regs)) syscall_set_nr(current, regs, -1); + /* + * Do the secure computing after ptrace; failures should be fast. + * If this fails we might have return value in a0 from seccomp + * (via SECCOMP_RET_ERRNO/TRACE). + */ + if (secure_computing(NULL) == -1) { + syscall_set_nr(current, regs, -1); + return; + } + #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) trace_sys_enter(regs, syscall_get_nr(current, regs)); diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 6322ec82ec1d..b2fe9d1be833 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -274,7 +274,6 @@ static void __init create_pmd_mapping(pmd_t *pmdp, #define get_pgd_next_virt(__pa) get_pmd_virt(__pa) #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ create_pmd_mapping(__nextp, __va, __pa, __sz, __prot) -#define PTE_PARENT_SIZE PMD_SIZE #define fixmap_pgd_next fixmap_pmd #else #define pgd_next_t pte_t @@ -282,7 +281,6 @@ static void __init create_pmd_mapping(pmd_t *pmdp, #define get_pgd_next_virt(__pa) get_pte_virt(__pa) #define create_pgd_next_mapping(__nextp, __va, __pa, __sz, __prot) \ create_pte_mapping(__nextp, __va, __pa, __sz, __prot) -#define PTE_PARENT_SIZE PGDIR_SIZE #define fixmap_pgd_next fixmap_pte #endif @@ -315,14 +313,11 @@ static void __init create_pgd_mapping(pgd_t *pgdp, static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size) { - uintptr_t map_size = PAGE_SIZE; + /* Upgrade to PMD_SIZE mappings whenever possible */ + if ((base & (PMD_SIZE - 1)) || (size & (PMD_SIZE - 1))) + return PAGE_SIZE; - /* Upgrade to PMD/PGDIR mappings whenever possible */ - if (!(base & (PTE_PARENT_SIZE - 1)) && - !(size & (PTE_PARENT_SIZE - 1))) - map_size = PTE_PARENT_SIZE; - - return map_size; + return PMD_SIZE; } /* diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c index 24cd33d2c48f..720b443c4528 100644 --- a/arch/riscv/mm/tlbflush.c +++ b/arch/riscv/mm/tlbflush.c @@ -2,6 +2,7 @@ #include <linux/mm.h> #include <linux/smp.h> +#include <linux/sched.h> #include <asm/sbi.h> void flush_tlb_all(void) @@ -9,13 +10,33 @@ void flush_tlb_all(void) sbi_remote_sfence_vma(NULL, 0, -1); } +/* + * This function must not be called with cmask being null. + * Kernel may panic if cmask is NULL. + */ static void __sbi_tlb_flush_range(struct cpumask *cmask, unsigned long start, unsigned long size) { struct cpumask hmask; + unsigned int cpuid; - riscv_cpuid_to_hartid_mask(cmask, &hmask); - sbi_remote_sfence_vma(hmask.bits, start, size); + if (cpumask_empty(cmask)) + return; + + cpuid = get_cpu(); + + if (cpumask_any_but(cmask, cpuid) >= nr_cpu_ids) { + /* local cpu is the only cpu present in cpumask */ + if (size <= PAGE_SIZE) + local_flush_tlb_page(start); + else + local_flush_tlb_all(); + } else { + riscv_cpuid_to_hartid_mask(cmask, &hmask); + sbi_remote_sfence_vma(cpumask_bits(&hmask), start, size); + } + + put_cpu(); } void flush_tlb_mm(struct mm_struct *mm) |