linux/arch/um/os-Linux/process.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2015 Thomas Meyer (thomas@m3y3r.de)
   4 * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   5 */
   6
   7#include <stdio.h>
   8#include <stdlib.h>
   9#include <unistd.h>
  10#include <errno.h>
  11#include <signal.h>
  12#include <fcntl.h>
  13#include <sys/mman.h>
  14#include <sys/ptrace.h>
  15#include <sys/wait.h>
  16#include <asm/unistd.h>
  17#include <init.h>
  18#include <longjmp.h>
  19#include <os.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_alarm_process(int pid)
  94{
  95        kill(pid, SIGALRM);
  96}
  97
  98void os_stop_process(int pid)
  99{
 100        kill(pid, SIGSTOP);
 101}
 102
 103void os_kill_process(int pid, int reap_child)
 104{
 105        kill(pid, SIGKILL);
 106        if (reap_child)
 107                CATCH_EINTR(waitpid(pid, NULL, __WALL));
 108}
 109
 110/* Kill off a ptraced child by all means available.  kill it normally first,
 111 * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from
 112 * which it can't exit directly.
 113 */
 114
 115void os_kill_ptraced_process(int pid, int reap_child)
 116{
 117        kill(pid, SIGKILL);
 118        ptrace(PTRACE_KILL, pid);
 119        ptrace(PTRACE_CONT, pid);
 120        if (reap_child)
 121                CATCH_EINTR(waitpid(pid, NULL, __WALL));
 122}
 123
 124/* Don't use the glibc version, which caches the result in TLS. It misses some
 125 * syscalls, and also breaks with clone(), which does not unshare the TLS.
 126 */
 127
 128int os_getpid(void)
 129{
 130        return syscall(__NR_getpid);
 131}
 132
 133int os_getpgrp(void)
 134{
 135        return getpgrp();
 136}
 137
 138int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
 139                  int r, int w, int x)
 140{
 141        void *loc;
 142        int prot;
 143
 144        prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
 145                (x ? PROT_EXEC : 0);
 146
 147        loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
 148                     fd, off);
 149        if (loc == MAP_FAILED)
 150                return -errno;
 151        return 0;
 152}
 153
 154int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
 155{
 156        int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
 157                    (x ? PROT_EXEC : 0));
 158
 159        if (mprotect(addr, len, prot) < 0)
 160                return -errno;
 161
 162        return 0;
 163}
 164
 165int os_unmap_memory(void *addr, int len)
 166{
 167        int err;
 168
 169        err = munmap(addr, len);
 170        if (err < 0)
 171                return -errno;
 172        return 0;
 173}
 174
 175#ifndef MADV_REMOVE
 176#define MADV_REMOVE KERNEL_MADV_REMOVE
 177#endif
 178
 179int os_drop_memory(void *addr, int length)
 180{
 181        int err;
 182
 183        err = madvise(addr, length, MADV_REMOVE);
 184        if (err < 0)
 185                err = -errno;
 186        return err;
 187}
 188
 189int __init can_drop_memory(void)
 190{
 191        void *addr;
 192        int fd, ok = 0;
 193
 194        printk(UM_KERN_INFO "Checking host MADV_REMOVE support...");
 195        fd = create_mem_file(UM_KERN_PAGE_SIZE);
 196        if (fd < 0) {
 197                printk(UM_KERN_ERR "Creating test memory file failed, "
 198                       "err = %d\n", -fd);
 199                goto out;
 200        }
 201
 202        addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
 203                      MAP_SHARED, fd, 0);
 204        if (addr == MAP_FAILED) {
 205                printk(UM_KERN_ERR "Mapping test memory file failed, "
 206                       "err = %d\n", -errno);
 207                goto out_close;
 208        }
 209
 210        if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) {
 211                printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno);
 212                goto out_unmap;
 213        }
 214
 215        printk(UM_KERN_CONT "OK\n");
 216        ok = 1;
 217
 218out_unmap:
 219        munmap(addr, UM_KERN_PAGE_SIZE);
 220out_close:
 221        close(fd);
 222out:
 223        return ok;
 224}
 225
 226static int os_page_mincore(void *addr)
 227{
 228        char vec[2];
 229        int ret;
 230
 231        ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
 232        if (ret < 0) {
 233                if (errno == ENOMEM || errno == EINVAL)
 234                        return 0;
 235                else
 236                        return -errno;
 237        }
 238
 239        return vec[0] & 1;
 240}
 241
 242int os_mincore(void *addr, unsigned long len)
 243{
 244        char *vec;
 245        int ret, i;
 246
 247        if (len <= UM_KERN_PAGE_SIZE)
 248                return os_page_mincore(addr);
 249
 250        vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE);
 251        if (!vec)
 252                return -ENOMEM;
 253
 254        ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
 255        if (ret < 0) {
 256                if (errno == ENOMEM || errno == EINVAL)
 257                        ret = 0;
 258                else
 259                        ret = -errno;
 260
 261                goto out;
 262        }
 263
 264        for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) {
 265                if (!(vec[i] & 1)) {
 266                        ret = 0;
 267                        goto out;
 268                }
 269        }
 270
 271        ret = 1;
 272out:
 273        free(vec);
 274        return ret;
 275}
 276
 277void init_new_thread_signals(void)
 278{
 279        set_handler(SIGSEGV);
 280        set_handler(SIGTRAP);
 281        set_handler(SIGFPE);
 282        set_handler(SIGILL);
 283        set_handler(SIGBUS);
 284        signal(SIGHUP, SIG_IGN);
 285        set_handler(SIGIO);
 286        signal(SIGWINCH, SIG_IGN);
 287}
 288