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 25 void os_alarm_process(int pid) 26 { 27 if (pid <= 0) 28 return; 29 30 kill(pid, SIGALRM); 31 } 32 33 void 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 53 void 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 70 pid_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 82 int os_getpid(void) 83 { 84 return syscall(__NR_getpid); 85 } 86 87 int 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 103 int 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 114 int 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 128 int 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 138 int __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 167 out_unmap: 168 munmap(addr, UM_KERN_PAGE_SIZE); 169 out_close: 170 close(fd); 171 out: 172 return ok; 173 } 174 175 void 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 190 void os_set_pdeathsig(void) 191 { 192 prctl(PR_SET_PDEATHSIG, SIGKILL); 193 } 194 195 int 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 204 int 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 } 212