diff options
author | Dave Airlie <airlied@starflyer.(none)> | 2006-01-03 18:18:01 +1100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-01-03 18:18:01 +1100 |
commit | 97f2aab6698f3ab2552c41c1024a65ffd0763a6d (patch) | |
tree | bb6e3b2949459f54f884c710fc74d40eef00d834 /arch/um | |
parent | d985c1088146607532093d9eaaaf99758f6a4d21 (diff) | |
parent | 88026842b0a760145aa71d69e74fbc9ec118ca44 (diff) | |
download | op-kernel-dev-97f2aab6698f3ab2552c41c1024a65ffd0763a6d.zip op-kernel-dev-97f2aab6698f3ab2552c41c1024a65ffd0763a6d.tar.gz |
drm: merge in Linus mainline
Diffstat (limited to 'arch/um')
34 files changed, 225 insertions, 194 deletions
diff --git a/arch/um/Kconfig b/arch/um/Kconfig index 3b5f47c..1eb21de 100644 --- a/arch/um/Kconfig +++ b/arch/um/Kconfig @@ -7,7 +7,6 @@ config UML bool default y -# XXX: does UM have a mmu/swap? config MMU bool default y @@ -36,12 +35,6 @@ config IRQ_RELEASE_METHOD bool default y -menu "Host processor type and features" - -source "arch/i386/Kconfig.cpu" - -endmenu - menu "UML-specific options" config MODE_TT @@ -209,7 +202,8 @@ config MAGIC_SYSRQ config SMP bool "Symmetric multi-processing support (EXPERIMENTAL)" default n - depends on (MODE_TT && EXPERIMENTAL && !SMP_BROKEN) || (BROKEN && SMP_BROKEN) + #SMP_BROKEN is for x86_64. + depends on MODE_TT && EXPERIMENTAL && (!SMP_BROKEN || (BROKEN && SMP_BROKEN)) help This option enables UML SMP support. It is NOT related to having a real SMP box. Not directly, at least. @@ -295,6 +289,8 @@ source "arch/um/Kconfig.net" source "drivers/net/Kconfig" +source "drivers/connector/Kconfig" + source "fs/Kconfig" source "security/Kconfig" diff --git a/arch/um/Kconfig.i386 b/arch/um/Kconfig.i386 index 5d92cac..c71b39a 100644 --- a/arch/um/Kconfig.i386 +++ b/arch/um/Kconfig.i386 @@ -1,3 +1,9 @@ +menu "Host processor type and features" + +source "arch/i386/Kconfig.cpu" + +endmenu + config UML_X86 bool default y @@ -42,7 +48,3 @@ config ARCH_HAS_SC_SIGNALS config ARCH_REUSE_HOST_VSYSCALL_AREA bool default y - -config X86_CMPXCHG - bool - default y diff --git a/arch/um/Makefile b/arch/um/Makefile index e55d32e..1b12fee 100644 --- a/arch/um/Makefile +++ b/arch/um/Makefile @@ -17,7 +17,7 @@ core-y += $(ARCH_DIR)/kernel/ \ # Have to precede the include because the included Makefiles reference them. SYMLINK_HEADERS := archparam.h system.h sigcontext.h processor.h ptrace.h \ - module.h vm-flags.h elf.h + module.h vm-flags.h elf.h ldt.h SYMLINK_HEADERS := $(foreach header,$(SYMLINK_HEADERS),include/asm-um/$(header)) # XXX: The "os" symlink is only used by arch/um/include/os.h, which includes diff --git a/arch/um/Makefile-i386 b/arch/um/Makefile-i386 index 1f7dcb0..7a0e04e 100644 --- a/arch/um/Makefile-i386 +++ b/arch/um/Makefile-i386 @@ -35,4 +35,3 @@ cflags-y += $(call cc-option,-mpreferred-stack-boundary=2) CFLAGS += $(cflags-y) USER_CFLAGS += $(cflags-y) - diff --git a/arch/um/Makefile-x86_64 b/arch/um/Makefile-x86_64 index 4f118d5..38df311 100644 --- a/arch/um/Makefile-x86_64 +++ b/arch/um/Makefile-x86_64 @@ -12,3 +12,7 @@ CHECKFLAGS += -m64 ELF_ARCH := i386:x86-64 ELF_FORMAT := elf64-x86-64 + +# Not on all 64-bit distros /lib is a symlink to /lib64. PLD is an example. + +LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib64 diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c index 16e7dc8..5b58fad 100644 --- a/arch/um/drivers/chan_kern.c +++ b/arch/um/drivers/chan_kern.c @@ -89,8 +89,7 @@ static int not_configged_write(int fd, const char *buf, int len, void *data) return(-EIO); } -static int not_configged_console_write(int fd, const char *buf, int len, - void *data) +static int not_configged_console_write(int fd, const char *buf, int len) { my_puts("Using a channel type which is configured out of " "UML\n"); @@ -299,7 +298,7 @@ int console_write_chan(struct list_head *chans, const char *buf, int len) chan = list_entry(ele, struct chan, list); if(!chan->output || (chan->ops->console_write == NULL)) continue; - n = chan->ops->console_write(chan->fd, buf, len, chan->data); + n = chan->ops->console_write(chan->fd, buf, len); if(chan->primary) ret = n; } return(ret); diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 1c55d58..5d50d4a 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -20,7 +20,7 @@ #include "choose-mode.h" #include "mode.h" -int generic_console_write(int fd, const char *buf, int n, void *unused) +int generic_console_write(int fd, const char *buf, int n) { struct termios save, new; int err; diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index c1b03f7..1bb085b2 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -98,7 +98,7 @@ static int connect_to_switch(struct daemon_data *pri) printk("daemon_open : control setup request failed, err = %d\n", -n); err = -ENOTCONN; - goto out; + goto out_free; } n = os_read_file(pri->control, sun, sizeof(*sun)); @@ -106,12 +106,14 @@ static int connect_to_switch(struct daemon_data *pri) printk("daemon_open : read of data socket failed, err = %d\n", -n); err = -ENOTCONN; - goto out_close; + goto out_free; } pri->data_addr = sun; return(fd); + out_free: + kfree(sun); out_close: os_close_file(fd); out: diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index f0b888f..3296e86 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -76,13 +76,6 @@ static void fd_close(int fd, void *d) } } -static int fd_console_write(int fd, const char *buf, int n, void *d) -{ - struct fd_chan *data = d; - - return(generic_console_write(fd, buf, n, &data->tt)); -} - struct chan_ops fd_ops = { .type = "fd", .init = fd_init, @@ -90,7 +83,7 @@ struct chan_ops fd_ops = { .close = fd_close, .read = generic_read, .write = generic_write, - .console_write = fd_console_write, + .console_write = generic_console_write, .window_size = generic_window_size, .free = generic_free, .winch = 1, diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 5db136e..afe85bf 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -54,7 +54,7 @@ static int mcast_open(void *data) struct mcast_data *pri = data; struct sockaddr_in *sin = pri->mcast_addr; struct ip_mreq mreq; - int fd, yes = 1, err = 0; + int fd, yes = 1, err = -EINVAL; if ((sin->sin_addr.s_addr == 0) || (sin->sin_port == 0)) @@ -63,40 +63,40 @@ static int mcast_open(void *data) fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0){ + err = -errno; printk("mcast_open : data socket failed, errno = %d\n", errno); - err = -errno; goto out; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) { + err = -errno; printk("mcast_open: SO_REUSEADDR failed, errno = %d\n", errno); - err = -errno; goto out_close; } /* set ttl according to config */ if (setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &pri->ttl, sizeof(pri->ttl)) < 0) { + err = -errno; printk("mcast_open: IP_MULTICAST_TTL failed, error = %d\n", errno); - err = -errno; goto out_close; } /* set LOOP, so data does get fed back to local sockets */ if (setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &yes, sizeof(yes)) < 0) { + err = -errno; printk("mcast_open: IP_MULTICAST_LOOP failed, error = %d\n", errno); - err = -errno; goto out_close; } /* bind socket to mcast address */ if (bind(fd, (struct sockaddr *) sin, sizeof(*sin)) < 0) { - printk("mcast_open : data bind failed, errno = %d\n", errno); err = -errno; + printk("mcast_open : data bind failed, errno = %d\n", errno); goto out_close; } @@ -105,22 +105,22 @@ static int mcast_open(void *data) mreq.imr_interface.s_addr = 0; if (setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { + err = -errno; printk("mcast_open: IP_ADD_MEMBERSHIP failed, error = %d\n", errno); printk("There appears not to be a multicast-capable network " "interface on the host.\n"); printk("eth0 should be configured in order to use the " "multicast transport.\n"); - err = -errno; - goto out_close; + goto out_close; } return fd; out_close: - os_close_file(fd); + os_close_file(fd); out: - return err; + return err; } static void mcast_close(int fd, void *data) diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 4cf31a2..84c73a3 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -268,9 +268,10 @@ void uml_net_user_timer_expire(unsigned long _conn) static DEFINE_SPINLOCK(devices_lock); static struct list_head devices = LIST_HEAD_INIT(devices); -static struct device_driver uml_net_driver = { - .name = DRIVER_NAME, - .bus = &platform_bus_type, +static struct platform_driver uml_net_driver = { + .driver = { + .name = DRIVER_NAME, + }, }; static int driver_registered; @@ -317,7 +318,7 @@ static int eth_configure(int n, void *init, char *mac, /* sysfs register */ if (!driver_registered) { - driver_register(¨_net_driver); + platform_driver_register(¨_net_driver); driver_registered = 1; } device->pdev.id = n; diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index ed4a1a6..c43e8bb 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -100,13 +100,6 @@ static void port_close(int fd, void *d) os_close_file(fd); } -static int port_console_write(int fd, const char *buf, int n, void *d) -{ - struct port_chan *data = d; - - return(generic_console_write(fd, buf, n, &data->tt)); -} - struct chan_ops port_ops = { .type = "port", .init = port_init, @@ -114,7 +107,7 @@ struct chan_ops port_ops = { .close = port_close, .read = generic_read, .write = generic_write, - .console_write = port_console_write, + .console_write = generic_console_write, .window_size = generic_window_size, .free = port_free, .winch = 1, diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 0306a1b..1c555c3 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -118,13 +118,6 @@ static int pty_open(int input, int output, int primary, void *d, return(fd); } -static int pty_console_write(int fd, const char *buf, int n, void *d) -{ - struct pty_chan *data = d; - - return(generic_console_write(fd, buf, n, &data->tt)); -} - struct chan_ops pty_ops = { .type = "pty", .init = pty_chan_init, @@ -132,7 +125,7 @@ struct chan_ops pty_ops = { .close = generic_close, .read = generic_read, .write = generic_write, - .console_write = pty_console_write, + .console_write = generic_console_write, .window_size = generic_window_size, .free = generic_free, .winch = 0, @@ -145,7 +138,7 @@ struct chan_ops pts_ops = { .close = generic_close, .read = generic_read, .write = generic_write, - .console_write = pty_console_write, + .console_write = generic_console_write, .window_size = generic_window_size, .free = generic_free, .winch = 0, diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index 6fbb670..94c9265 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -60,13 +60,6 @@ static int tty_open(int input, int output, int primary, void *d, return(fd); } -static int tty_console_write(int fd, const char *buf, int n, void *d) -{ - struct tty_chan *data = d; - - return(generic_console_write(fd, buf, n, &data->tt)); -} - struct chan_ops tty_ops = { .type = "tty", .init = tty_chan_init, @@ -74,7 +67,7 @@ struct chan_ops tty_ops = { .close = generic_close, .read = generic_read, .write = generic_write, - .console_write = tty_console_write, + .console_write = generic_console_write, .window_size = generic_window_size, .free = generic_free, .winch = 0, diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index b2c8625..9389891 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -823,9 +823,10 @@ static int ubd_mc_init(void) __initcall(ubd_mc_init); -static struct device_driver ubd_driver = { - .name = DRIVER_NAME, - .bus = &platform_bus_type, +static struct platform_driver ubd_driver = { + .driver = { + .name = DRIVER_NAME, + }, }; int ubd_init(void) @@ -850,7 +851,7 @@ int ubd_init(void) if (register_blkdev(fake_major, "ubd")) return -1; } - driver_register(&ubd_driver); + platform_driver_register(&ubd_driver); for (i = 0; i < MAX_DEV; i++) ubd_add(i); return 0; diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index b530f1a..aaa63666 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -194,13 +194,6 @@ static void xterm_free(void *d) free(d); } -static int xterm_console_write(int fd, const char *buf, int n, void *d) -{ - struct xterm_chan *data = d; - - return(generic_console_write(fd, buf, n, &data->tt)); -} - struct chan_ops xterm_ops = { .type = "xterm", .init = xterm_init, @@ -208,7 +201,7 @@ struct chan_ops xterm_ops = { .close = xterm_close, .read = generic_read, .write = generic_write, - .console_write = xterm_console_write, + .console_write = generic_console_write, .window_size = generic_window_size, .free = xterm_free, .winch = 1, diff --git a/arch/um/include/chan_user.h b/arch/um/include/chan_user.h index f77d9aa..659bb3c 100644 --- a/arch/um/include/chan_user.h +++ b/arch/um/include/chan_user.h @@ -25,7 +25,7 @@ struct chan_ops { void (*close)(int, void *); int (*read)(int, char *, void *); int (*write)(int, const char *, int, void *); - int (*console_write)(int, const char *, int, void *); + int (*console_write)(int, const char *, int); int (*window_size)(int, void *, unsigned short *, unsigned short *); void (*free)(void *); int winch; @@ -37,7 +37,7 @@ extern struct chan_ops fd_ops, null_ops, port_ops, pts_ops, pty_ops, tty_ops, extern void generic_close(int fd, void *unused); extern int generic_read(int fd, char *c_out, void *unused); extern int generic_write(int fd, const char *buf, int n, void *unused); -extern int generic_console_write(int fd, const char *buf, int n, void *state); +extern int generic_console_write(int fd, const char *buf, int n); extern int generic_window_size(int fd, void *unused, unsigned short *rows_out, unsigned short *cols_out); extern void generic_free(void *data); diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h index a49ceb1..b492b12 100644 --- a/arch/um/include/sysdep-i386/stub.h +++ b/arch/um/include/sysdep-i386/stub.h @@ -6,8 +6,12 @@ #ifndef __SYSDEP_STUB_H #define __SYSDEP_STUB_H +#include <sys/mman.h> #include <asm/ptrace.h> #include <asm/unistd.h> +#include "stub-data.h" +#include "kern_constants.h" +#include "uml-config.h" extern void stub_segv_handler(int sig); extern void stub_clone_handler(void); @@ -16,6 +20,15 @@ extern void stub_clone_handler(void); #define STUB_MMAP_NR __NR_mmap2 #define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT) +static inline long stub_syscall0(long syscall) +{ + long ret; + + __asm__ volatile ("int $0x80" : "=a" (ret) : "0" (syscall)); + + return ret; +} + static inline long stub_syscall1(long syscall, long arg1) { long ret; @@ -67,23 +80,22 @@ static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, return ret; } -static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, - long arg4, long arg5, long arg6) +static inline void trap_myself(void) { - long ret; - - __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; " - "int $0x80 ; pop %%ebp" - : "=a" (ret) - : "g" (syscall), "b" (arg1), "c" (arg2), "d" (arg3), - "S" (arg4), "D" (arg5), "0" (arg6)); - - return ret; + __asm("int3"); } -static inline void trap_myself(void) +static inline void remap_stack(int fd, unsigned long offset) { - __asm("int3"); + __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;" + "movl %7, %%ebx ; movl %%eax, (%%ebx)" + : : "g" (STUB_MMAP_NR), "b" (UML_CONFIG_STUB_DATA), + "c" (UM_KERN_PAGE_SIZE), + "d" (PROT_READ | PROT_WRITE), + "S" (MAP_FIXED | MAP_SHARED), "D" (fd), + "a" (offset), + "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) + : "memory"); } #endif diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h index 2bd6e7a..92e989f 100644 --- a/arch/um/include/sysdep-x86_64/stub.h +++ b/arch/um/include/sysdep-x86_64/stub.h @@ -6,9 +6,12 @@ #ifndef __SYSDEP_STUB_H #define __SYSDEP_STUB_H -#include <asm/ptrace.h> +#include <sys/mman.h> #include <asm/unistd.h> #include <sysdep/ptrace_user.h> +#include "stub-data.h" +#include "kern_constants.h" +#include "uml-config.h" extern void stub_segv_handler(int sig); extern void stub_clone_handler(void); @@ -20,6 +23,17 @@ extern void stub_clone_handler(void); #define __syscall_clobber "r11","rcx","memory" #define __syscall "syscall" +static inline long stub_syscall0(long syscall) +{ + long ret; + + __asm__ volatile (__syscall + : "=a" (ret) + : "0" (syscall) : __syscall_clobber ); + + return ret; +} + static inline long stub_syscall2(long syscall, long arg1, long arg2) { long ret; @@ -71,23 +85,23 @@ static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, return ret; } -static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, - long arg4, long arg5, long arg6) +static inline void trap_myself(void) { - long ret; - - __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " - "movq %7, %%r9; " __syscall : "=a" (ret) - : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3), - "g" (arg4), "g" (arg5), "g" (arg6) - : __syscall_clobber, "r10", "r8", "r9" ); - - return ret; + __asm("int3"); } -static inline void trap_myself(void) +static inline void remap_stack(long fd, unsigned long offset) { - __asm("int3"); + __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; " + "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; " + "movq %%rax, (%%rbx)": + : "a" (STUB_MMAP_NR), "D" (UML_CONFIG_STUB_DATA), + "S" (UM_KERN_PAGE_SIZE), + "d" (PROT_READ | PROT_WRITE), + "g" (MAP_FIXED | MAP_SHARED), "g" (fd), + "g" (offset), + "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) + : __syscall_clobber, "r10", "r8", "r9" ); } #endif diff --git a/arch/um/include/um_uaccess.h b/arch/um/include/um_uaccess.h index 84c0868..4567f1e 100644 --- a/arch/um/include/um_uaccess.h +++ b/arch/um/include/um_uaccess.h @@ -17,8 +17,27 @@ #include "uaccess-skas.h" #endif +#include "asm/fixmap.h" + +#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) && \ + ((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) \ - CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, 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) || \ + CHOOSE_MODE_PROC(access_ok_tt, access_ok_skas, type, addr, size))) static inline int copy_from_user(void *to, const void __user *from, int n) { diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 4dc55f1..47b812b 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -9,18 +9,23 @@ #include "stub-data.h" #include "uml-config.h" #include "sysdep/stub.h" +#include "kern_constants.h" /* This is in a separate file because it needs to be compiled with any * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled + * + * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize + * on some systems. */ + void __attribute__ ((__section__ (".__syscall_stub"))) stub_clone_handler(void) { + struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA; long err; - struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, - UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 - + UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); if(err != 0) goto out; @@ -29,16 +34,21 @@ stub_clone_handler(void) if(err) goto out; - err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, - (long) &from->timer, 0); + err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, + (long) &data->timer, 0); if(err) goto out; - err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, - from->fd, from->offset); + remap_stack(data->fd, data->offset); + goto done; + out: - /* save current result. Parent: pid; child: retcode of mmap */ - from->err = err; + /* save current result. + * Parent: pid; + * child: retcode of mmap already saved and it jumps around this + * assignment + */ + data->err = err; + done: trap_myself(); } diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 7da0c2d..64516c5 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h @@ -7,16 +7,9 @@ #define __SKAS_UACCESS_H #include "asm/errno.h" -#include "asm/fixmap.h" -#define access_ok_skas(type, addr, size) \ - ((segment_eq(get_fs(), KERNEL_DS)) || \ - (((unsigned long) (addr) < TASK_SIZE) && \ - ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \ - ((type == VERIFY_READ ) && \ - ((unsigned long) (addr) >= FIXADDR_USER_START) && \ - ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ - ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) +/* No SKAS-specific checking. */ +#define access_ok_skas(type, addr, size) 0 extern int copy_from_user_skas(void *to, const void __user *from, int n); extern int copy_to_user_skas(void __user *to, const void *from, int n); diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 7519528..a5a4752 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -143,7 +143,7 @@ int copy_from_user_skas(void *to, const void __user *from, int n) return(0); } - return(access_ok_skas(VERIFY_READ, from, n) ? + return(access_ok(VERIFY_READ, from, n) ? buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): n); } @@ -164,7 +164,7 @@ int copy_to_user_skas(void __user *to, const void *from, int n) return(0); } - return(access_ok_skas(VERIFY_WRITE, to, n) ? + return(access_ok(VERIFY_WRITE, to, n) ? buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : n); } @@ -193,7 +193,7 @@ int strncpy_from_user_skas(char *dst, const char __user *src, int count) return(strnlen(dst, count)); } - if(!access_ok_skas(VERIFY_READ, src, 1)) + if(!access_ok(VERIFY_READ, src, 1)) return(-EFAULT); n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, @@ -221,7 +221,7 @@ int clear_user_skas(void __user *mem, int len) return(0); } - return(access_ok_skas(VERIFY_WRITE, mem, len) ? + return(access_ok(VERIFY_WRITE, mem, len) ? buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); } diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 95c8f87..0d4c10a 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -95,7 +95,16 @@ survive: pte = pte_offset_kernel(pmd, address); } while(!pte_present(*pte)); err = 0; + /* The below warning was added in place of + * pte_mkyoung(); if (is_write) pte_mkdirty(); + * If it's triggered, we'd see normally a hang here (a clean pte is + * marked read-only to emulate the dirty bit). + * However, the generic code can mark a PTE writable but clean on a + * concurrent read fault, triggering this harmlessly. So comment it out. + */ +#if 0 WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); +#endif flush_tlb_page(vma, address); out: up_read(&mm->mmap_sem); diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index dc2ebfa..b9bfe9c 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h @@ -19,19 +19,13 @@ extern unsigned long end_vm; extern unsigned long uml_physmem; -#define under_task_size(addr, size) \ - (((unsigned long) (addr) < TASK_SIZE) && \ - (((unsigned long) (addr) + (size)) < TASK_SIZE)) - #define is_stack(addr, size) \ (((unsigned long) (addr) < STACK_TOP) && \ ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ (((unsigned long) (addr) + (size)) <= STACK_TOP)) #define access_ok_tt(type, addr, size) \ - ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ - (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ - (under_task_size(addr, size) || is_stack(addr, size)))) + (is_stack(addr, size)) extern unsigned long get_fault_addr(void); diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index a72aa63..1cb6072 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c @@ -8,7 +8,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n) { - if(!access_ok_tt(VERIFY_READ, from, n)) + if(!access_ok(VERIFY_READ, from, n)) return(n); return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, @@ -17,7 +17,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n) int copy_to_user_tt(void __user *to, const void *from, int n) { - if(!access_ok_tt(VERIFY_WRITE, to, n)) + if(!access_ok(VERIFY_WRITE, to, n)) return(n); return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, @@ -28,7 +28,7 @@ int strncpy_from_user_tt(char *dst, const char __user *src, int count) { int n; - if(!access_ok_tt(VERIFY_READ, src, 1)) + if(!access_ok(VERIFY_READ, src, 1)) return(-EFAULT); n = __do_strncpy_from_user(dst, src, count, @@ -47,7 +47,7 @@ int __clear_user_tt(void __user *mem, int len) int clear_user_tt(void __user *mem, int len) { - if(!access_ok_tt(VERIFY_WRITE, mem, len)) + if(!access_ok(VERIFY_WRITE, mem, len)) return(len); return(__do_clear_user(mem, len, ¤t->thread.fault_addr, diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 37517d4..29a9e3f 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -116,16 +116,16 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode, if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); if (exit_with == 2) - printk("check_ptrace : child exited with status 2. " + printf("check_ptrace : child exited with status 2. " "Serious trouble happening! Try updating your " "host skas patch!\nDisabling SYSEMU support."); - printk("check_ptrace : child exited with exitcode %d, while " + printf("check_ptrace : child exited with exitcode %d, while " "expecting %d; status 0x%x", exit_with, exitcode, status); if (mustpanic) panic("\n"); else - printk("\n"); + printf("\n"); ret = -1; } @@ -183,7 +183,7 @@ static void __init check_sysemu(void) void *stack; int pid, n, status, count=0; - printk("Checking syscall emulation patch for ptrace..."); + printf("Checking syscall emulation patch for ptrace..."); sysemu_supported = 0; pid = start_ptraced_child(&stack); @@ -207,10 +207,10 @@ static void __init check_sysemu(void) goto fail_stopped; sysemu_supported = 1; - printk("OK\n"); + printf("OK\n"); set_using_sysemu(!force_sysemu_disabled); - printk("Checking advanced syscall emulation patch for ptrace..."); + printf("Checking advanced syscall emulation patch for ptrace..."); pid = start_ptraced_child(&stack); if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, @@ -246,7 +246,7 @@ static void __init check_sysemu(void) goto fail_stopped; sysemu_supported = 2; - printk("OK\n"); + printf("OK\n"); if ( !force_sysemu_disabled ) set_using_sysemu(sysemu_supported); @@ -255,7 +255,7 @@ static void __init check_sysemu(void) fail: stop_ptraced_child(pid, stack, 1, 0); fail_stopped: - printk("missing\n"); + printf("missing\n"); } static void __init check_ptrace(void) @@ -263,7 +263,7 @@ static void __init check_ptrace(void) void *stack; int pid, syscall, n, status; - printk("Checking that ptrace can change system call numbers..."); + printf("Checking that ptrace can change system call numbers..."); pid = start_ptraced_child(&stack); if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) @@ -292,7 +292,7 @@ static void __init check_ptrace(void) } } stop_ptraced_child(pid, stack, 0, 1); - printk("OK\n"); + printf("OK\n"); check_sysemu(); } @@ -472,6 +472,8 @@ int can_do_skas(void) int have_devanon = 0; +/* Runs on boot kernel stack - already safe to use printk. */ + void check_devanon(void) { int fd; diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 56d3f87..8da6ab3 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -34,6 +34,11 @@ EXPORT_SYMBOL(strstr); int sym(void); \ EXPORT_SYMBOL(sym); +extern void readdir64(void) __attribute__((weak)); +EXPORT_SYMBOL(readdir64); +extern void truncate64(void) __attribute__((weak)); +EXPORT_SYMBOL(truncate64); + #ifdef SUBARCH_i386 EXPORT_SYMBOL(vsyscall_ehdr); EXPORT_SYMBOL(vsyscall_end); diff --git a/arch/um/scripts/Makefile.rules b/arch/um/scripts/Makefile.rules index b3fbf12..2e41cab 100644 --- a/arch/um/scripts/Makefile.rules +++ b/arch/um/scripts/Makefile.rules @@ -21,11 +21,6 @@ define unprofile endef -# The stubs and unmap.o can't try to call mcount or update basic block data -define unprofile - $(patsubst -pg,,$(patsubst -fprofile-arcs -ftest-coverage,,$(1))) -endef - # cmd_make_link checks to see if the $(foo-dir) variable starts with a /. If # so, it's considered to be a path relative to $(srcdir) rather than # $(srcdir)/arch/$(SUBARCH). This is because x86_64 wants to get ldt.c from diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 6dfeb70f..f5fd5b0 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile @@ -1,11 +1,13 @@ -obj-y = bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ - ptrace_user.o semaphore.o signal.o sigcontext.o stub.o stub_segv.o \ - syscalls.o sysrq.o sys_call_table.o +obj-y := bitops.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ + ptrace_user.o semaphore.o signal.o sigcontext.o syscalls.o sysrq.o \ + sys_call_table.o + +obj-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o obj-$(CONFIG_HIGHMEM) += highmem.o obj-$(CONFIG_MODULES) += module.o -USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o +USER_OBJS := bugs.o ptrace_user.o sigcontext.o fault.o stub_segv.o SYMLINKS = bitops.c semaphore.c highmem.c module.c diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 6360f1c..17746b4 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -228,7 +228,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) size = LDT_ENTRY_SIZE*LDT_DIRECT_ENTRIES; if(size > bytecount) size = bytecount; - if(copy_to_user(ptr, ldt->entries, size)) + if(copy_to_user(ptr, ldt->u.entries, size)) err = -EFAULT; bytecount -= size; ptr += size; @@ -239,7 +239,7 @@ static int read_ldt(void __user * ptr, unsigned long bytecount) size = PAGE_SIZE; if(size > bytecount) size = bytecount; - if(copy_to_user(ptr, ldt->pages[i], size)){ + if(copy_to_user(ptr, ldt->u.pages[i], size)){ err = -EFAULT; break; } @@ -321,10 +321,11 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) i*LDT_ENTRIES_PER_PAGE <= ldt_info.entry_number; i++){ if(i == 0) - memcpy(&entry0, ldt->entries, sizeof(entry0)); - ldt->pages[i] = (struct ldt_entry *) - __get_free_page(GFP_KERNEL|__GFP_ZERO); - if(!ldt->pages[i]){ + memcpy(&entry0, ldt->u.entries, + sizeof(entry0)); + ldt->u.pages[i] = (struct ldt_entry *) + __get_free_page(GFP_KERNEL|__GFP_ZERO); + if(!ldt->u.pages[i]){ err = -ENOMEM; /* Undo the change in host */ memset(&ldt_info, 0, sizeof(ldt_info)); @@ -332,8 +333,9 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) goto out_unlock; } if(i == 0) { - memcpy(ldt->pages[0], &entry0, sizeof(entry0)); - memcpy(ldt->pages[0]+1, ldt->entries+1, + memcpy(ldt->u.pages[0], &entry0, + sizeof(entry0)); + memcpy(ldt->u.pages[0]+1, ldt->u.entries+1, sizeof(entry0)*(LDT_DIRECT_ENTRIES-1)); } ldt->entry_count = (i + 1) * LDT_ENTRIES_PER_PAGE; @@ -343,9 +345,9 @@ static int write_ldt(void __user * ptr, unsigned long bytecount, int func) ldt->entry_count = ldt_info.entry_number + 1; if(ldt->entry_count <= LDT_DIRECT_ENTRIES) - ldt_p = ldt->entries + ldt_info.entry_number; + ldt_p = ldt->u.entries + ldt_info.entry_number; else - ldt_p = ldt->pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + + ldt_p = ldt->u.pages[ldt_info.entry_number/LDT_ENTRIES_PER_PAGE] + ldt_info.entry_number%LDT_ENTRIES_PER_PAGE; if(ldt_info.base_addr == 0 && ldt_info.limit == 0 && @@ -501,8 +503,8 @@ long init_new_ldt(struct mmu_context_skas * new_mm, */ down(&from_mm->ldt.semaphore); if(from_mm->ldt.entry_count <= LDT_DIRECT_ENTRIES){ - memcpy(new_mm->ldt.entries, from_mm->ldt.entries, - sizeof(new_mm->ldt.entries)); + memcpy(new_mm->ldt.u.entries, from_mm->ldt.u.entries, + sizeof(new_mm->ldt.u.entries)); } else{ i = from_mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; @@ -512,9 +514,10 @@ long init_new_ldt(struct mmu_context_skas * new_mm, err = -ENOMEM; break; } - new_mm->ldt.pages[i] = (struct ldt_entry*)page; - memcpy(new_mm->ldt.pages[i], - from_mm->ldt.pages[i], PAGE_SIZE); + new_mm->ldt.u.pages[i] = + (struct ldt_entry *) page; + memcpy(new_mm->ldt.u.pages[i], + from_mm->ldt.u.pages[i], PAGE_SIZE); } } new_mm->ldt.entry_count = from_mm->ldt.entry_count; @@ -532,7 +535,7 @@ void free_ldt(struct mmu_context_skas * mm) if(!ptrace_ldt && mm->ldt.entry_count > LDT_DIRECT_ENTRIES){ i = mm->ldt.entry_count / LDT_ENTRIES_PER_PAGE; while(i-- > 0){ - free_page((long )mm->ldt.pages[i]); + free_page((long )mm->ldt.u.pages[i]); } } mm->ldt.entry_count = 0; diff --git a/arch/um/sys-i386/stub_segv.c b/arch/um/sys-i386/stub_segv.c index 1e88b27..a37f672 100644 --- a/arch/um/sys-i386/stub_segv.c +++ b/arch/um/sys-i386/stub_segv.c @@ -3,9 +3,11 @@ * Licensed under the GPL */ -#include <asm/signal.h> +#include <signal.h> +#include <sys/select.h> /* The only way I can see to get sigset_t */ #include <asm/unistd.h> #include "uml-config.h" +#include "sysdep/stub.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" @@ -13,13 +15,14 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) { struct sigcontext *sc = (struct sigcontext *) (&sig + 1); + int pid; GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), sc); - __asm__("movl %0, %%eax ; int $0x80": : "g" (__NR_getpid)); - __asm__("movl %%eax, %%ebx ; movl %0, %%eax ; movl %1, %%ecx ;" - "int $0x80": : "g" (__NR_kill), "g" (SIGUSR1)); + pid = stub_syscall0(__NR_getpid); + stub_syscall2(__NR_kill, pid, SIGUSR1); + /* Load pointer to sigcontext into esp, since we need to leave * the stack in its original form when we do the sigreturn here, by * hand. diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index ea977df..a351091 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile @@ -6,13 +6,14 @@ #XXX: why into lib-y? lib-y = bitops.o bugs.o csum-partial.o delay.o fault.o ldt.o mem.o memcpy.o \ - ptrace.o ptrace_user.o sigcontext.o signal.o stub.o \ - stub_segv.o syscalls.o syscall_table.o sysrq.o thunk.o + ptrace.o ptrace_user.o sigcontext.o signal.o syscalls.o \ + syscall_table.o sysrq.o thunk.o +lib-$(CONFIG_MODE_SKAS) += stub.o stub_segv.o obj-y := ksyms.o obj-$(CONFIG_MODULES) += module.o um_module.o -USER_OBJS := ptrace_user.o sigcontext.o +USER_OBJS := ptrace_user.o sigcontext.o stub_segv.o SYMLINKS = bitops.c csum-copy.S csum-partial.c csum-wrappers.c ldt.c memcpy.S \ thunk.S module.c diff --git a/arch/um/sys-x86_64/stub_segv.c b/arch/um/sys-x86_64/stub_segv.c index d1e53bd..a270995 100644 --- a/arch/um/sys-x86_64/stub_segv.c +++ b/arch/um/sys-x86_64/stub_segv.c @@ -3,14 +3,14 @@ * Licensed under the GPL */ -#include <asm/signal.h> +#include <stddef.h> +#include <signal.h> #include <linux/compiler.h> #include <asm/unistd.h> -#include <asm/ucontext.h> #include "uml-config.h" #include "sysdep/sigcontext.h" #include "sysdep/faultinfo.h" -#include <stddef.h> +#include "sysdep/stub.h" /* Copied from sys-x86_64/signal.c - Can't find an equivalent definition * in the libc headers anywhere. @@ -31,21 +31,21 @@ void __attribute__ ((__section__ (".__syscall_stub"))) stub_segv_handler(int sig) { struct ucontext *uc; + int pid; __asm__("movq %%rdx, %0" : "=g" (uc) :); GET_FAULTINFO_FROM_SC(*((struct faultinfo *) UML_CONFIG_STUB_DATA), &uc->uc_mcontext); - __asm__("movq %0, %%rax ; syscall": : "g" (__NR_getpid)); - __asm__("movq %%rax, %%rdi ; movq %0, %%rax ; movq %1, %%rsi ;" - "syscall": : "g" (__NR_kill), "g" (SIGUSR1) : - "%rdi", "%rax", "%rsi"); + pid = stub_syscall0(__NR_getpid); + stub_syscall2(__NR_kill, pid, SIGUSR1); + /* sys_sigreturn expects that the stack pointer will be 8 bytes into * the signal frame. So, we use the ucontext pointer, which we know * already, to get the signal frame pointer, and add 8 to that. */ - __asm__("movq %0, %%rsp": : + __asm__("movq %0, %%rsp; movq %1, %%rax ; syscall": : "g" ((unsigned long) container_of(uc, struct rt_sigframe, - uc) + 8)); - __asm__("movq %0, %%rax ; syscall" : : "g" (__NR_rt_sigreturn)); + uc) + 8), + "g" (__NR_rt_sigreturn)); } |