linux/arch/um/os-Linux/process.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include <stdio.h>
   7#include <unistd.h>
   8#include <errno.h>
   9#include <signal.h>
  10#include <fcntl.h>
  11#include <sys/mman.h>
  12#include <sys/ptrace.h>
  13#include <sys/wait.h>
  14#include <asm/unistd.h>
  15#include "init.h"
  16#include "kern_constants.h"
  17#include "longjmp.h"
  18#include "os.h"
  19#include "process.h"
  20#include "skas_ptrace.h"
  21#include "user.h"
  22
  23#define ARBITRARY_ADDR -1
  24#define FAILURE_PID    -1
  25
  26#define STAT_PATH_LEN sizeof("/proc/#######/stat\0")
  27#define COMM_SCANF "%*[^)])"
  28
  29unsigned long os_process_pc(int pid)
  30{
  31        char proc_stat[STAT_PATH_LEN], buf[256];
  32        unsigned long pc = ARBITRARY_ADDR;
  33        int fd, err;
  34
  35        sprintf(proc_stat, "/proc/%d/stat", pid);
  36        fd = open(proc_stat, O_RDONLY, 0);
  37        if (fd < 0) {
  38                printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', "
  39                       "errno = %d\n", proc_stat, errno);
  40                goto out;
  41        }
  42        CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
  43        if (err < 0) {
  44                printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', "
  45                       "err = %d\n", proc_stat, errno);
  46                goto out_close;
  47        }
  48        os_close_file(fd);
  49        pc = ARBITRARY_ADDR;
  50        if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
  51                   "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
  52                   "%*d %*d %*d %*d %*d %lu", &pc) != 1)
  53                printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n",
  54                       buf);
  55 out_close:
  56        close(fd);
  57 out:
  58        return pc;
  59}
  60
  61int os_process_parent(int pid)
  62{
  63        char stat[STAT_PATH_LEN];
  64        char data[256];
  65        int parent = FAILURE_PID, n, fd;
  66
  67        if (pid == -1)
  68                return parent;
  69
  70        snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
  71        fd = open(stat, O_RDONLY, 0);
  72        if (fd < 0) {
  73                printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat,
  74                       errno);
  75                return parent;
  76        }
  77
  78        CATCH_EINTR(n = read(fd, data, sizeof(data)));
  79        close(fd);
  80
  81        if (n < 0) {
  82                printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat,
  83                       errno);
  84                return parent;
  85        }
  86
  87        parent = FAILURE_PID;
  88        n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
  89        if (n != 1)
  90                printk(UM_KERN_ERR "Failed to scan '%s'\n", data);
  91
  92        return parent;
  93}
  94
  95void os_stop_process(int pid)
  96{
  97        kill(pid, SIGSTOP);
  98}
  99
 100void os_kill_process(int pid, int reap_child)
 101{
 102        kill(pid, SIGKILL);
 103        if (reap_child)
 104                CATCH_EINTR(waitpid(pid, NULL, __WALL));
 105}
 106
 107/* This is here uniquely to have access to the userspace errno, i.e. the one
 108 * used by ptrace in case of error.
 109 */
 110
 111long os_ptrace_ldt(long pid, long addr, long data)
 112{
 113        int ret;
 114
 115        ret = ptrace(PTRACE_LDT, pid, addr, data);
 116
 117        if (ret < 0)
 118                return -errno;
 119        return ret;
 120}
 121
 122/* Kill off a ptraced child by all means available.  kill it normally first,
 123 * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from
 124 * which it can't exit directly.
 125 */
 126
 127void os_kill_ptraced_process(int pid, int reap_child)
 128{
 129        kill(pid, SIGKILL);
 130        ptrace(PTRACE_KILL, pid);
 131        ptrace(PTRACE_CONT, pid);
 132        if (reap_child)
 133                CATCH_EINTR(waitpid(pid, NULL, __WALL));
 134}
 135
 136/* Don't use the glibc version, which caches the result in TLS. It misses some
 137 * syscalls, and also breaks with clone(), which does not unshare the TLS.
 138 */
 139
 140int os_getpid(void)
 141{
 142        return syscall(__NR_getpid);
 143}
 144
 145int os_getpgrp(void)
 146{
 147        return getpgrp();
 148}
 149
 150int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
 151                  int r, int w, int x)
 152{
 153        void *loc;
 154        int prot;
 155
 156        prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
 157                (x ? PROT_EXEC : 0);
 158
 159        loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
 160                     fd, off);
 161        if (loc == MAP_FAILED)
 162                return -errno;
 163        return 0;
 164}
 165
 166int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
 167{
 168        int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
 169                    (x ? PROT_EXEC : 0));
 170
 171        if (mprotect(addr, len, prot) < 0)
 172                return -errno;
 173
 174        return 0;
 175}
 176
 177int os_unmap_memory(void *addr, int len)
 178{
 179        int err;
 180
 181        err = munmap(addr, len);
 182        if (err < 0)
 183                return -errno;
 184        return 0;
 185}
 186
 187#ifndef MADV_REMOVE
 188#define MADV_REMOVE KERNEL_MADV_REMOVE
 189#endif
 190
 191int os_drop_memory(void *addr, int length)
 192{
 193        int err;
 194
 195        err = madvise(addr, length, MADV_REMOVE);
 196        if (err < 0)
 197                err = -errno;
 198        return err;
 199}
 200
 201int __init can_drop_memory(void)
 202{
 203        void *addr;
 204        int fd, ok = 0;
 205
 206        printk(UM_KERN_INFO "Checking host MADV_REMOVE support...");
 207        fd = create_mem_file(UM_KERN_PAGE_SIZE);
 208        if (fd < 0) {
 209                printk(UM_KERN_ERR "Creating test memory file failed, "
 210                       "err = %d\n", -fd);
 211                goto out;
 212        }
 213
 214        addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
 215                      MAP_SHARED, fd, 0);
 216        if (addr == MAP_FAILED) {
 217                printk(UM_KERN_ERR "Mapping test memory file failed, "
 218                       "err = %d\n", -errno);
 219                goto out_close;
 220        }
 221
 222        if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) {
 223                printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno);
 224                goto out_unmap;
 225        }
 226
 227        printk(UM_KERN_CONT "OK\n");
 228        ok = 1;
 229
 230out_unmap:
 231        munmap(addr, UM_KERN_PAGE_SIZE);
 232out_close:
 233        close(fd);
 234out:
 235        return ok;
 236}
 237
 238void init_new_thread_signals(void)
 239{
 240        set_handler(SIGSEGV, (__sighandler_t) sig_handler, SA_ONSTACK,
 241                    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
 242        set_handler(SIGTRAP, (__sighandler_t) sig_handler, SA_ONSTACK,
 243                    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
 244        set_handler(SIGFPE, (__sighandler_t) sig_handler, SA_ONSTACK,
 245                    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
 246        set_handler(SIGILL, (__sighandler_t) sig_handler, SA_ONSTACK,
 247                    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
 248        set_handler(SIGBUS, (__sighandler_t) sig_handler, SA_ONSTACK,
 249                    SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
 250        signal(SIGHUP, SIG_IGN);
 251
 252        set_handler(SIGIO, (__sighandler_t) sig_handler,
 253                    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGALRM,
 254                    SIGVTALRM, -1);
 255        signal(SIGWINCH, SIG_IGN);
 256}
 257
 258int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr)
 259{
 260        jmp_buf buf;
 261        int n;
 262
 263        *jmp_ptr = &buf;
 264        n = UML_SETJMP(&buf);
 265        if (n != 0)
 266                return n;
 267        (*fn)(arg);
 268        return 0;
 269}
 270