From d5f20be7cab85e6e701751323eea77c7935ae522 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Sun, 12 Oct 2014 13:02:11 +0200 Subject: um: Create asm/sections.h arch/um/kernel/dyn.lds.S and arch/um/kernel/uml.lds.S define some UML-specific symbols. These symbols are used in the kernel part of UML with extern declarations. Move these declarations to a new header, asm/sections.h, like other architectures do. Signed-off-by: Nicolas Iooss Signed-off-by: Richard Weinberger --- arch/um/include/asm/Kbuild | 1 - arch/um/include/asm/sections.h | 9 +++++++++ arch/um/kernel/physmem.c | 3 +-- arch/um/kernel/skas/mmu.c | 3 +-- arch/um/kernel/um_arch.c | 2 -- 5 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 arch/um/include/asm/sections.h (limited to 'arch/um') diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild index 9176fa11d49b..ea9ec2e34384 100644 --- a/arch/um/include/asm/Kbuild +++ b/arch/um/include/asm/Kbuild @@ -22,7 +22,6 @@ generic-y += pci.h generic-y += percpu.h generic-y += preempt.h generic-y += scatterlist.h -generic-y += sections.h generic-y += switch_to.h generic-y += topology.h generic-y += trace_clock.h diff --git a/arch/um/include/asm/sections.h b/arch/um/include/asm/sections.h new file mode 100644 index 000000000000..3a6ebcc65519 --- /dev/null +++ b/arch/um/include/asm/sections.h @@ -0,0 +1,9 @@ +#ifndef __UM_SECTIONS_H +#define __UM_SECTIONS_H + +#include + +extern char __binary_start; +extern int __syscall_stub_start, __syscall_stub_end; + +#endif diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 9034fc8056b4..249c9feb5485 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -55,8 +56,6 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, } } -extern int __syscall_stub_start; - /** * setup_physmem() - Setup physical memory for UML * @start: Start address of the physical kernel memory, diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 94abdcc1d6ad..2216eddc6893 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -8,12 +8,11 @@ #include #include #include +#include #include #include #include -extern int __syscall_stub_start; - static int init_stub_pte(struct mm_struct *mm, unsigned long proc, unsigned long kernel) { diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 07f798f4bcee..ffa185d92d2d 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -248,8 +248,6 @@ EXPORT_SYMBOL(end_iomem); #define MIN_VMALLOC (32 * 1024 * 1024) -extern char __binary_start; - int __init linux_main(int argc, char **argv) { unsigned long avail, diff; -- cgit v1.2.3 From 05eacfd00ccf239a24cfb409b084fa126c2e9468 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Sun, 12 Oct 2014 13:02:12 +0200 Subject: um: Use char[] for linker script address declarations The linker script defines some variables which are declared either with type char[] in include/asm-generic/sections.h or with a meaningless integer type in arch/um/include/asm/sections.h. Fix this inconsistency by declaring every variable char[]. Signed-off-by: Nicolas Iooss Signed-off-by: Richard Weinberger --- arch/um/include/asm/sections.h | 4 ++-- arch/um/kernel/physmem.c | 4 ++-- arch/um/kernel/skas/mmu.c | 4 ++-- arch/um/kernel/um_arch.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/asm/sections.h b/arch/um/include/asm/sections.h index 3a6ebcc65519..cafcf684d947 100644 --- a/arch/um/include/asm/sections.h +++ b/arch/um/include/asm/sections.h @@ -3,7 +3,7 @@ #include -extern char __binary_start; -extern int __syscall_stub_start, __syscall_stub_end; +extern char __binary_start[]; +extern char __syscall_stub_start[], __syscall_stub_end[]; #endif diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 249c9feb5485..4c9861b421fd 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -109,8 +109,8 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end, * Special kludge - This page will be mapped in to userspace processes * from physmem_fd, so it needs to be written out there. */ - os_seek_file(physmem_fd, __pa(&__syscall_stub_start)); - os_write_file(physmem_fd, &__syscall_stub_start, PAGE_SIZE); + os_seek_file(physmem_fd, __pa(__syscall_stub_start)); + os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE); os_fsync_file(physmem_fd); bootmap_size = init_bootmem(pfn, pfn + delta); diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 2216eddc6893..fda1deba1757 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -92,7 +92,7 @@ void uml_setup_stubs(struct mm_struct *mm) int err, ret; ret = init_stub_pte(mm, STUB_CODE, - (unsigned long) &__syscall_stub_start); + (unsigned long) __syscall_stub_start); if (ret) goto out; @@ -100,7 +100,7 @@ void uml_setup_stubs(struct mm_struct *mm) if (ret) goto out; - mm->context.stub_pages[0] = virt_to_page(&__syscall_stub_start); + mm->context.stub_pages[0] = virt_to_page(__syscall_stub_start); mm->context.stub_pages[1] = virt_to_page(mm->context.id.stack); /* dup_mmap already holds mmap_sem */ diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index ffa185d92d2d..16630e75f056 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -292,7 +292,7 @@ int __init linux_main(int argc, char **argv) physmem_size += UML_ROUND_UP(brk_start) - UML_ROUND_UP(&_end); } - uml_physmem = (unsigned long) &__binary_start & PAGE_MASK; + uml_physmem = (unsigned long) __binary_start & PAGE_MASK; /* Reserve up to 4M after the current brk */ uml_reserved = ROUND_4M(brk_start) + (1 << 22); -- cgit v1.2.3 From 5f32943b5e9a48bf3269430e1a7a210411e0cc98 Mon Sep 17 00:00:00 2001 From: Nicolas Iooss Date: Sun, 12 Oct 2014 13:02:13 +0200 Subject: um/os-Linux: Use char[] for syscall_stub declarations When declaring __syscall_stub_start, use the same type in UML userspace code as in arch/um/include/asm/sections.h. While at it, also declare batch_syscall_stub as char[]. Signed-off-by: Nicolas Iooss Signed-off-by: Richard Weinberger --- arch/um/os-Linux/skas/mem.c | 6 +++--- arch/um/os-Linux/skas/process.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index e7f8c945a573..35015e3e1e87 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -18,7 +18,7 @@ #include #include -extern unsigned long batch_syscall_stub, __syscall_stub_start; +extern char batch_syscall_stub[], __syscall_stub_start[]; extern void wait_stub_done(int pid); @@ -38,8 +38,8 @@ static int __init init_syscall_regs(void) { get_safe_registers(syscall_regs, NULL); syscall_regs[REGS_IP_INDEX] = STUB_CODE + - ((unsigned long) &batch_syscall_stub - - (unsigned long) &__syscall_stub_start); + ((unsigned long) batch_syscall_stub - + (unsigned long) __syscall_stub_start); return 0; } diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 7a9777570a62..3dddedba3a07 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -174,7 +174,7 @@ static void handle_trap(int pid, struct uml_pt_regs *regs, handle_syscall(regs); } -extern int __syscall_stub_start; +extern char __syscall_stub_start[]; static int userspace_tramp(void *stack) { @@ -197,7 +197,7 @@ static int userspace_tramp(void *stack) * This has a pte, but it can't be mapped in with the usual * tlb_flush mechanism because this is part of that mechanism */ - fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); + fd = phys_mapping(to_phys(__syscall_stub_start), &offset); addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE, PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); if (addr == MAP_FAILED) { @@ -223,7 +223,7 @@ static int userspace_tramp(void *stack) unsigned long v = STUB_CODE + (unsigned long) stub_segv_handler - - (unsigned long) &__syscall_stub_start; + (unsigned long) __syscall_stub_start; set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); @@ -447,7 +447,7 @@ static int __init init_thread_regs(void) /* Set parent's instruction pointer to start of clone-stub */ thread_regs[REGS_IP_INDEX] = STUB_CODE + (unsigned long) stub_clone_handler - - (unsigned long) &__syscall_stub_start; + (unsigned long) __syscall_stub_start; thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - sizeof(void *); #ifdef __SIGNAL_FRAMESIZE -- cgit v1.2.3 From a791b1565f828f926a54f1f5a612890ce0f00e6f Mon Sep 17 00:00:00 2001 From: Chen Gang Date: Sat, 4 Oct 2014 21:11:31 +0800 Subject: um: kernel: ksyms: Export symbol syscall() for fixing modpost issue syscall() is implemented in libc.so/a (e.g. for glibc, in "syscall.o"), so for normal ".o" files, it is undefined, neither can be found within kernel wide, so will break modpost. Since ".o" files is OK, can simply export 'syscall' symbol, let modpost know about that, then can fix this issue. The related error (with allmodconfig under um): MODPOST 1205 modules ERROR: "syscall" [fs/hostfs/hostfs.ko] undefined! Signed-off-by: Chen Gang Signed-off-by: Richard Weinberger --- arch/um/kernel/ksyms.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/um') diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 543c04756939..e7780f32a639 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -42,3 +42,6 @@ EXPORT_SYMBOL(os_makedev); EXPORT_SYMBOL(add_sigio_fd); EXPORT_SYMBOL(ignore_sigio_fd); EXPORT_SYMBOL(sigio_broken); + +extern long int syscall (long int __sysno, ...); +EXPORT_SYMBOL(syscall); -- cgit v1.2.3 From 89520d999683cb945d7540efd0944b3af2db9a54 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 13:11:19 +0200 Subject: um: Move syscall() declaration into os.h Signed-off-by: Richard Weinberger --- arch/um/include/shared/os.h | 2 ++ arch/um/kernel/ksyms.c | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index d824528f6f62..ad3fa3ae6d34 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h @@ -301,4 +301,6 @@ extern int get_pty(void); /* sys-$ARCH/task_size.c */ extern unsigned long os_get_top_address(void); +long syscall(long number, ...); + #endif diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index e7780f32a639..232b22307fdd 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -43,5 +43,4 @@ EXPORT_SYMBOL(add_sigio_fd); EXPORT_SYMBOL(ignore_sigio_fd); EXPORT_SYMBOL(sigio_broken); -extern long int syscall (long int __sysno, ...); EXPORT_SYMBOL(syscall); -- cgit v1.2.3 From f74a14e870c80d6261afed66d4bad779c1213e03 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 21 Apr 2015 20:52:26 +0200 Subject: um: Remove hppfs hppfs (honeypot procfs) was an attempt to use UML as honeypot. It was never stable nor in heavy use. As Al Viro and Christoph Hellwig pointed some major issues out it is better to let it die. Signed-off-by: Richard Weinberger --- arch/um/Kconfig.um | 15 --------------- 1 file changed, 15 deletions(-) (limited to 'arch/um') diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um index 6e67847f5272..bd5459ce77b1 100644 --- a/arch/um/Kconfig.um +++ b/arch/um/Kconfig.um @@ -44,21 +44,6 @@ config HOSTFS If you'd like to be able to work with files stored on the host, say Y or M here; otherwise say N. -config HPPFS - tristate "HoneyPot ProcFS" - depends on PROC_FS - help - hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc - entries to be overridden, removed, or fabricated from the host. - Its purpose is to allow a UML to appear to be a physical machine - by removing or changing anything in /proc which gives away the - identity of a UML. - - See for more information. - - You only need this if you are setting up a UML honeypot. Otherwise, - it is safe to say 'N' here. - config MCONSOLE bool "Management console" default y -- cgit v1.2.3 From f8d65d27e677da0ce33de570e3068308a77ed2b1 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 12 May 2015 00:17:28 +0200 Subject: um: Rework uaccess code Rework UML's uaccess code to reuse as much as possible from asm-generic/uaccess.c. Signed-off-by: Richard Weinberger --- arch/um/include/asm/thread_info.h | 2 +- arch/um/include/asm/uaccess.h | 176 ++++++-------------------------------- arch/um/kernel/skas/uaccess.c | 47 ++++------ 3 files changed, 43 insertions(+), 182 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index b30c85b141d9..53968aaf76f9 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h @@ -10,7 +10,7 @@ #include #include -#include +#include struct thread_info { struct task_struct *task; /* main task structure */ diff --git a/arch/um/include/asm/uaccess.h b/arch/um/include/asm/uaccess.h index 3f22fbf7ca1d..3705620ca298 100644 --- a/arch/um/include/asm/uaccess.h +++ b/arch/um/include/asm/uaccess.h @@ -1,178 +1,52 @@ /* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2015 Richard Weinberger (richard@nod.at) * Licensed under the GPL */ #ifndef __UM_UACCESS_H #define __UM_UACCESS_H -/* thread_info has a mm_segment_t in it, so put the definition up here */ -typedef struct { - unsigned long seg; -} mm_segment_t; - -#include -#include -#include +#include #include -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * The fs value determines whether argument validity checking should be - * performed or not. If get_fs() == USER_DS, checking is performed, with - * get_fs() == KERNEL_DS, checking is bypassed. - * - * For historical reasons, these macros are grossly misnamed. - */ - -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) - -#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) -#define USER_DS MAKE_MM_SEG(TASK_SIZE) - -#define get_ds() (KERNEL_DS) -#define get_fs() (current_thread_info()->addr_limit) -#define set_fs(x) (current_thread_info()->addr_limit = (x)) - -#define segment_eq(a, b) ((a).seg == (b).seg) - #define __under_task_size(addr, size) \ (((unsigned long) (addr) < TASK_SIZE) && \ (((unsigned long) (addr) + (size)) < TASK_SIZE)) -#define __access_ok_vsyscall(type, addr, size) \ - ((type == VERIFY_READ) && \ - ((unsigned long) (addr) >= FIXADDR_USER_START) && \ +#define __access_ok_vsyscall(addr, size) \ + (((unsigned long) (addr) >= FIXADDR_USER_START) && \ ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ ((unsigned long) (addr) + (size) >= (unsigned long)(addr))) #define __addr_range_nowrap(addr, size) \ ((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) -#define access_ok(type, addr, size) \ - (__addr_range_nowrap(addr, size) && \ - (__under_task_size(addr, size) || \ - __access_ok_vsyscall(type, addr, size) || \ - segment_eq(get_fs(), KERNEL_DS))) - -extern int copy_from_user(void *to, const void __user *from, int n); -extern int copy_to_user(void __user *to, const void *from, int n); - -/* - * strncpy_from_user: - Copy a NUL terminated string from userspace. - * @dst: Destination address, in kernel space. This buffer must be at - * least @count bytes long. - * @src: Source address, in user space. - * @count: Maximum number of bytes to copy, including the trailing NUL. - * - * Copies a NUL-terminated string from userspace to kernel space. - * - * On success, returns the length of the string (not including the trailing - * NUL). - * - * If access to userspace fails, returns -EFAULT (some data may have been - * copied). - * - * If @count is smaller than the length of the string, copies @count bytes - * and returns @count. - */ - -extern int strncpy_from_user(char *dst, const char __user *src, int count); - -/* - * __clear_user: - Zero a block of memory in user space, with less checking. - * @to: Destination address, in user space. - * @n: Number of bytes to zero. - * - * Zero a block of memory in user space. Caller must check - * the specified block with access_ok() before calling this function. - * - * Returns number of bytes that could not be cleared. - * On success, this will be zero. - */ -extern int __clear_user(void __user *mem, int len); - -/* - * clear_user: - Zero a block of memory in user space. - * @to: Destination address, in user space. - * @n: Number of bytes to zero. - * - * Zero a block of memory in user space. - * - * Returns number of bytes that could not be cleared. - * On success, this will be zero. - */ -extern int clear_user(void __user *mem, int len); - -/* - * strlen_user: - Get the size of a string in user space. - * @str: The string to measure. - * @n: The maximum valid length - * - * Get the size of a NUL-terminated string in user space. - * - * Returns the size of the string INCLUDING the terminating NUL. - * On exception, returns 0. - * If the string is too long, returns a value greater than @n. - */ -extern int strnlen_user(const void __user *str, int len); - -#define __copy_from_user(to, from, n) copy_from_user(to, from, n) - -#define __copy_to_user(to, from, n) copy_to_user(to, from, n) - +extern long __copy_from_user(void *to, const void __user *from, unsigned long n); +extern long __copy_to_user(void __user *to, const void *from, unsigned long n); +extern long __strncpy_from_user(char *dst, const char __user *src, long count); +extern long __strnlen_user(const void __user *str, long len); +extern unsigned long __clear_user(void __user *mem, unsigned long len); +static inline int __access_ok(unsigned long addr, unsigned long size); + +/* Teach asm-generic/uaccess.h that we have C functions for these. */ +#define __access_ok __access_ok +#define __clear_user __clear_user +#define __copy_to_user __copy_to_user +#define __copy_from_user __copy_from_user +#define __strnlen_user __strnlen_user +#define __strncpy_from_user __strncpy_from_user #define __copy_to_user_inatomic __copy_to_user #define __copy_from_user_inatomic __copy_from_user -#define __get_user(x, ptr) \ -({ \ - const __typeof__(*(ptr)) __user *__private_ptr = (ptr); \ - __typeof__(x) __private_val; \ - int __private_ret = -EFAULT; \ - (x) = (__typeof__(*(__private_ptr)))0; \ - if (__copy_from_user((__force void *)&__private_val, (__private_ptr),\ - sizeof(*(__private_ptr))) == 0) { \ - (x) = (__typeof__(*(__private_ptr))) __private_val; \ - __private_ret = 0; \ - } \ - __private_ret; \ -}) - -#define get_user(x, ptr) \ -({ \ - const __typeof__((*(ptr))) __user *private_ptr = (ptr); \ - (access_ok(VERIFY_READ, private_ptr, sizeof(*private_ptr)) ? \ - __get_user(x, private_ptr) : ((x) = (__typeof__(*ptr))0, -EFAULT)); \ -}) - -#define __put_user(x, ptr) \ -({ \ - __typeof__(*(ptr)) __user *__private_ptr = ptr; \ - __typeof__(*(__private_ptr)) __private_val; \ - int __private_ret = -EFAULT; \ - __private_val = (__typeof__(*(__private_ptr))) (x); \ - if (__copy_to_user((__private_ptr), &__private_val, \ - sizeof(*(__private_ptr))) == 0) { \ - __private_ret = 0; \ - } \ - __private_ret; \ -}) - -#define put_user(x, ptr) \ -({ \ - __typeof__(*(ptr)) __user *private_ptr = (ptr); \ - (access_ok(VERIFY_WRITE, private_ptr, sizeof(*private_ptr)) ? \ - __put_user(x, private_ptr) : -EFAULT); \ -}) - -#define strlen_user(str) strnlen_user(str, ~0U >> 1) +#include -struct exception_table_entry +static inline int __access_ok(unsigned long addr, unsigned long size) { - unsigned long insn; - unsigned long fixup; -}; + return __addr_range_nowrap(addr, size) && + (__under_task_size(addr, size) || + __access_ok_vsyscall(addr, size) || + segment_eq(get_fs(), KERNEL_DS)); +} #endif diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 4ffb644d6c07..85ac8adb069b 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -87,10 +87,10 @@ static int do_op_one_page(unsigned long addr, int len, int is_write, return n; } -static int buffer_op(unsigned long addr, int len, int is_write, - int (*op)(unsigned long, int, void *), void *arg) +static long buffer_op(unsigned long addr, int len, int is_write, + int (*op)(unsigned long, int, void *), void *arg) { - int size, remain, n; + long size, remain, n; size = min(PAGE_ALIGN(addr) - addr, (unsigned long) len); remain = len; @@ -139,18 +139,16 @@ static int copy_chunk_from_user(unsigned long from, int len, void *arg) return 0; } -int copy_from_user(void *to, const void __user *from, int n) +long __copy_from_user(void *to, const void __user *from, unsigned long n) { if (segment_eq(get_fs(), KERNEL_DS)) { memcpy(to, (__force void*)from, n); return 0; } - return access_ok(VERIFY_READ, from, n) ? - buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): - n; + return buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to); } -EXPORT_SYMBOL(copy_from_user); +EXPORT_SYMBOL(__copy_from_user); static int copy_chunk_to_user(unsigned long to, int len, void *arg) { @@ -161,18 +159,16 @@ static int copy_chunk_to_user(unsigned long to, int len, void *arg) return 0; } -int copy_to_user(void __user *to, const void *from, int n) +long __copy_to_user(void __user *to, const void *from, unsigned long n) { if (segment_eq(get_fs(), KERNEL_DS)) { memcpy((__force void *) to, from, n); return 0; } - return access_ok(VERIFY_WRITE, to, n) ? - buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : - n; + return buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from); } -EXPORT_SYMBOL(copy_to_user); +EXPORT_SYMBOL(__copy_to_user); static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) { @@ -188,9 +184,9 @@ static int strncpy_chunk_from_user(unsigned long from, int len, void *arg) return 0; } -int strncpy_from_user(char *dst, const char __user *src, int count) +long __strncpy_from_user(char *dst, const char __user *src, long count) { - int n; + long n; char *ptr = dst; if (segment_eq(get_fs(), KERNEL_DS)) { @@ -198,16 +194,13 @@ int strncpy_from_user(char *dst, const char __user *src, int count) return strnlen(dst, count); } - if (!access_ok(VERIFY_READ, src, 1)) - return -EFAULT; - n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, &ptr); if (n != 0) return -EFAULT; return strnlen(dst, count); } -EXPORT_SYMBOL(strncpy_from_user); +EXPORT_SYMBOL(__strncpy_from_user); static int clear_chunk(unsigned long addr, int len, void *unused) { @@ -215,22 +208,16 @@ static int clear_chunk(unsigned long addr, int len, void *unused) return 0; } -int __clear_user(void __user *mem, int len) -{ - return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); -} - -int clear_user(void __user *mem, int len) +unsigned long __clear_user(void __user *mem, unsigned long len) { if (segment_eq(get_fs(), KERNEL_DS)) { memset((__force void*)mem, 0, len); return 0; } - return access_ok(VERIFY_WRITE, mem, len) ? - buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len; + return buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL); } -EXPORT_SYMBOL(clear_user); +EXPORT_SYMBOL(__clear_user); static int strnlen_chunk(unsigned long str, int len, void *arg) { @@ -244,7 +231,7 @@ static int strnlen_chunk(unsigned long str, int len, void *arg) return 0; } -int strnlen_user(const void __user *str, int len) +long __strnlen_user(const void __user *str, long len) { int count = 0, n; @@ -256,4 +243,4 @@ int strnlen_user(const void __user *str, int len) return count + 1; return 0; } -EXPORT_SYMBOL(strnlen_user); +EXPORT_SYMBOL(__strnlen_user); -- cgit v1.2.3 From d2313084e2c3488e254796617fcda45d69731b21 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 19:21:51 +0200 Subject: um: Catch unprotected user memory access If the kernel tries to access user memory without copy_from_user() a trap will happen as kernel and userspace run in different processes on the host side. Currently this special page fault cannot be resolved and will happen over and over again. As result UML will lockup. This patch allows the page fault code to detect that situation and causes a panic() such that the root cause of the unprotected memory access can be found and fixed. Signed-off-by: Richard Weinberger --- arch/um/kernel/trap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/um') diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c index 8e4daf44e980..34b633ec852f 100644 --- a/arch/um/kernel/trap.c +++ b/arch/um/kernel/trap.c @@ -219,6 +219,11 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, show_regs(container_of(regs, struct pt_regs, regs)); panic("Segfault with no mm"); } + else if (!is_user && address < TASK_SIZE) { + show_regs(container_of(regs, struct pt_regs, regs)); + panic("Kernel tried to access user memory at addr 0x%lx, ip 0x%lx", + address, ip); + } if (SEGV_IS_FIXABLE(&fi)) err = handle_page_fault(address, ip, is_write, is_user, -- cgit v1.2.3 From 298e20ba8c197e8d429a6c8671550c41c7919033 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 19:50:57 +0200 Subject: um: Stop abusing __KERNEL__ Currently UML is abusing __KERNEL__ to distinguish between kernel and host code (os-Linux). It is better to use a custom define such that existing users of __KERNEL__ don't get confused. Signed-off-by: Richard Weinberger --- arch/um/Makefile | 7 ++++--- arch/um/drivers/mconsole.h | 2 +- arch/um/include/shared/init.h | 4 ++-- arch/um/include/shared/user.h | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) (limited to 'arch/um') diff --git a/arch/um/Makefile b/arch/um/Makefile index 17d4460b1af3..098ab3333e7c 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -68,9 +68,10 @@ KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \ KBUILD_AFLAGS += $(ARCH_INCLUDE) -USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -D__KERNEL__,,\ - $(patsubst -I%,,$(KBUILD_CFLAGS)))) $(ARCH_INCLUDE) $(MODE_INCLUDE) \ - $(filter -I%,$(CFLAGS)) -D_FILE_OFFSET_BITS=64 -idirafter include +USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \ + $(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \ + -D_FILE_OFFSET_BITS=64 -idirafter include \ + -D__KERNEL__ -D__UM_HOST__ #This will adjust *FLAGS accordingly to the platform. include $(ARCH_DIR)/Makefile-os-$(OS) diff --git a/arch/um/drivers/mconsole.h b/arch/um/drivers/mconsole.h index 8b22535c62ce..44af7379ea19 100644 --- a/arch/um/drivers/mconsole.h +++ b/arch/um/drivers/mconsole.h @@ -7,7 +7,7 @@ #ifndef __MCONSOLE_H__ #define __MCONSOLE_H__ -#ifndef __KERNEL__ +#ifdef __UM_HOST__ #include #define u32 uint32_t #endif diff --git a/arch/um/include/shared/init.h b/arch/um/include/shared/init.h index b3906f860a87..031ad1d111e7 100644 --- a/arch/um/include/shared/init.h +++ b/arch/um/include/shared/init.h @@ -40,7 +40,7 @@ typedef int (*initcall_t)(void); typedef void (*exitcall_t)(void); -#ifndef __KERNEL__ +#ifdef __UM_HOST__ #ifndef __section # define __section(S) __attribute__ ((__section__(#S))) #endif @@ -131,7 +131,7 @@ extern struct uml_param __uml_setup_start, __uml_setup_end; #define __uml_postsetup_call __used __section(.uml.postsetup.init) #define __uml_exit_call __used __section(.uml.exitcall.exit) -#ifndef __KERNEL__ +#ifdef __UM_HOST__ #define __define_initcall(level,fn) \ static initcall_t __initcall_##fn __used \ diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h index cef068563336..4cff19f6207a 100644 --- a/arch/um/include/shared/user.h +++ b/arch/um/include/shared/user.h @@ -17,7 +17,7 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* This is to get size_t */ -#ifdef __KERNEL__ +#ifndef __UM_HOST__ #include #else #include -- cgit v1.2.3 From 30b11ee9ae23d78de66b9ae315880af17a64ba83 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 22:15:58 +0200 Subject: um: Remove copy&paste code from init.h As we got rid of the __KERNEL__ abuse, we can directly include linux/compiler.h now. This also allows gcc 5 to build UML. Reported-by: Hans-Werner Hilse Signed-off-by: Richard Weinberger --- arch/um/include/shared/init.h | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/shared/init.h b/arch/um/include/shared/init.h index 031ad1d111e7..233e2593eee0 100644 --- a/arch/um/include/shared/init.h +++ b/arch/um/include/shared/init.h @@ -40,28 +40,8 @@ typedef int (*initcall_t)(void); typedef void (*exitcall_t)(void); -#ifdef __UM_HOST__ -#ifndef __section -# define __section(S) __attribute__ ((__section__(#S))) -#endif - -#if __GNUC__ == 3 - -#if __GNUC_MINOR__ >= 3 -# define __used __attribute__((__used__)) -#else -# define __used __attribute__((__unused__)) -#endif - -#else -#if __GNUC__ == 4 -# define __used __attribute__((__used__)) -#endif -#endif - -#else #include -#endif + /* These are for everybody (although not all archs will actually discard it in modules) */ #define __init __section(.init.text) -- cgit v1.2.3 From 5334cdae407a5778a297a98a75ca61140e37ebfa Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 22:59:03 +0200 Subject: um: Handle tracehook_report_syscall_entry() result tracehook_report_syscall_entry() is allowed to fail, in case of failure we have to abort the current syscall. Signed-off-by: Richard Weinberger --- arch/um/include/asm/ptrace-generic.h | 2 +- arch/um/kernel/ptrace.c | 6 +++--- arch/um/kernel/skas/syscall.c | 6 +++++- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'arch/um') diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h index cb9b3c47ca8e..283480a7ad23 100644 --- a/arch/um/include/asm/ptrace-generic.h +++ b/arch/um/include/asm/ptrace-generic.h @@ -37,7 +37,7 @@ extern int putreg(struct task_struct *child, int regno, unsigned long value); extern int arch_copy_tls(struct task_struct *new); extern void clear_flushed_tls(struct task_struct *task); -extern void syscall_trace_enter(struct pt_regs *regs); +extern int syscall_trace_enter(struct pt_regs *regs); extern void syscall_trace_leave(struct pt_regs *regs); #endif diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 174ee5017264..cac2ea058b7a 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -131,7 +131,7 @@ static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs, * XXX Check PT_DTRACE vs TIF_SINGLESTEP for singlestepping check and * PT_PTRACED vs TIF_SYSCALL_TRACE for syscall tracing check */ -void syscall_trace_enter(struct pt_regs *regs) +int syscall_trace_enter(struct pt_regs *regs) { audit_syscall_entry(UPT_SYSCALL_NR(®s->regs), UPT_SYSCALL_ARG1(®s->regs), @@ -140,9 +140,9 @@ void syscall_trace_enter(struct pt_regs *regs) UPT_SYSCALL_ARG4(®s->regs)); if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + return 0; - tracehook_report_syscall_entry(regs); + return tracehook_report_syscall_entry(regs); } void syscall_trace_leave(struct pt_regs *regs) diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index c0681e097432..d9ec0068b623 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -18,7 +18,10 @@ void handle_syscall(struct uml_pt_regs *r) long result; int syscall; - syscall_trace_enter(regs); + if (syscall_trace_enter(regs)) { + result = -ENOSYS; + goto out; + } /* * This should go in the declaration of syscall, but when I do that, @@ -34,6 +37,7 @@ void handle_syscall(struct uml_pt_regs *r) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); +out: PT_REGS_SET_SYSCALL_RETURN(regs, result); syscall_trace_leave(regs); -- cgit v1.2.3 From 1eb7c6c70e9d8e86b7083661e91ae8f6cd1bffd4 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 31 May 2015 23:27:26 +0200 Subject: um: Fix mconsole dependency mconsole depends on CONFIG_PROC_FS. Signed-off-by: Richard Weinberger --- arch/um/Kconfig.um | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um') diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um index bd5459ce77b1..28a9885e3a37 100644 --- a/arch/um/Kconfig.um +++ b/arch/um/Kconfig.um @@ -46,6 +46,7 @@ config HOSTFS config MCONSOLE bool "Management console" + depends on PROC_FS default y help The user mode linux management console is a low-level interface to -- cgit v1.2.3 From 9a75551aeaa8c79fd6ad713cb20e6bbccc767331 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Thu, 11 Jun 2015 11:29:18 +0200 Subject: um: Do not use __ptr_t type for stack_t's .ss pointer __ptr_t type is a glibc-specific type, while the generally documented type is a void*. That's what other C libraries use, too. Signed-off-by: Hans-Werner Hilse Signed-off-by: Richard Weinberger --- arch/um/os-Linux/signal.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'arch/um') diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 7b605e4dfffa..036d0dbc7b52 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -112,9 +112,11 @@ void timer_init(void) void set_sigstack(void *sig_stack, int size) { - stack_t stack = ((stack_t) { .ss_flags = 0, - .ss_sp = (__ptr_t) sig_stack, - .ss_size = size - sizeof(void *) }); + stack_t stack = { + .ss_flags = 0, + .ss_sp = sig_stack, + .ss_size = size - sizeof(void *) + }; if (sigaltstack(&stack, NULL) != 0) panic("enabling signal stack failed, errno = %d\n", errno); -- cgit v1.2.3 From f9bb3b5947c507d402eecbffabb8fb0864263ad1 Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Thu, 11 Jun 2015 11:29:19 +0200 Subject: um: Do not use stdin and stdout identifiers for struct members stdin, stdout and stderr are macros according to C89/C99. Thus do not use them as struct member identifiers to avoid bad results from macro expansion. Signed-off-by: Hans-Werner Hilse Signed-off-by: Richard Weinberger --- arch/um/drivers/harddog_user.c | 18 +++++++++--------- arch/um/drivers/net_user.c | 6 +++--- arch/um/drivers/slip_user.c | 14 +++++++------- arch/um/drivers/slirp_user.c | 16 ++++++++-------- arch/um/os-Linux/drivers/tuntap_user.c | 6 +++--- 5 files changed, 30 insertions(+), 30 deletions(-) (limited to 'arch/um') diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index f99b32a4dbff..3aa8b0d52a48 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -9,8 +9,8 @@ #include struct dog_data { - int stdin; - int stdout; + int stdin_fd; + int stdout_fd; int close_me[2]; }; @@ -18,11 +18,11 @@ static void pre_exec(void *d) { struct dog_data *data = d; - dup2(data->stdin, 0); - dup2(data->stdout, 1); - dup2(data->stdout, 2); - close(data->stdin); - close(data->stdout); + dup2(data->stdin_fd, 0); + dup2(data->stdout_fd, 1); + dup2(data->stdout_fd, 2); + close(data->stdin_fd); + close(data->stdout_fd); close(data->close_me[0]); close(data->close_me[1]); } @@ -49,8 +49,8 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock) goto out_close_in; } - data.stdin = out_fds[0]; - data.stdout = in_fds[1]; + data.stdin_fd = out_fds[0]; + data.stdout_fd = in_fds[1]; data.close_me[0] = out_fds[1]; data.close_me[1] = in_fds[0]; diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index cd14157b556d..e697a4136707 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -166,7 +166,7 @@ int net_sendto(int fd, void *buf, int len, void *to, int sock_len) struct change_pre_exec_data { int close_me; - int stdout; + int stdout_fd; }; static void change_pre_exec(void *arg) @@ -174,7 +174,7 @@ static void change_pre_exec(void *arg) struct change_pre_exec_data *data = arg; close(data->close_me); - dup2(data->stdout, 1); + dup2(data->stdout_fd, 1); } static int change_tramp(char **argv, char *output, int output_len) @@ -189,7 +189,7 @@ static int change_tramp(char **argv, char *output, int output_len) return err; } pe_data.close_me = fds[0]; - pe_data.stdout = fds[1]; + pe_data.stdout_fd = fds[1]; pid = run_helper(change_pre_exec, &pe_data, argv); if (pid > 0) /* Avoid hang as we won't get data in failure case. */ diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 55c290d925f3..0d6b66c64a81 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -55,8 +55,8 @@ static int set_up_tty(int fd) } struct slip_pre_exec_data { - int stdin; - int stdout; + int stdin_fd; + int stdout_fd; int close_me; }; @@ -64,9 +64,9 @@ static void slip_pre_exec(void *arg) { struct slip_pre_exec_data *data = arg; - if (data->stdin >= 0) - dup2(data->stdin, 0); - dup2(data->stdout, 1); + if (data->stdin_fd >= 0) + dup2(data->stdin_fd, 0); + dup2(data->stdout_fd, 1); if (data->close_me >= 0) close(data->close_me); } @@ -85,8 +85,8 @@ static int slip_tramp(char **argv, int fd) } err = 0; - pe_data.stdin = fd; - pe_data.stdout = fds[1]; + pe_data.stdin_fd = fd; + pe_data.stdout_fd = fds[1]; pe_data.close_me = fds[0]; err = run_helper(slip_pre_exec, &pe_data, argv); if (err < 0) diff --git a/arch/um/drivers/slirp_user.c b/arch/um/drivers/slirp_user.c index c999d187abb9..98b6a41a254e 100644 --- a/arch/um/drivers/slirp_user.c +++ b/arch/um/drivers/slirp_user.c @@ -20,18 +20,18 @@ static int slirp_user_init(void *data, void *dev) } struct slirp_pre_exec_data { - int stdin; - int stdout; + int stdin_fd; + int stdout_fd; }; static void slirp_pre_exec(void *arg) { struct slirp_pre_exec_data *data = arg; - if (data->stdin != -1) - dup2(data->stdin, 0); - if (data->stdout != -1) - dup2(data->stdout, 1); + if (data->stdin_fd != -1) + dup2(data->stdin_fd, 0); + if (data->stdout_fd != -1) + dup2(data->stdout_fd, 1); } static int slirp_tramp(char **argv, int fd) @@ -39,8 +39,8 @@ static int slirp_tramp(char **argv, int fd) struct slirp_pre_exec_data pe_data; int pid; - pe_data.stdin = fd; - pe_data.stdout = fd; + pe_data.stdin_fd = fd; + pe_data.stdout_fd = fd; pid = run_helper(slirp_pre_exec, &pe_data, argv); return pid; diff --git a/arch/um/os-Linux/drivers/tuntap_user.c b/arch/um/os-Linux/drivers/tuntap_user.c index 14126d9176aa..c2e6e1dad876 100644 --- a/arch/um/os-Linux/drivers/tuntap_user.c +++ b/arch/um/os-Linux/drivers/tuntap_user.c @@ -47,7 +47,7 @@ static void tuntap_del_addr(unsigned char *addr, unsigned char *netmask, } struct tuntap_pre_exec_data { - int stdout; + int stdout_fd; int close_me; }; @@ -55,7 +55,7 @@ static void tuntap_pre_exec(void *arg) { struct tuntap_pre_exec_data *data = arg; - dup2(data->stdout, 1); + dup2(data->stdout_fd, 1); close(data->close_me); } @@ -74,7 +74,7 @@ static int tuntap_open_tramp(char *gate, int *fd_out, int me, int remote, sprintf(version_buf, "%d", UML_NET_VERSION); - data.stdout = remote; + data.stdout_fd = remote; data.close_me = me; pid = run_helper(tuntap_pre_exec, &data, argv); -- cgit v1.2.3 From 8eeba4e9a76cd126e737d3d303d9c424b66ea90d Mon Sep 17 00:00:00 2001 From: Hans-Werner Hilse Date: Thu, 11 Jun 2015 11:29:20 +0200 Subject: um: Include sys/types.h for makedev(), major(), minor() The functions in question are not part of the POSIX standard, documentation however hints that the corresponding header shall be sys/types.h. C libraries other than glibc, namely musl, did not include that header via other ways and complained. Signed-off-by: Hans-Werner Hilse Signed-off-by: Richard Weinberger --- arch/um/os-Linux/file.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um') diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c index 08d90fba952c..26e0164895e4 100644 --- a/arch/um/os-Linux/file.c +++ b/arch/um/os-Linux/file.c @@ -13,6 +13,7 @@ #include #include #include +#include #include static void copy_stat(struct uml_stat *dst, const struct stat64 *src) -- cgit v1.2.3 From da028d5e5463dabb6ede2f5e3f6cced1283988cc Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Thu, 25 Jun 2015 22:44:11 +0200 Subject: um: Don't pollute kernel namespace with uapi Don't include ptrace uapi stuff in arch headers, it will pollute the kernel namespace and conflict with existing stuff. In this case it fixes clashes with common names like R8. Signed-off-by: Richard Weinberger --- arch/um/include/asm/ptrace-generic.h | 1 - arch/um/kernel/ptrace.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um') diff --git a/arch/um/include/asm/ptrace-generic.h b/arch/um/include/asm/ptrace-generic.h index 283480a7ad23..2966adbbdf6c 100644 --- a/arch/um/include/asm/ptrace-generic.h +++ b/arch/um/include/asm/ptrace-generic.h @@ -8,7 +8,6 @@ #ifndef __ASSEMBLY__ -#include #include struct pt_regs { diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index cac2ea058b7a..6a826cbb15c4 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -8,6 +8,7 @@ #include #include #include +#include void user_enable_single_step(struct task_struct *child) { -- cgit v1.2.3