diff options
-rw-r--r-- | Documentation/features/seccomp/seccomp-filter/arch-support.txt | 2 | ||||
-rw-r--r-- | arch/xtensa/Kconfig | 16 | ||||
-rw-r--r-- | arch/xtensa/boot/Makefile | 12 | ||||
-rw-r--r-- | arch/xtensa/boot/boot-elf/Makefile | 5 | ||||
-rw-r--r-- | arch/xtensa/boot/boot-redboot/Makefile | 5 | ||||
-rw-r--r-- | arch/xtensa/include/asm/Kbuild | 1 | ||||
-rw-r--r-- | arch/xtensa/include/asm/initialize_mmu.h | 2 | ||||
-rw-r--r-- | arch/xtensa/include/asm/thread_info.h | 11 | ||||
-rw-r--r-- | arch/xtensa/include/uapi/asm/ptrace.h | 3 | ||||
-rw-r--r-- | arch/xtensa/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/xtensa/kernel/entry.S | 11 | ||||
-rw-r--r-- | arch/xtensa/kernel/perf_event.c | 2 | ||||
-rw-r--r-- | arch/xtensa/kernel/ptrace.c | 14 | ||||
-rw-r--r-- | tools/testing/selftests/seccomp/seccomp_bpf.c | 16 |
14 files changed, 87 insertions, 16 deletions
diff --git a/Documentation/features/seccomp/seccomp-filter/arch-support.txt b/Documentation/features/seccomp/seccomp-filter/arch-support.txt index f54ddfc06a12..c688aba22a8d 100644 --- a/Documentation/features/seccomp/seccomp-filter/arch-support.txt +++ b/Documentation/features/seccomp/seccomp-filter/arch-support.txt @@ -29,5 +29,5 @@ | sparc: | TODO | | um: | ok | | x86: | ok | - | xtensa: | TODO | + | xtensa: | ok | ----------------------- diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index b71ba910d92f..e997e0119c02 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -21,8 +21,10 @@ config XTENSA select GENERIC_PCI_IOMAP select GENERIC_SCHED_CLOCK select GENERIC_STRNCPY_FROM_USER if KASAN + select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL + select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK select HAVE_DEBUG_KMEMLEAK select HAVE_DMA_CONTIGUOUS @@ -215,6 +217,20 @@ config HOTPLUG_CPU Say N if you want to disable CPU hotplug. +config SECCOMP + bool + prompt "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. + config FAST_SYSCALL_XTENSA bool "Enable fast atomic syscalls" default n diff --git a/arch/xtensa/boot/Makefile b/arch/xtensa/boot/Makefile index 1a14d38d9b33..f6bb352f94b4 100644 --- a/arch/xtensa/boot/Makefile +++ b/arch/xtensa/boot/Makefile @@ -17,6 +17,8 @@ BIG_ENDIAN := $(shell echo __XTENSA_EB__ | $(CC) -E - | grep -v "\#") export BIG_ENDIAN subdir-y := lib +targets += vmlinux.bin vmlinux.bin.gz +targets += uImage xipImage # Subdirs for the boot loader(s) @@ -35,19 +37,19 @@ boot-elf boot-redboot: $(addprefix $(obj)/,$(subdir-y)) OBJCOPYFLAGS = --strip-all -R .comment -R .notes -O binary -vmlinux.bin: vmlinux FORCE +$(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) -vmlinux.bin.gz: vmlinux.bin FORCE +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE $(call if_changed,gzip) -boot-elf: vmlinux.bin -boot-redboot: vmlinux.bin.gz +boot-elf: $(obj)/vmlinux.bin +boot-redboot: $(obj)/vmlinux.bin.gz UIMAGE_LOADADDR = $(CONFIG_KERNEL_LOAD_ADDRESS) UIMAGE_COMPRESSION = gzip -$(obj)/uImage: vmlinux.bin.gz FORCE +$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE $(call if_changed,uimage) $(Q)$(kecho) ' Kernel: $@ is ready' diff --git a/arch/xtensa/boot/boot-elf/Makefile b/arch/xtensa/boot/boot-elf/Makefile index 12ae1e91cb75..0ebc9827f7e5 100644 --- a/arch/xtensa/boot/boot-elf/Makefile +++ b/arch/xtensa/boot/boot-elf/Makefile @@ -15,12 +15,13 @@ export CPPFLAGS_boot.lds += -P -C export KBUILD_AFLAGS += -mtext-section-literals boot-y := bootstrap.o +targets += $(boot-y) boot.lds OBJS := $(addprefix $(obj)/,$(boot-y)) -$(obj)/Image.o: vmlinux.bin $(OBJS) +$(obj)/Image.o: $(obj)/../vmlinux.bin $(OBJS) $(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section image=vmlinux.bin \ + --add-section image=$< \ --set-section-flags image=contents,alloc,load,load,data \ $(OBJS) $@ diff --git a/arch/xtensa/boot/boot-redboot/Makefile b/arch/xtensa/boot/boot-redboot/Makefile index 8632473ad319..07cb24afedc2 100644 --- a/arch/xtensa/boot/boot-redboot/Makefile +++ b/arch/xtensa/boot/boot-redboot/Makefile @@ -13,15 +13,16 @@ endif LD_ARGS = -T $(srctree)/$(obj)/boot.ld boot-y := bootstrap.o +targets += $(boot-y) OBJS := $(addprefix $(obj)/,$(boot-y)) LIBS := arch/xtensa/boot/lib/lib.a arch/xtensa/lib/lib.a LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) -$(obj)/zImage.o: vmlinux.bin.gz $(OBJS) +$(obj)/zImage.o: $(obj)/../vmlinux.bin.gz $(OBJS) $(Q)$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \ - --add-section image=vmlinux.bin.gz \ + --add-section image=$< \ --set-section-flags image=contents,alloc,load,load,data \ $(OBJS) $@ diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 9718e9593564..c59c42a1221a 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild @@ -7,4 +7,5 @@ generic-y += mcs_spinlock.h generic-y += param.h generic-y += qrwlock.h generic-y += qspinlock.h +generic-y += seccomp.h generic-y += user.h diff --git a/arch/xtensa/include/asm/initialize_mmu.h b/arch/xtensa/include/asm/initialize_mmu.h index 9ee0c1d004f9..05cb13dfe6f4 100644 --- a/arch/xtensa/include/asm/initialize_mmu.h +++ b/arch/xtensa/include/asm/initialize_mmu.h @@ -6,7 +6,7 @@ * For the new V3 MMU we remap the TLB from virtual == physical * to the standard Linux mapping used in earlier MMU's. * - * The the MMU we also support a new configuration register that + * For the MMU we also support a new configuration register that * specifies how the S32C1I instruction operates with the cache * controller. * diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h index f092cc3f4e66..6acbbe0d87d3 100644 --- a/arch/xtensa/include/asm/thread_info.h +++ b/arch/xtensa/include/asm/thread_info.h @@ -55,6 +55,10 @@ struct thread_info { mm_segment_t addr_limit; /* thread address space */ unsigned long cpenable; +#if XCHAL_HAVE_EXCLUSIVE + /* result of the most recent exclusive store */ + unsigned long atomctl8; +#endif /* Allocate storage for extra user states and coprocessor states. */ #if XTENSA_HAVE_COPROCESSORS @@ -111,15 +115,20 @@ static inline struct thread_info *current_thread_info(void) #define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */ #define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ #define TIF_DB_DISABLED 8 /* debug trap disabled for syscall */ +#define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ +#define TIF_SECCOMP 10 /* secure computing */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) #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_SYSCALL_TRACE | _TIF_SINGLESTEP | \ - _TIF_SYSCALL_TRACEPOINT) + _TIF_SYSCALL_TRACEPOINT | \ + _TIF_SYSCALL_AUDIT | _TIF_SECCOMP) #define THREAD_SIZE KERNEL_STACK_SIZE #define THREAD_SIZE_ORDER (KERNEL_STACK_SHIFT - PAGE_SHIFT) diff --git a/arch/xtensa/include/uapi/asm/ptrace.h b/arch/xtensa/include/uapi/asm/ptrace.h index 2ec0f9100a06..50db3e0a6341 100644 --- a/arch/xtensa/include/uapi/asm/ptrace.h +++ b/arch/xtensa/include/uapi/asm/ptrace.h @@ -50,7 +50,8 @@ struct user_pt_regs { __u32 windowstart; __u32 windowbase; __u32 threadptr; - __u32 reserved[7 + 48]; + __u32 syscall; + __u32 reserved[6 + 48]; __u32 a[64]; }; diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index 33a257b33723..dc5c83cad9be 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c @@ -93,6 +93,9 @@ int main(void) DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra)); DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp)); DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable)); +#if XCHAL_HAVE_EXCLUSIVE + DEFINE(THREAD_ATOMCTL8, offsetof (struct thread_info, atomctl8)); +#endif #if XTENSA_HAVE_COPROCESSORS DEFINE(THREAD_XTREGS_CP0, offsetof(struct thread_info, xtregs_cp.cp0)); DEFINE(THREAD_XTREGS_CP1, offsetof(struct thread_info, xtregs_cp.cp1)); diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 98515c24d9b2..703cf6205efe 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -374,6 +374,11 @@ common_exception: s32i a2, a1, PT_LCOUNT #endif +#if XCHAL_HAVE_EXCLUSIVE + /* Clear exclusive access monitor set by interrupted code */ + clrex +#endif + /* It is now save to restore the EXC_TABLE_FIXUP variable. */ rsr a2, exccause @@ -2020,6 +2025,12 @@ ENTRY(_switch_to) s32i a3, a4, THREAD_CPENABLE #endif +#if XCHAL_HAVE_EXCLUSIVE + l32i a3, a5, THREAD_ATOMCTL8 + getex a3 + s32i a3, a4, THREAD_ATOMCTL8 +#endif + /* Flush register file. */ spill_registers_kernel diff --git a/arch/xtensa/kernel/perf_event.c b/arch/xtensa/kernel/perf_event.c index 99fcd63ce597..a0d05c8598d0 100644 --- a/arch/xtensa/kernel/perf_event.c +++ b/arch/xtensa/kernel/perf_event.c @@ -399,7 +399,7 @@ static struct pmu xtensa_pmu = { .read = xtensa_pmu_read, }; -static int xtensa_pmu_setup(int cpu) +static int xtensa_pmu_setup(unsigned int cpu) { unsigned i; diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index b4c07bd890fe..ce4a32bd2294 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -12,6 +12,7 @@ * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca> */ +#include <linux/audit.h> #include <linux/errno.h> #include <linux/hw_breakpoint.h> #include <linux/kernel.h> @@ -21,6 +22,7 @@ #include <linux/regset.h> #include <linux/sched.h> #include <linux/sched/task_stack.h> +#include <linux/seccomp.h> #include <linux/security.h> #include <linux/signal.h> #include <linux/smp.h> @@ -51,6 +53,7 @@ static int gpr_get(struct task_struct *target, .threadptr = regs->threadptr, .windowbase = regs->windowbase, .windowstart = regs->windowstart, + .syscall = regs->syscall, }; memcpy(newregs.a, @@ -90,6 +93,9 @@ static int gpr_set(struct task_struct *target, regs->sar = newregs.sar; regs->threadptr = newregs.threadptr; + if (newregs.syscall) + regs->syscall = newregs.syscall; + if (newregs.windowbase != regs->windowbase || newregs.windowstart != regs->windowstart) { u32 rotws, wmask; @@ -554,7 +560,8 @@ int do_syscall_trace_enter(struct pt_regs *regs) return 0; } - if (regs->syscall == NO_SYSCALL) { + if (regs->syscall == NO_SYSCALL || + secure_computing() == -1) { do_syscall_trace_leave(regs); return 0; } @@ -562,6 +569,9 @@ int do_syscall_trace_enter(struct pt_regs *regs) if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) trace_sys_enter(regs, syscall_get_nr(current, regs)); + audit_syscall_entry(regs->syscall, regs->areg[6], + regs->areg[3], regs->areg[4], + regs->areg[5]); return 1; } @@ -569,6 +579,8 @@ void do_syscall_trace_leave(struct pt_regs *regs) { int step; + audit_syscall_exit(regs); + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) trace_sys_exit(regs, regs_return_value(regs)); diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c index 5267b9fb7c0f..06bd5901be74 100644 --- a/tools/testing/selftests/seccomp/seccomp_bpf.c +++ b/tools/testing/selftests/seccomp/seccomp_bpf.c @@ -129,6 +129,8 @@ struct seccomp_data { # define __NR_seccomp 358 # elif defined(__s390__) # define __NR_seccomp 348 +# elif defined(__xtensa__) +# define __NR_seccomp 337 # else # warning "seccomp syscall number unknown for this architecture" # define __NR_seccomp 0xffff @@ -1699,6 +1701,14 @@ TEST_F(TRACE_poke, getpid_runs_normally) # define SYSCALL_SYSCALL_NUM regs[4] # define SYSCALL_RET regs[2] # define SYSCALL_NUM_RET_SHARE_REG +#elif defined(__xtensa__) +# define ARCH_REGS struct user_pt_regs +# define SYSCALL_NUM syscall +/* + * On xtensa syscall return value is in the register + * a2 of the current window which is not fixed. + */ +#define SYSCALL_RET(reg) a[(reg).windowbase * 4 + 2] #else # error "Do not know how to find your architecture's registers and syscalls" #endif @@ -1770,7 +1780,8 @@ void change_syscall(struct __test_metadata *_metadata, EXPECT_EQ(0, ret) {} #if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ - defined(__s390__) || defined(__hppa__) || defined(__riscv) + defined(__s390__) || defined(__hppa__) || defined(__riscv) || \ + defined(__xtensa__) { regs.SYSCALL_NUM = syscall; } @@ -1813,6 +1824,9 @@ void change_syscall(struct __test_metadata *_metadata, if (syscall == -1) #ifdef SYSCALL_NUM_RET_SHARE_REG TH_LOG("Can't modify syscall return on this architecture"); + +#elif defined(__xtensa__) + regs.SYSCALL_RET(regs) = result; #else regs.SYSCALL_RET = result; #endif |