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