From 3787fa6df5bb6e80b274ff805e10b6a9bfc4588c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 21 May 2008 06:32:11 +0100 Subject: fix include order in sys-i386/registers.c We want sys/ptrace.h before any includes of linux/ptrace.h and asm/user.h pulls the latter. Signed-off-by: Al Viro Acked-by: Jeff Dike Signed-off-by: Linus Torvalds --- arch/um/os-Linux/sys-i386/registers.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um/os-Linux') diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index c6183e7aec3..b487cbead1b 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -5,6 +5,7 @@ */ #include +#include #include #include "kern_constants.h" #include "longjmp.h" -- cgit v1.2.3-70-g09d2 From 06e1e4ffbd1932e288839b3140cda6b8141eb684 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 5 Jun 2008 22:46:10 -0700 Subject: uml: deal with host time going backwards Protection against the host's time going backwards (eg, ntp activity on the host) by keeping track of the time at the last tick and if it's greater than the current time, keep time stopped until the host catches up. Cc: Nix Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/time.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/um/os-Linux') diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index bee98f466d6..dec5678fc17 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -106,6 +106,10 @@ static void deliver_alarm(void) unsigned long long this_tick = os_nsecs(); int one_tick = UM_NSEC_PER_SEC / UM_HZ; + /* Protection against the host's time going backwards */ + if ((last_tick != 0) && (this_tick < last_tick)) + this_tick = last_tick; + if (last_tick == 0) last_tick = this_tick - one_tick; @@ -148,6 +152,9 @@ static int after_sleep_interval(struct timespec *ts) start_usecs = usec; start_usecs -= skew / UM_NSEC_PER_USEC; + if (start_usecs < 0) + start_usecs = 0; + tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC, .tv_usec = start_usecs % UM_USEC_PER_SEC }); interval = ((struct itimerval) { { 0, usec }, tv }); -- cgit v1.2.3-70-g09d2 From 40fb16a360d9c6459afee91dc793c1e3374feb94 Mon Sep 17 00:00:00 2001 From: Tom Spink Date: Thu, 5 Jun 2008 22:46:12 -0700 Subject: uml: deal with inaccessible address space start This patch makes os_get_task_size locate the bottom of the address space, as well as the top. This is for systems which put a lower limit on mmap addresses. It works by manually scanning pages from zero onwards until a valid page is found. Because the bottom of the address space may not be zero, it's not sufficient to assume the top of the address space is the size of the address space. The size is the difference between the top address and bottom address. [jdike@addtoit.com: changed the name to reflect that this function is supposed to return the top of the process address space, not its size and changed the return value to reflect that. Also some minor formatting changes] Signed-off-by: Tom Spink Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/os.h | 2 +- arch/um/kernel/um_arch.c | 2 +- arch/um/os-Linux/sys-i386/task_size.c | 31 +++++++++++++++++++++++-------- arch/um/os-Linux/sys-x86_64/task_size.c | 2 +- 4 files changed, 26 insertions(+), 11 deletions(-) (limited to 'arch/um/os-Linux') diff --git a/arch/um/include/os.h b/arch/um/include/os.h index e2716ac8889..db5be46e3e1 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -299,6 +299,6 @@ extern int os_arch_prctl(int pid, int code, unsigned long *addr); extern int get_pty(void); /* sys-$ARCH/task_size.c */ -extern unsigned long os_get_task_size(void); +extern unsigned long os_get_top_address(void); #endif diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 9db85b2ce69..8d84250324b 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -274,7 +274,7 @@ int __init linux_main(int argc, char **argv) if (have_root == 0) add_arg(DEFAULT_COMMAND_LINE); - host_task_size = os_get_task_size(); + host_task_size = os_get_top_address(); /* * TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps * out diff --git a/arch/um/os-Linux/sys-i386/task_size.c b/arch/um/os-Linux/sys-i386/task_size.c index ccb49b0aff5..be04c1e183b 100644 --- a/arch/um/os-Linux/sys-i386/task_size.c +++ b/arch/um/os-Linux/sys-i386/task_size.c @@ -63,7 +63,7 @@ static int page_ok(unsigned long page) return ok; } -unsigned long os_get_task_size(void) +unsigned long os_get_top_address(void) { struct sigaction sa, old; unsigned long bottom = 0; @@ -76,9 +76,9 @@ unsigned long os_get_task_size(void) * hosts, but shouldn't hurt otherwise. */ unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT; - unsigned long test; + unsigned long test, original; - printf("Locating the top of the address space ... "); + printf("Locating the bottom of the address space ... "); fflush(stdout); /* @@ -89,16 +89,31 @@ unsigned long os_get_task_size(void) sigemptyset(&sa.sa_mask); sa.sa_flags = SA_NODEFER; if (sigaction(SIGSEGV, &sa, &old)) { - perror("os_get_task_size"); + perror("os_get_top_address"); exit(1); } - if (!page_ok(bottom)) { - fprintf(stderr, "Address 0x%x no good?\n", - bottom << UM_KERN_PAGE_SHIFT); + /* Manually scan the address space, bottom-up, until we find + * the first valid page (or run out of them). + */ + for (bottom = 0; bottom < top; bottom++) { + if (page_ok(bottom)) + break; + } + + /* If we've got this far, we ran out of pages. */ + if (bottom == top) { + fprintf(stderr, "Unable to determine bottom of address " + "space.\n"); exit(1); } + printf("0x%x\n", bottom << UM_KERN_PAGE_SHIFT); + printf("Locating the top of the address space ... "); + fflush(stdout); + + original = bottom; + /* This could happen with a 4G/4G split */ if (page_ok(top)) goto out; @@ -114,7 +129,7 @@ unsigned long os_get_task_size(void) out: /* Restore the old SIGSEGV handling */ if (sigaction(SIGSEGV, &old, NULL)) { - perror("os_get_task_size"); + perror("os_get_top_address"); exit(1); } top <<= UM_KERN_PAGE_SHIFT; diff --git a/arch/um/os-Linux/sys-x86_64/task_size.c b/arch/um/os-Linux/sys-x86_64/task_size.c index fad6f57f8ee..26a0dd1f349 100644 --- a/arch/um/os-Linux/sys-x86_64/task_size.c +++ b/arch/um/os-Linux/sys-x86_64/task_size.c @@ -1,4 +1,4 @@ -unsigned long os_get_task_size(unsigned long shift) +unsigned long os_get_top_address(unsigned long shift) { /* The old value of CONFIG_TOP_ADDR */ return 0x7fc0000000; -- cgit v1.2.3-70-g09d2 From 3d5ede6f776bdb1483bcd086f79c3bf41fed3865 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 5 Jun 2008 22:46:13 -0700 Subject: uml: stub needs to tolerate SIGWINCH We lost the marking of SIGWINCH as being OK to receive during stub execution, causing a panic should that happen. Cc: Benedict Verheyen Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/skas/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/um/os-Linux') diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 6be028ca181..172ad8f72e1 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -55,7 +55,7 @@ static int ptrace_dump_regs(int pid) * Signals that are OK to receive in the stub - we'll just continue it. * SIGWINCH will happen when UML is inside a detached screen. */ -#define STUB_SIG_MASK (1 << SIGVTALRM) +#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH)) /* Signals that the stub will finish with - anything else is an error */ #define STUB_DONE_MASK (1 << SIGTRAP) -- cgit v1.2.3-70-g09d2 From b6d8adf477439e7086224bc9674c6b6638780783 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 5 Jun 2008 22:46:14 -0700 Subject: uml: PATH_MAX needs limits.h Include limits.h to get a definition of PATH_MAX. Signed-off-by: Ingo Molnar Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/helper.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/um/os-Linux') diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index 74ca7aabf4e..30860b89ec5 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include "kern_constants.h" -- cgit v1.2.3-70-g09d2 From 14c8a77e1bbd693446dad297d2ae2dd22f187e4f Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 12 Jun 2008 15:21:40 -0700 Subject: uml: remove include of asm/user.h I allowed an include of asm/user.h to sneak back in. This patch replaces it with sys/user.h. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/sys-i386/registers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/um/os-Linux') diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index b487cbead1b..229f7a53d8d 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include "kern_constants.h" #include "longjmp.h" #include "user.h" @@ -76,7 +76,7 @@ int put_fp_registers(int pid, unsigned long *regs) void arch_init_registers(int pid) { - struct user_fxsr_struct fpx_regs; + struct user_fpxregs_struct fpx_regs; int err; err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); -- cgit v1.2.3-70-g09d2 From f1ef9167ca4494a8c6d71d0031c73e9c8841eadd Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Thu, 12 Jun 2008 15:21:41 -0700 Subject: uml: work around broken host PTRACE_SYSEMU Fedora broke PTRACE_SYSEMU again, and UML crashes as a result when it doesn't need to. This patch makes the PTRACE_SYSEMU check fail gracefully and makes UML fall back to PTRACE_SYSCALL. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/start_up.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'arch/um/os-Linux') diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index b4b36e0f2e8..183db26d01b 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -121,8 +121,10 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) { int status, n, ret = 0; - if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) - fatal_perror("stop_ptraced_child : ptrace failed"); + if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) { + perror("stop_ptraced_child : ptrace failed"); + return -1; + } CATCH_EINTR(n = waitpid(pid, &status, 0)); if (!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) { int exit_with = WEXITSTATUS(status); @@ -212,7 +214,7 @@ static void __init check_sysemu(void) if (n < 0) fatal_perror("check_sysemu : wait failed"); if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) - fatal("check_sysemu : expected SIGTRAP, got status = %d", + fatal("check_sysemu : expected SIGTRAP, got status = %d\n", status); if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) @@ -254,9 +256,11 @@ static void __init check_sysemu(void) if (WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))) { - if (!count) - fatal("check_ptrace : SYSEMU_SINGLESTEP " - "doesn't singlestep"); + if (!count) { + non_fatal("check_ptrace : SYSEMU_SINGLESTEP " + "doesn't singlestep"); + goto fail; + } n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); if (n < 0) @@ -266,9 +270,12 @@ static void __init check_sysemu(void) } else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP)) count++; - else - fatal("check_ptrace : expected SIGTRAP or " - "(SIGTRAP | 0x80), got status = %d", status); + else { + non_fatal("check_ptrace : expected SIGTRAP or " + "(SIGTRAP | 0x80), got status = %d\n", + status); + goto fail; + } } if (stop_ptraced_child(pid, 0, 0) < 0) goto fail_stopped; -- cgit v1.2.3-70-g09d2