at master 4.1 kB view raw
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 <limits.h> 14#include <linux/futex.h> 15#include <sys/mman.h> 16#include <sys/ptrace.h> 17#include <sys/prctl.h> 18#include <sys/wait.h> 19#include <asm/unistd.h> 20#include <init.h> 21#include <longjmp.h> 22#include <os.h> 23#include <skas/skas.h> 24 25void os_alarm_process(int pid) 26{ 27 if (pid <= 0) 28 return; 29 30 kill(pid, SIGALRM); 31} 32 33void os_kill_process(int pid, int reap_child) 34{ 35 if (pid <= 0) 36 return; 37 38 /* Block signals until child is reaped */ 39 block_signals(); 40 41 kill(pid, SIGKILL); 42 if (reap_child) 43 CATCH_EINTR(waitpid(pid, NULL, __WALL)); 44 45 unblock_signals(); 46} 47 48/* Kill off a ptraced child by all means available. kill it normally first, 49 * then PTRACE_KILL it, then PTRACE_CONT it in case it's in a run state from 50 * which it can't exit directly. 51 */ 52 53void os_kill_ptraced_process(int pid, int reap_child) 54{ 55 if (pid <= 0) 56 return; 57 58 /* Block signals until child is reaped */ 59 block_signals(); 60 61 kill(pid, SIGKILL); 62 ptrace(PTRACE_KILL, pid); 63 ptrace(PTRACE_CONT, pid); 64 if (reap_child) 65 CATCH_EINTR(waitpid(pid, NULL, __WALL)); 66 67 unblock_signals(); 68} 69 70pid_t os_reap_child(void) 71{ 72 int status; 73 74 /* Try to reap a child */ 75 return waitpid(-1, &status, WNOHANG); 76} 77 78/* Don't use the glibc version, which caches the result in TLS. It misses some 79 * syscalls, and also breaks with clone(), which does not unshare the TLS. 80 */ 81 82int os_getpid(void) 83{ 84 return syscall(__NR_getpid); 85} 86 87int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len, 88 int r, int w, int x) 89{ 90 void *loc; 91 int prot; 92 93 prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 94 (x ? PROT_EXEC : 0); 95 96 loc = mmap64((void *) virt, len, prot, MAP_SHARED | MAP_FIXED, 97 fd, off); 98 if (loc == MAP_FAILED) 99 return -errno; 100 return 0; 101} 102 103int os_protect_memory(void *addr, unsigned long len, int r, int w, int x) 104{ 105 int prot = ((r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 106 (x ? PROT_EXEC : 0)); 107 108 if (mprotect(addr, len, prot) < 0) 109 return -errno; 110 111 return 0; 112} 113 114int os_unmap_memory(void *addr, int len) 115{ 116 int err; 117 118 err = munmap(addr, len); 119 if (err < 0) 120 return -errno; 121 return 0; 122} 123 124#ifndef MADV_REMOVE 125#define MADV_REMOVE KERNEL_MADV_REMOVE 126#endif 127 128int os_drop_memory(void *addr, int length) 129{ 130 int err; 131 132 err = madvise(addr, length, MADV_REMOVE); 133 if (err < 0) 134 err = -errno; 135 return err; 136} 137 138int __init can_drop_memory(void) 139{ 140 void *addr; 141 int fd, ok = 0; 142 143 printk(UM_KERN_INFO "Checking host MADV_REMOVE support..."); 144 fd = create_mem_file(UM_KERN_PAGE_SIZE); 145 if (fd < 0) { 146 printk(UM_KERN_ERR "Creating test memory file failed, " 147 "err = %d\n", -fd); 148 goto out; 149 } 150 151 addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, 152 MAP_SHARED, fd, 0); 153 if (addr == MAP_FAILED) { 154 printk(UM_KERN_ERR "Mapping test memory file failed, " 155 "err = %d\n", -errno); 156 goto out_close; 157 } 158 159 if (madvise(addr, UM_KERN_PAGE_SIZE, MADV_REMOVE) != 0) { 160 printk(UM_KERN_ERR "MADV_REMOVE failed, err = %d\n", -errno); 161 goto out_unmap; 162 } 163 164 printk(UM_KERN_CONT "OK\n"); 165 ok = 1; 166 167out_unmap: 168 munmap(addr, UM_KERN_PAGE_SIZE); 169out_close: 170 close(fd); 171out: 172 return ok; 173} 174 175void init_new_thread_signals(void) 176{ 177 set_handler(SIGSEGV); 178 set_handler(SIGTRAP); 179 set_handler(SIGFPE); 180 set_handler(SIGILL); 181 set_handler(SIGBUS); 182 signal(SIGHUP, SIG_IGN); 183 set_handler(SIGIO); 184 /* We (currently) only use the child reaper IRQ in seccomp mode */ 185 if (using_seccomp) 186 set_handler(SIGCHLD); 187 signal(SIGWINCH, SIG_IGN); 188} 189 190void os_set_pdeathsig(void) 191{ 192 prctl(PR_SET_PDEATHSIG, SIGKILL); 193} 194 195int os_futex_wait(void *uaddr, unsigned int val) 196{ 197 int r; 198 199 CATCH_EINTR(r = syscall(__NR_futex, uaddr, FUTEX_WAIT, val, 200 NULL, NULL, 0)); 201 return r < 0 ? -errno : r; 202} 203 204int os_futex_wake(void *uaddr) 205{ 206 int r; 207 208 CATCH_EINTR(r = syscall(__NR_futex, uaddr, FUTEX_WAKE, INT_MAX, 209 NULL, NULL, 0)); 210 return r < 0 ? -errno : r; 211}