Commit 79b7e67b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML updates from Richard Weinberger:

 - KASAN support for x86_64

 - noreboot command line option, just like qemu's -no-reboot

 - Various fixes and cleanups

* tag 'for-linus-5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: include sys/types.h for size_t
  um: Replace to_phys() and to_virt() with less generic function names
  um: Add missing apply_returns()
  um: add "noreboot" command line option for PANIC_TIMEOUT=-1 setups
  um: include linux/stddef.h for __always_inline
  UML: add support for KASAN under x86_64
  mm: Add PAGE_ALIGN_DOWN macro
  um: random: Don't initialise hwrng struct with zero
  um: remove unused mm_copy_segments
  um: remove unused variable
  um: Remove straying parenthesis
  um: x86: print RIP with symbol
  arch: um: Fix build for statically linked UML w/ constructors
  x86/um: Kconfig: Fix indentation
  um/drivers: Kconfig: Fix indentation
  um: Kconfig: Fix indentation
parents 4d5398a3 af3e1610
...@@ -12,6 +12,8 @@ config UML ...@@ -12,6 +12,8 @@ config UML
select ARCH_HAS_STRNLEN_USER select ARCH_HAS_STRNLEN_USER
select ARCH_NO_PREEMPT select ARCH_NO_PREEMPT
select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_KASAN if X86_64
select HAVE_ARCH_KASAN_VMALLOC if HAVE_ARCH_KASAN
select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_SECCOMP_FILTER
select HAVE_ASM_MODVERSIONS select HAVE_ASM_MODVERSIONS
select HAVE_UID16 select HAVE_UID16
...@@ -219,6 +221,19 @@ config UML_TIME_TRAVEL_SUPPORT ...@@ -219,6 +221,19 @@ config UML_TIME_TRAVEL_SUPPORT
It is safe to say Y, but you probably don't need this. It is safe to say Y, but you probably don't need this.
config KASAN_SHADOW_OFFSET
hex
depends on KASAN
default 0x100000000000
help
This is the offset at which the ~16TB of shadow memory is
mapped and used by KASAN for memory debugging. This can be any
address that has at least KASAN_SHADOW_SIZE (total address space divided
by 8) amount of space so that the KASAN shadow memory does not conflict
with anything. The default is 0x100000000000, which works even if mem is
set to a large value. On low-memory systems, try 0x7fff8000, as it fits
into the immediate of most instructions, improving performance.
endmenu endmenu
source "arch/um/drivers/Kconfig" source "arch/um/drivers/Kconfig"
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* protects against a module being loaded twice at the same time. * protects against a module being loaded twice at the same time.
*/ */
static int random_fd = -1; static int random_fd = -1;
static struct hwrng hwrng = { 0, }; static struct hwrng hwrng;
static DECLARE_COMPLETION(have_data); static DECLARE_COMPLETION(have_data);
static int rng_dev_read(struct hwrng *rng, void *buf, size_t max, bool block) static int rng_dev_read(struct hwrng *rng, void *buf, size_t max, bool block)
......
...@@ -83,6 +83,8 @@ ...@@ -83,6 +83,8 @@
} }
.init_array : { .init_array : {
__init_array_start = .; __init_array_start = .;
*(.kasan_init)
*(.init_array.*)
*(.init_array) *(.init_array)
__init_array_end = .; __init_array_end = .;
} }
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_UM_KASAN_H
#define __ASM_UM_KASAN_H
#include <linux/init.h>
#include <linux/const.h>
#define KASAN_SHADOW_OFFSET _AC(CONFIG_KASAN_SHADOW_OFFSET, UL)
/* used in kasan_mem_to_shadow to divide by 8 */
#define KASAN_SHADOW_SCALE_SHIFT 3
#ifdef CONFIG_X86_64
#define KASAN_HOST_USER_SPACE_END_ADDR 0x00007fffffffffffUL
/* KASAN_SHADOW_SIZE is the size of total address space divided by 8 */
#define KASAN_SHADOW_SIZE ((KASAN_HOST_USER_SPACE_END_ADDR + 1) >> \
KASAN_SHADOW_SCALE_SHIFT)
#else
#error "KASAN_SHADOW_SIZE is not defined for this sub-architecture"
#endif /* CONFIG_X86_64 */
#define KASAN_SHADOW_START (KASAN_SHADOW_OFFSET)
#define KASAN_SHADOW_END (KASAN_SHADOW_START + KASAN_SHADOW_SIZE)
#ifdef CONFIG_KASAN
void kasan_init(void);
void kasan_map_memory(void *start, unsigned long len);
extern int kasan_um_is_ready;
#ifdef CONFIG_STATIC_LINK
#define kasan_arch_is_ready() (kasan_um_is_ready)
#endif
#else
static inline void kasan_init(void) { }
#endif /* CONFIG_KASAN */
#endif /* __ASM_UM_KASAN_H */
...@@ -59,11 +59,6 @@ static inline void release_thread(struct task_struct *task) ...@@ -59,11 +59,6 @@ static inline void release_thread(struct task_struct *task)
{ {
} }
static inline void mm_copy_segments(struct mm_struct *from_mm,
struct mm_struct *new_mm)
{
}
/* /*
* User space process size: 3GB (default). * User space process size: 3GB (default).
*/ */
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#undef XOR_SELECT_TEMPLATE #undef XOR_SELECT_TEMPLATE
/* pick an arbitrary one - measuring isn't possible with inf-cpu */ /* pick an arbitrary one - measuring isn't possible with inf-cpu */
#define XOR_SELECT_TEMPLATE(x) \ #define XOR_SELECT_TEMPLATE(x) \
(time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x)) (time_travel_mode == TT_MODE_INFCPU ? TT_CPU_INF_XOR_DEFAULT : x)
#endif #endif
#endif #endif
...@@ -16,11 +16,12 @@ ...@@ -16,11 +16,12 @@
*/ */
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
/* This is to get size_t */ /* This is to get size_t and NULL */
#ifndef __UM_HOST__ #ifndef __UM_HOST__
#include <linux/types.h> #include <linux/types.h>
#else #else
#include <stddef.h> #include <stddef.h>
#include <sys/types.h>
#endif #endif
extern void panic(const char *fmt, ...) extern void panic(const char *fmt, ...)
......
...@@ -109,7 +109,11 @@ SECTIONS ...@@ -109,7 +109,11 @@ SECTIONS
be empty, which isn't pretty. */ be empty, which isn't pretty. */
. = ALIGN(32 / 8); . = ALIGN(32 / 8);
.preinit_array : { *(.preinit_array) } .preinit_array : { *(.preinit_array) }
.init_array : { *(.init_array) } .init_array : {
*(.kasan_init)
*(.init_array.*)
*(.init_array)
}
.fini_array : { *(.fini_array) } .fini_array : { *(.fini_array) }
.data : { .data : {
INIT_TASK_DATA(KERNEL_STACK_SIZE) INIT_TASK_DATA(KERNEL_STACK_SIZE)
......
...@@ -18,6 +18,25 @@ ...@@ -18,6 +18,25 @@
#include <kern_util.h> #include <kern_util.h>
#include <mem_user.h> #include <mem_user.h>
#include <os.h> #include <os.h>
#include <linux/sched/task.h>
#ifdef CONFIG_KASAN
int kasan_um_is_ready;
void kasan_init(void)
{
/*
* kasan_map_memory will map all of the required address space and
* the host machine will allocate physical memory as necessary.
*/
kasan_map_memory((void *)KASAN_SHADOW_START, KASAN_SHADOW_SIZE);
init_task.kasan_depth = 0;
kasan_um_is_ready = true;
}
static void (*kasan_init_ptr)(void)
__section(".kasan_init") __used
= kasan_init;
#endif
/* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */ /* allocated in paging_init, zeroed in mem_init, and unchanged thereafter */
unsigned long *empty_zero_page = NULL; unsigned long *empty_zero_page = NULL;
......
...@@ -27,7 +27,7 @@ void dump_trace(struct task_struct *tsk, ...@@ -27,7 +27,7 @@ void dump_trace(struct task_struct *tsk,
frame = (struct stack_frame *)bp; frame = (struct stack_frame *)bp;
while (((long) sp & (THREAD_SIZE-1)) != 0) { while (((long) sp & (THREAD_SIZE-1)) != 0) {
addr = *sp; addr = READ_ONCE_NOCHECK(*sp);
if (__kernel_text_address(addr)) { if (__kernel_text_address(addr)) {
reliable = 0; reliable = 0;
if ((unsigned long) sp == bp + sizeof(long)) { if ((unsigned long) sp == bp + sizeof(long)) {
......
...@@ -95,6 +95,7 @@ SECTIONS ...@@ -95,6 +95,7 @@ SECTIONS
} }
.got : { *(.got.plt) *(.got) } .got : { *(.got.plt) *(.got) }
.eh_frame : { KEEP (*(.eh_frame)) }
.dynamic : { *(.dynamic) } .dynamic : { *(.dynamic) }
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
......
...@@ -17,6 +17,28 @@ ...@@ -17,6 +17,28 @@
#include <init.h> #include <init.h>
#include <os.h> #include <os.h>
/*
* kasan_map_memory - maps memory from @start with a size of @len.
* The allocated memory is filled with zeroes upon success.
* @start: the start address of the memory to be mapped
* @len: the length of the memory to be mapped
*
* This function is used to map shadow memory for KASAN in uml
*/
void kasan_map_memory(void *start, size_t len)
{
if (mmap(start,
len,
PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE,
-1,
0) == MAP_FAILED) {
os_info("Couldn't allocate shadow memory: %s\n.",
strerror(errno));
exit(1);
}
}
/* Set by make_tempfile() during early boot. */ /* Set by make_tempfile() during early boot. */
static char *tempdir = NULL; static char *tempdir = NULL;
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <sched.h> #include <sched.h>
#include <errno.h> #include <errno.h>
...@@ -707,10 +708,24 @@ void halt_skas(void) ...@@ -707,10 +708,24 @@ void halt_skas(void)
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT); UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
} }
static bool noreboot;
static int __init noreboot_cmd_param(char *str, int *add)
{
noreboot = true;
return 0;
}
__uml_setup("noreboot", noreboot_cmd_param,
"noreboot\n"
" Rather than rebooting, exit always, akin to QEMU's -no-reboot option.\n"
" This is useful if you're using CONFIG_PANIC_TIMEOUT in order to catch\n"
" crashes in CI\n");
void reboot_skas(void) void reboot_skas(void)
{ {
block_signals_trace(); block_signals_trace();
UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); UML_LONGJMP(&initial_jmpbuf, noreboot ? INIT_JMP_HALT : INIT_JMP_REBOOT);
} }
void __switch_mm(struct mm_id *mm_idp) void __switch_mm(struct mm_id *mm_idp)
......
...@@ -136,7 +136,7 @@ static int remove_files_and_dir(char *dir) ...@@ -136,7 +136,7 @@ static int remove_files_and_dir(char *dir)
static inline int is_umdir_used(char *dir) static inline int is_umdir_used(char *dir)
{ {
char pid[sizeof("nnnnnnnnn")], *end, *file; char pid[sizeof("nnnnnnnnn")], *end, *file;
int dead, fd, p, n, err; int fd, p, n, err;
size_t filelen = strlen(dir) + sizeof("/pid") + 1; size_t filelen = strlen(dir) + sizeof("/pid") + 1;
file = malloc(filelen); file = malloc(filelen);
...@@ -145,7 +145,6 @@ static inline int is_umdir_used(char *dir) ...@@ -145,7 +145,6 @@ static inline int is_umdir_used(char *dir)
snprintf(file, filelen, "%s/pid", dir); snprintf(file, filelen, "%s/pid", dir);
dead = 0;
fd = open(file, O_RDONLY); fd = open(file, O_RDONLY);
if (fd < 0) { if (fd < 0) {
fd = -errno; fd = -errno;
......
...@@ -27,10 +27,10 @@ EXPORT_SYMBOL(strstr); ...@@ -27,10 +27,10 @@ EXPORT_SYMBOL(strstr);
#ifndef __x86_64__ #ifndef __x86_64__
extern void *memcpy(void *, const void *, size_t); extern void *memcpy(void *, const void *, size_t);
EXPORT_SYMBOL(memcpy); EXPORT_SYMBOL(memcpy);
#endif
EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memset);
#endif
EXPORT_SYMBOL(printf); EXPORT_SYMBOL(printf);
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms. /* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
......
...@@ -28,7 +28,8 @@ else ...@@ -28,7 +28,8 @@ else
obj-y += syscalls_64.o vdso/ obj-y += syscalls_64.o vdso/
subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o subarch-y = ../lib/csum-partial_64.o ../lib/memcpy_64.o ../entry/thunk_64.o \
../lib/memmove_64.o ../lib/memset_64.o
endif endif
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <sysdep/ptrace_user.h> #include <sysdep/ptrace_user.h>
#include <generated/asm-offsets.h> #include <generated/asm-offsets.h>
#include <linux/stddef.h>
#define STUB_MMAP_NR __NR_mmap #define STUB_MMAP_NR __NR_mmap
#define MMAP_OFFSET(o) (o) #define MMAP_OFFSET(o) (o)
......
...@@ -19,8 +19,8 @@ void show_regs(struct pt_regs *regs) ...@@ -19,8 +19,8 @@ void show_regs(struct pt_regs *regs)
print_modules(); print_modules();
printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current), printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
current->comm, print_tainted(), init_utsname()->release); current->comm, print_tainted(), init_utsname()->release);
printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff, printk(KERN_INFO "RIP: %04lx:%pS\n", PT_REGS_CS(regs) & 0xffff,
PT_REGS_IP(regs)); (void *)PT_REGS_IP(regs));
printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_SP(regs), printk(KERN_INFO "RSP: %016lx EFLAGS: %08lx\n", PT_REGS_SP(regs),
PT_REGS_EFLAGS(regs)); PT_REGS_EFLAGS(regs));
printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n", printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
# Building vDSO images for x86. # Building vDSO images for x86.
# #
# do not instrument on vdso because KASAN is not compatible with user mode
KASAN_SANITIZE := n
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n KCOV_INSTRUMENT := n
......
...@@ -221,6 +221,9 @@ int overcommit_policy_handler(struct ctl_table *, int, void *, size_t *, ...@@ -221,6 +221,9 @@ int overcommit_policy_handler(struct ctl_table *, int, void *, size_t *,
/* to align the pointer to the (next) page boundary */ /* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE) #define PAGE_ALIGN(addr) ALIGN(addr, PAGE_SIZE)
/* to align the pointer to the (prev) page boundary */
#define PAGE_ALIGN_DOWN(addr) ALIGN_DOWN(addr, PAGE_SIZE)
/* test whether an address (unsigned long or pointer) is aligned to PAGE_SIZE */ /* test whether an address (unsigned long or pointer) is aligned to PAGE_SIZE */
#define PAGE_ALIGNED(addr) IS_ALIGNED((unsigned long)(addr), PAGE_SIZE) #define PAGE_ALIGNED(addr) IS_ALIGNED((unsigned long)(addr), PAGE_SIZE)
......
...@@ -295,9 +295,22 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size) ...@@ -295,9 +295,22 @@ int kasan_populate_vmalloc(unsigned long addr, unsigned long size)
return 0; return 0;
shadow_start = (unsigned long)kasan_mem_to_shadow((void *)addr); shadow_start = (unsigned long)kasan_mem_to_shadow((void *)addr);
shadow_start = ALIGN_DOWN(shadow_start, PAGE_SIZE);
shadow_end = (unsigned long)kasan_mem_to_shadow((void *)addr + size); shadow_end = (unsigned long)kasan_mem_to_shadow((void *)addr + size);
shadow_end = ALIGN(shadow_end, PAGE_SIZE);
/*
* User Mode Linux maps enough shadow memory for all of virtual memory
* at boot, so doesn't need to allocate more on vmalloc, just clear it.
*
* The remaining CONFIG_UML checks in this file exist for the same
* reason.
*/
if (IS_ENABLED(CONFIG_UML)) {
__memset((void *)shadow_start, KASAN_VMALLOC_INVALID, shadow_end - shadow_start);
return 0;
}
shadow_start = PAGE_ALIGN_DOWN(shadow_start);
shadow_end = PAGE_ALIGN(shadow_end);
ret = apply_to_page_range(&init_mm, shadow_start, ret = apply_to_page_range(&init_mm, shadow_start,
shadow_end - shadow_start, shadow_end - shadow_start,
...@@ -466,6 +479,10 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end, ...@@ -466,6 +479,10 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
if (shadow_end > shadow_start) { if (shadow_end > shadow_start) {
size = shadow_end - shadow_start; size = shadow_end - shadow_start;
if (IS_ENABLED(CONFIG_UML)) {
__memset(shadow_start, KASAN_SHADOW_INIT, shadow_end - shadow_start);
return;
}
apply_to_existing_page_range(&init_mm, apply_to_existing_page_range(&init_mm,
(unsigned long)shadow_start, (unsigned long)shadow_start,
size, kasan_depopulate_vmalloc_pte, size, kasan_depopulate_vmalloc_pte,
...@@ -531,6 +548,11 @@ int kasan_alloc_module_shadow(void *addr, size_t size, gfp_t gfp_mask) ...@@ -531,6 +548,11 @@ int kasan_alloc_module_shadow(void *addr, size_t size, gfp_t gfp_mask)
if (WARN_ON(!PAGE_ALIGNED(shadow_start))) if (WARN_ON(!PAGE_ALIGNED(shadow_start)))
return -EINVAL; return -EINVAL;
if (IS_ENABLED(CONFIG_UML)) {
__memset((void *)shadow_start, KASAN_SHADOW_INIT, shadow_size);
return 0;
}
ret = __vmalloc_node_range(shadow_size, 1, shadow_start, ret = __vmalloc_node_range(shadow_size, 1, shadow_start,
shadow_start + shadow_size, shadow_start + shadow_size,
GFP_KERNEL, GFP_KERNEL,
...@@ -554,6 +576,9 @@ int kasan_alloc_module_shadow(void *addr, size_t size, gfp_t gfp_mask) ...@@ -554,6 +576,9 @@ int kasan_alloc_module_shadow(void *addr, size_t size, gfp_t gfp_mask)
void kasan_free_module_shadow(const struct vm_struct *vm) void kasan_free_module_shadow(const struct vm_struct *vm)
{ {
if (IS_ENABLED(CONFIG_UML))
return;
if (vm->flags & VM_KASAN) if (vm->flags & VM_KASAN)
vfree(kasan_mem_to_shadow(vm->addr)); vfree(kasan_mem_to_shadow(vm->addr));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment