]> err.no Git - linux-2.6/blobdiff - arch/um/os-Linux/start_up.c
[PATCH] uml: move libc code out of mem_user.c and tempfile.c
[linux-2.6] / arch / um / os-Linux / start_up.c
index a3eab25f3791613b4a2e229bd46b08e51a331140..6af83171ca4eaf2b6ad8e170602d1372d0498906 100644 (file)
@@ -4,18 +4,22 @@
  */
 
 #include <stdio.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <signal.h>
 #include <sched.h>
+#include <fcntl.h>
 #include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
 #include <setjmp.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
+#include <sys/types.h>
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
@@ -25,6 +29,7 @@
 #include "sysdep/sigcontext.h"
 #include "irq_user.h"
 #include "ptrace_user.h"
+#include "mem_user.h"
 #include "time_user.h"
 #include "init.h"
 #include "os.h"
@@ -32,6 +37,8 @@
 #include "choose-mode.h"
 #include "mode.h"
 #include "tempfile.h"
+#include "kern_constants.h"
+
 #ifdef UML_CONFIG_MODE_SKAS
 #include "skas.h"
 #include "skas_ptrace.h"
@@ -161,7 +168,7 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
 static void __init check_sysemu(void)
 {
        void *stack;
-       int pid, syscall, n, status, count=0;
+       int pid, n, status, count=0;
 
        printk("Checking syscall emulation patch for ptrace...");
        sysemu_supported = 0;
@@ -192,6 +199,12 @@ static void __init check_sysemu(void)
 
        printk("Checking advanced syscall emulation patch for ptrace...");
        pid = start_ptraced_child(&stack);
+
+       if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
+                 (void *) PTRACE_O_TRACESYSGOOD) < 0)
+               panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d",
+                     errno);
+
        while(1){
                count++;
                if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
@@ -199,15 +212,10 @@ static void __init check_sysemu(void)
                CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
                if(n < 0)
                        panic("check_ptrace : wait failed, errno = %d", errno);
-               if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-                       panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
-                             "got status = %d", status);
-
-               syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
-                                0);
-               if(syscall == __NR_getpid){
+               if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){
                        if (!count)
-                               panic("check_ptrace : SYSEMU_SINGLESTEP doesn't singlestep");
+                               panic("check_ptrace : SYSEMU_SINGLESTEP "
+                                     "doesn't singlestep");
                        n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
                                   os_getpid());
                        if(n < 0)
@@ -215,6 +223,11 @@ static void __init check_sysemu(void)
                                      "call return, errno = %d", errno);
                        break;
                }
+               else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
+                       count++;
+               else
+                       panic("check_ptrace : expected SIGTRAP or "
+                             "(SIGTRAP|0x80), got status = %d", status);
        }
        if (stop_ptraced_child(pid, stack, 0, 0) < 0)
                goto fail_stopped;
@@ -250,8 +263,8 @@ static void __init check_ptrace(void)
                CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
                if(n < 0)
                        panic("check_ptrace : wait failed, errno = %d", errno);
-               if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP + 0x80))
-                       panic("check_ptrace : expected SIGTRAP + 0x80, "
+               if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|0x80)))
+                       panic("check_ptrace : expected (SIGTRAP|0x80), "
                              "got status = %d", status);
 
                syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
@@ -270,11 +283,64 @@ static void __init check_ptrace(void)
        check_sysemu();
 }
 
+extern int create_tmp_file(unsigned long len);
+
+static void check_tmpexec(void)
+{
+       void *addr;
+       int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+       addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+                   PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+       printf("Checking PROT_EXEC mmap in /tmp...");
+       fflush(stdout);
+       if(addr == MAP_FAILED){
+               err = errno;
+               perror("failed");
+               if(err == EPERM)
+                       printf("/tmp must be not mounted noexec\n");
+               exit(1);
+       }
+       printf("OK\n");
+       munmap(addr, UM_KERN_PAGE_SIZE);
+
+       close(fd);
+}
+
 void os_early_checks(void)
 {
        check_ptrace();
+
+       /* Need to check this early because mmapping happens before the
+        * kernel is running.
+        */
+       check_tmpexec();
+}
+
+static int __init noprocmm_cmd_param(char *str, int* add)
+{
+       proc_mm = 0;
+       return 0;
+}
+
+__uml_setup("noprocmm", noprocmm_cmd_param,
+"noprocmm\n"
+"    Turns off usage of /proc/mm, even if host supports it.\n"
+"    To support /proc/mm, the host needs to be patched using\n"
+"    the current skas3 patch.\n\n");
+
+static int __init noptracefaultinfo_cmd_param(char *str, int* add)
+{
+       ptrace_faultinfo = 0;
+       return 0;
 }
 
+__uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param,
+"noptracefaultinfo\n"
+"    Turns off usage of PTRACE_FAULTINFO, even if host supports\n"
+"    it. To support PTRACE_FAULTINFO, the host needs to be patched\n"
+"    using the current skas3 patch.\n\n");
+
 #ifdef UML_CONFIG_MODE_SKAS
 static inline void check_skas3_ptrace_support(void)
 {
@@ -327,3 +393,72 @@ int can_do_skas(void)
        return(0);
 }
 #endif
+
+int have_devanon = 0;
+
+void check_devanon(void)
+{
+       int fd;
+
+       printk("Checking for /dev/anon on the host...");
+       fd = open("/dev/anon", O_RDWR);
+       if(fd < 0){
+               printk("Not available (open failed with errno %d)\n", errno);
+               return;
+       }
+
+       printk("OK\n");
+       have_devanon = 1;
+}
+
+int __init parse_iomem(char *str, int *add)
+{
+       struct iomem_region *new;
+       struct uml_stat buf;
+       char *file, *driver;
+       int fd, err, size;
+
+       driver = str;
+       file = strchr(str,',');
+       if(file == NULL){
+               printf("parse_iomem : failed to parse iomem\n");
+               goto out;
+       }
+       *file = '\0';
+       file++;
+       fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0);
+       if(fd < 0){
+               os_print_error(fd, "parse_iomem - Couldn't open io file");
+               goto out;
+       }
+
+       err = os_stat_fd(fd, &buf);
+       if(err < 0){
+               os_print_error(err, "parse_iomem - cannot stat_fd file");
+               goto out_close;
+       }
+
+       new = malloc(sizeof(*new));
+       if(new == NULL){
+               perror("Couldn't allocate iomem_region struct");
+               goto out_close;
+       }
+
+       size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1);
+
+       *new = ((struct iomem_region) { .next           = iomem_regions,
+                                       .driver         = driver,
+                                       .fd             = fd,
+                                       .size           = size,
+                                       .phys           = 0,
+                                       .virt           = 0 });
+       iomem_regions = new;
+       iomem_size += new->size + UM_KERN_PAGE_SIZE;
+
+       return(0);
+ out_close:
+       os_close_file(fd);
+ out:
+       return(1);
+}
+