LCOV - code coverage report
Current view: top level - arch/um/os-Linux - process.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 33 125 26.4 %
Date: 2023-08-24 13:40:31 Functions: 5 16 31.2 %

          Line data    Source code
       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             : 
      27           0 : unsigned long os_process_pc(int pid)
      28             : {
      29             :         char proc_stat[STAT_PATH_LEN], buf[256];
      30           0 :         unsigned long pc = ARBITRARY_ADDR;
      31             :         int fd, err;
      32             : 
      33           0 :         sprintf(proc_stat, "/proc/%d/stat", pid);
      34           0 :         fd = open(proc_stat, O_RDONLY, 0);
      35           0 :         if (fd < 0) {
      36           0 :                 printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', "
      37             :                        "errno = %d\n", proc_stat, errno);
      38           0 :                 goto out;
      39             :         }
      40           0 :         CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
      41           0 :         if (err < 0) {
      42           0 :                 printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', "
      43             :                        "err = %d\n", proc_stat, errno);
      44           0 :                 goto out_close;
      45             :         }
      46           0 :         os_close_file(fd);
      47           0 :         pc = ARBITRARY_ADDR;
      48           0 :         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           0 :                 printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n",
      52             :                        buf);
      53             :  out_close:
      54           0 :         close(fd);
      55             :  out:
      56           0 :         return pc;
      57             : }
      58             : 
      59           0 : int os_process_parent(int pid)
      60             : {
      61             :         char stat[STAT_PATH_LEN];
      62             :         char data[256];
      63           0 :         int parent = FAILURE_PID, n, fd;
      64             : 
      65           0 :         if (pid == -1)
      66             :                 return parent;
      67             : 
      68           0 :         snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
      69           0 :         fd = open(stat, O_RDONLY, 0);
      70           0 :         if (fd < 0) {
      71           0 :                 printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat,
      72             :                        errno);
      73           0 :                 return parent;
      74             :         }
      75             : 
      76           0 :         CATCH_EINTR(n = read(fd, data, sizeof(data)));
      77           0 :         close(fd);
      78             : 
      79           0 :         if (n < 0) {
      80           0 :                 printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat,
      81             :                        errno);
      82           0 :                 return parent;
      83             :         }
      84             : 
      85           0 :         parent = FAILURE_PID;
      86           0 :         n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
      87           0 :         if (n != 1)
      88           0 :                 printk(UM_KERN_ERR "Failed to scan '%s'\n", data);
      89             : 
      90           0 :         return parent;
      91             : }
      92             : 
      93           0 : void os_alarm_process(int pid)
      94             : {
      95           0 :         kill(pid, SIGALRM);
      96           0 : }
      97             : 
      98           0 : void os_stop_process(int pid)
      99             : {
     100           0 :         kill(pid, SIGSTOP);
     101           0 : }
     102             : 
     103           0 : void os_kill_process(int pid, int reap_child)
     104             : {
     105           0 :         kill(pid, SIGKILL);
     106           0 :         if (reap_child)
     107           0 :                 CATCH_EINTR(waitpid(pid, NULL, __WALL));
     108           0 : }
     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             : 
     115           0 : void os_kill_ptraced_process(int pid, int reap_child)
     116             : {
     117           0 :         kill(pid, SIGKILL);
     118           0 :         ptrace(PTRACE_KILL, pid);
     119           0 :         ptrace(PTRACE_CONT, pid);
     120           0 :         if (reap_child)
     121           0 :                 CATCH_EINTR(waitpid(pid, NULL, __WALL));
     122           0 : }
     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             : 
     128          16 : int os_getpid(void)
     129             : {
     130          16 :         return syscall(__NR_getpid);
     131             : }
     132             : 
     133           0 : int os_getpgrp(void)
     134             : {
     135           0 :         return getpgrp();
     136             : }
     137             : 
     138          66 : int 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         132 :         prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
     145          66 :                 (x ? PROT_EXEC : 0);
     146             : 
     147          66 :         loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED,
     148             :                      fd, off);
     149          66 :         if (loc == MAP_FAILED)
     150           0 :                 return -errno;
     151             :         return 0;
     152             : }
     153             : 
     154           0 : int os_protect_memory(void *addr, unsigned long len, int r, int w, int x)
     155             : {
     156           0 :         int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) |
     157           0 :                     (x ? PROT_EXEC : 0));
     158             : 
     159           0 :         if (mprotect(addr, len, prot) < 0)
     160           0 :                 return -errno;
     161             : 
     162             :         return 0;
     163             : }
     164             : 
     165          64 : int os_unmap_memory(void *addr, int len)
     166             : {
     167             :         int err;
     168             : 
     169          64 :         err = munmap(addr, len);
     170          64 :         if (err < 0)
     171           0 :                 return -errno;
     172             :         return 0;
     173             : }
     174             : 
     175             : #ifndef MADV_REMOVE
     176             : #define MADV_REMOVE KERNEL_MADV_REMOVE
     177             : #endif
     178             : 
     179           0 : int os_drop_memory(void *addr, int length)
     180             : {
     181             :         int err;
     182             : 
     183           0 :         err = madvise(addr, length, MADV_REMOVE);
     184           0 :         if (err < 0)
     185           0 :                 err = -errno;
     186           0 :         return err;
     187             : }
     188             : 
     189           1 : int __init can_drop_memory(void)
     190             : {
     191             :         void *addr;
     192           1 :         int fd, ok = 0;
     193             : 
     194           1 :         printk(UM_KERN_INFO "Checking host MADV_REMOVE support...");
     195           1 :         fd = create_mem_file(UM_KERN_PAGE_SIZE);
     196           1 :         if (fd < 0) {
     197           0 :                 printk(UM_KERN_ERR "Creating test memory file failed, "
     198             :                        "err = %d\n", -fd);
     199           0 :                 goto out;
     200             :         }
     201             : 
     202           1 :         addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
     203             :                       MAP_SHARED, fd, 0);
     204           1 :         if (addr == MAP_FAILED) {
     205           0 :                 printk(UM_KERN_ERR "Mapping test memory file failed, "
     206             :                        "err = %d\n", -errno);
     207           0 :                 goto out_close;
     208             :         }
     209             : 
     210           1 :         if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) {
     211           0 :                 printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno);
     212           0 :                 goto out_unmap;
     213             :         }
     214             : 
     215           1 :         printk(UM_KERN_CONT "OK\n");
     216           1 :         ok = 1;
     217             : 
     218             : out_unmap:
     219           1 :         munmap(addr, UM_KERN_PAGE_SIZE);
     220             : out_close:
     221           1 :         close(fd);
     222             : out:
     223           1 :         return ok;
     224             : }
     225             : 
     226           0 : static int os_page_mincore(void *addr)
     227             : {
     228             :         char vec[2];
     229             :         int ret;
     230             : 
     231           0 :         ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
     232           0 :         if (ret < 0) {
     233           0 :                 if (errno == ENOMEM || errno == EINVAL)
     234             :                         return 0;
     235             :                 else
     236           0 :                         return -errno;
     237             :         }
     238             : 
     239           0 :         return vec[0] & 1;
     240             : }
     241             : 
     242           0 : int os_mincore(void *addr, unsigned long len)
     243             : {
     244             :         char *vec;
     245             :         int ret, i;
     246             : 
     247           0 :         if (len <= UM_KERN_PAGE_SIZE)
     248           0 :                 return os_page_mincore(addr);
     249             : 
     250           0 :         vec = calloc(1, (len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE);
     251           0 :         if (!vec)
     252             :                 return -ENOMEM;
     253             : 
     254           0 :         ret = mincore(addr, UM_KERN_PAGE_SIZE, vec);
     255           0 :         if (ret < 0) {
     256           0 :                 if (errno == ENOMEM || errno == EINVAL)
     257             :                         ret = 0;
     258             :                 else
     259           0 :                         ret = -errno;
     260             : 
     261             :                 goto out;
     262             :         }
     263             : 
     264           0 :         for (i = 0; i < ((len + UM_KERN_PAGE_SIZE - 1) / UM_KERN_PAGE_SIZE); i++) {
     265           0 :                 if (!(vec[i] & 1)) {
     266             :                         ret = 0;
     267             :                         goto out;
     268             :                 }
     269             :         }
     270             : 
     271             :         ret = 1;
     272             : out:
     273           0 :         free(vec);
     274           0 :         return ret;
     275             : }
     276             : 
     277           1 : void init_new_thread_signals(void)
     278             : {
     279           1 :         set_handler(SIGSEGV);
     280           1 :         set_handler(SIGTRAP);
     281           1 :         set_handler(SIGFPE);
     282           1 :         set_handler(SIGILL);
     283           1 :         set_handler(SIGBUS);
     284           1 :         signal(SIGHUP, SIG_IGN);
     285           1 :         set_handler(SIGIO);
     286           1 :         signal(SIGWINCH, SIG_IGN);
     287           1 : }

Generated by: LCOV version 1.14