1 1.141 kre /* $NetBSD: hijack.c,v 1.141 2024/11/12 03:06:58 kre Exp $ */ 2 1.1 pooka 3 1.1 pooka /*- 4 1.1 pooka * Copyright (c) 2011 Antti Kantee. All Rights Reserved. 5 1.1 pooka * 6 1.1 pooka * Redistribution and use in source and binary forms, with or without 7 1.1 pooka * modification, are permitted provided that the following conditions 8 1.1 pooka * are met: 9 1.1 pooka * 1. Redistributions of source code must retain the above copyright 10 1.1 pooka * notice, this list of conditions and the following disclaimer. 11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 pooka * notice, this list of conditions and the following disclaimer in the 13 1.1 pooka * documentation and/or other materials provided with the distribution. 14 1.1 pooka * 15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 pooka * SUCH DAMAGE. 26 1.1 pooka */ 27 1.1 pooka 28 1.111 pooka /* 29 1.111 pooka * XXX: rumphijack sort of works on glibc Linux. But it's not 30 1.111 pooka * the same quality working as on NetBSD. 31 1.111 pooka * autoconf HAVE_FOO vs. __NetBSD__ / __linux__ could be further 32 1.111 pooka * improved. 33 1.111 pooka */ 34 1.106 pooka #include <rump/rumpuser_port.h> 35 1.96 pooka 36 1.101 pooka #if !defined(lint) 37 1.141 kre __RCSID("$NetBSD: hijack.c,v 1.141 2024/11/12 03:06:58 kre Exp $"); 38 1.101 pooka #endif 39 1.1 pooka 40 1.1 pooka #include <sys/param.h> 41 1.1 pooka #include <sys/types.h> 42 1.1 pooka #include <sys/ioctl.h> 43 1.62 pooka #include <sys/mman.h> 44 1.48 pooka #include <sys/mount.h> 45 1.1 pooka #include <sys/socket.h> 46 1.96 pooka #include <sys/stat.h> 47 1.96 pooka #include <sys/time.h> 48 1.102 pooka #include <sys/uio.h> 49 1.96 pooka 50 1.111 pooka #ifdef __NetBSD__ 51 1.107 justin #include <sys/statvfs.h> 52 1.107 justin #endif 53 1.107 justin 54 1.111 pooka #ifdef HAVE_KQUEUE 55 1.96 pooka #include <sys/event.h> 56 1.96 pooka #endif 57 1.96 pooka 58 1.111 pooka #ifdef __NetBSD__ 59 1.91 dholland #include <sys/quotactl.h> 60 1.96 pooka #endif 61 1.1 pooka 62 1.1 pooka #include <assert.h> 63 1.1 pooka #include <dlfcn.h> 64 1.1 pooka #include <err.h> 65 1.1 pooka #include <errno.h> 66 1.1 pooka #include <fcntl.h> 67 1.1 pooka #include <poll.h> 68 1.1 pooka #include <pthread.h> 69 1.3 pooka #include <signal.h> 70 1.1 pooka #include <stdarg.h> 71 1.8 pooka #include <stdbool.h> 72 1.96 pooka #include <stdint.h> 73 1.1 pooka #include <stdio.h> 74 1.1 pooka #include <stdlib.h> 75 1.28 pooka #include <string.h> 76 1.3 pooka #include <time.h> 77 1.1 pooka #include <unistd.h> 78 1.1 pooka 79 1.96 pooka #include <rump/rumpclient.h> 80 1.96 pooka #include <rump/rump_syscalls.h> 81 1.96 pooka 82 1.64 pooka #include "hijack.h" 83 1.64 pooka 84 1.96 pooka /* 85 1.96 pooka * XXX: Consider autogenerating this, syscnames[] and syscalls[] with 86 1.96 pooka * a DSL where the tool also checks the symbols exported by this library 87 1.96 pooka * to make sure all relevant calls are accounted for. 88 1.96 pooka */ 89 1.17 pooka enum dualcall { 90 1.60 pooka DUALCALL_WRITE, DUALCALL_WRITEV, DUALCALL_PWRITE, DUALCALL_PWRITEV, 91 1.140 ozaki DUALCALL_IOCTL, DUALCALL_FCNTL, DUALCALL_FLOCK, 92 1.127 bad DUALCALL_SOCKET, DUALCALL_ACCEPT, 93 1.127 bad #ifndef __linux__ 94 1.127 bad DUALCALL_PACCEPT, 95 1.127 bad #endif 96 1.122 ozaki DUALCALL_BIND, DUALCALL_CONNECT, 97 1.17 pooka DUALCALL_GETPEERNAME, DUALCALL_GETSOCKNAME, DUALCALL_LISTEN, 98 1.17 pooka DUALCALL_RECVFROM, DUALCALL_RECVMSG, 99 1.17 pooka DUALCALL_SENDTO, DUALCALL_SENDMSG, 100 1.17 pooka DUALCALL_GETSOCKOPT, DUALCALL_SETSOCKOPT, 101 1.17 pooka DUALCALL_SHUTDOWN, 102 1.60 pooka DUALCALL_READ, DUALCALL_READV, DUALCALL_PREAD, DUALCALL_PREADV, 103 1.41 pooka DUALCALL_DUP2, 104 1.34 pooka DUALCALL_CLOSE, 105 1.17 pooka DUALCALL_POLLTS, 106 1.97 pooka 107 1.97 pooka #ifndef __linux__ 108 1.45 pooka DUALCALL_STAT, DUALCALL_LSTAT, DUALCALL_FSTAT, 109 1.97 pooka #endif 110 1.97 pooka 111 1.45 pooka DUALCALL_CHMOD, DUALCALL_LCHMOD, DUALCALL_FCHMOD, 112 1.45 pooka DUALCALL_CHOWN, DUALCALL_LCHOWN, DUALCALL_FCHOWN, 113 1.45 pooka DUALCALL_OPEN, 114 1.45 pooka DUALCALL_CHDIR, DUALCALL_FCHDIR, 115 1.45 pooka DUALCALL_LSEEK, 116 1.45 pooka DUALCALL_UNLINK, DUALCALL_SYMLINK, DUALCALL_READLINK, 117 1.95 riastrad DUALCALL_LINK, DUALCALL_RENAME, 118 1.45 pooka DUALCALL_MKDIR, DUALCALL_RMDIR, 119 1.45 pooka DUALCALL_UTIMES, DUALCALL_LUTIMES, DUALCALL_FUTIMES, 120 1.113 enami DUALCALL_UTIMENSAT, DUALCALL_FUTIMENS, 121 1.45 pooka DUALCALL_TRUNCATE, DUALCALL_FTRUNCATE, 122 1.96 pooka DUALCALL_FSYNC, 123 1.97 pooka DUALCALL_ACCESS, 124 1.97 pooka 125 1.97 pooka #ifndef __linux__ 126 1.57 pooka DUALCALL___GETCWD, 127 1.98 pooka DUALCALL_GETDENTS, 128 1.97 pooka #endif 129 1.97 pooka 130 1.97 pooka #ifndef __linux__ 131 1.68 pooka DUALCALL_MKNOD, 132 1.97 pooka #endif 133 1.97 pooka 134 1.111 pooka #ifdef __NetBSD__ 135 1.96 pooka DUALCALL_GETFH, DUALCALL_FHOPEN, DUALCALL_FHSTAT, DUALCALL_FHSTATVFS1, 136 1.97 pooka #endif 137 1.97 pooka 138 1.111 pooka #ifdef HAVE_KQUEUE 139 1.97 pooka DUALCALL_KEVENT, 140 1.97 pooka #endif 141 1.96 pooka 142 1.111 pooka #ifdef __NetBSD__ 143 1.78 pooka DUALCALL___SYSCTL, 144 1.126 hannken DUALCALL_MODCTL, 145 1.96 pooka #endif 146 1.96 pooka 147 1.111 pooka #ifdef __NetBSD__ 148 1.96 pooka DUALCALL_NFSSVC, 149 1.96 pooka #endif 150 1.96 pooka 151 1.111 pooka #ifdef __NetBSD__ 152 1.96 pooka DUALCALL_STATVFS1, DUALCALL_FSTATVFS1, DUALCALL_GETVFSSTAT, 153 1.96 pooka #endif 154 1.96 pooka 155 1.111 pooka #ifdef __NetBSD__ 156 1.96 pooka DUALCALL_MOUNT, DUALCALL_UNMOUNT, 157 1.96 pooka #endif 158 1.96 pooka 159 1.111 pooka #ifdef HAVE_FSYNC_RANGE 160 1.96 pooka DUALCALL_FSYNC_RANGE, 161 1.96 pooka #endif 162 1.96 pooka 163 1.111 pooka #ifdef HAVE_CHFLAGS 164 1.96 pooka DUALCALL_CHFLAGS, DUALCALL_LCHFLAGS, DUALCALL_FCHFLAGS, 165 1.96 pooka #endif 166 1.96 pooka 167 1.111 pooka #ifdef HAVE___QUOTACTL 168 1.80 bouyer DUALCALL_QUOTACTL, 169 1.83 pooka #endif 170 1.123 christos #ifdef __NetBSD__ 171 1.123 christos DUALCALL_LINKAT, 172 1.123 christos #endif 173 1.131 christos DUALCALL_PATHCONF, 174 1.131 christos DUALCALL_LPATHCONF, 175 1.131 christos 176 1.17 pooka DUALCALL__NUM 177 1.1 pooka }; 178 1.1 pooka 179 1.8 pooka #define RSYS_STRING(a) __STRING(a) 180 1.8 pooka #define RSYS_NAME(a) RSYS_STRING(__CONCAT(RUMP_SYS_RENAME_,a)) 181 1.8 pooka 182 1.1 pooka /* 183 1.14 pooka * Would be nice to get this automatically in sync with libc. 184 1.97 pooka * Also, this does not work for compat-using binaries (we should 185 1.97 pooka * provide all previous interfaces, not just the current ones) 186 1.14 pooka */ 187 1.97 pooka #if defined(__NetBSD__) 188 1.97 pooka 189 1.14 pooka #if !__NetBSD_Prereq__(5,99,7) 190 1.134 rillig #define REALPSELECT pselect 191 1.29 pooka #define REALSELECT select 192 1.29 pooka #define REALPOLLTS pollts 193 1.45 pooka #define REALSTAT __stat30 194 1.45 pooka #define REALLSTAT __lstat30 195 1.45 pooka #define REALFSTAT __fstat30 196 1.45 pooka #define REALUTIMES utimes 197 1.45 pooka #define REALLUTIMES lutimes 198 1.45 pooka #define REALFUTIMES futimes 199 1.68 pooka #define REALMKNOD mknod 200 1.78 pooka #define REALFHSTAT __fhstat40 201 1.96 pooka #else /* >= 5.99.7 */ 202 1.132 christos #define REALPSELECT _sys___pselect50 203 1.29 pooka #define REALSELECT _sys___select50 204 1.29 pooka #define REALPOLLTS _sys___pollts50 205 1.45 pooka #define REALSTAT __stat50 206 1.45 pooka #define REALLSTAT __lstat50 207 1.45 pooka #define REALFSTAT __fstat50 208 1.45 pooka #define REALUTIMES __utimes50 209 1.45 pooka #define REALLUTIMES __lutimes50 210 1.69 pooka #define REALFUTIMES __futimes50 211 1.68 pooka #define REALMKNOD __mknod50 212 1.78 pooka #define REALFHSTAT __fhstat50 213 1.96 pooka #endif /* < 5.99.7 */ 214 1.97 pooka 215 1.137 christos #if !__NetBSD_Prereq__(5,99,7) 216 1.137 christos #define REALKEVENT kevent 217 1.138 rin #elif !__NetBSD_Prereq__(10,99,7) 218 1.137 christos #define REALKEVENT _sys___kevent50 219 1.137 christos #else 220 1.137 christos #define REALKEVENT _sys___kevent100 221 1.137 christos #endif 222 1.137 christos 223 1.31 pooka #define REALREAD _sys_read 224 1.60 pooka #define REALPREAD _sys_pread 225 1.60 pooka #define REALPWRITE _sys_pwrite 226 1.45 pooka #define REALGETDENTS __getdents30 227 1.48 pooka #define REALMOUNT __mount50 228 1.78 pooka #define REALGETFH __getfh30 229 1.78 pooka #define REALFHOPEN __fhopen40 230 1.128 christos #if !__NetBSD_Prereq__(9,99,13) 231 1.128 christos #define REALSTATVFS1 statvfs1 232 1.128 christos #define REALFSTATVFS1 fstatvfs1 233 1.128 christos #define REALGETVFSSTAT getvfsstat 234 1.78 pooka #define REALFHSTATVFS1 __fhstatvfs140 235 1.128 christos #else 236 1.128 christos #define REALSTATVFS1 __statvfs190 237 1.128 christos #define REALFSTATVFS1 __fstatvfs190 238 1.128 christos #define REALGETVFSSTAT __getvfsstat90 239 1.128 christos #define REALFHSTATVFS1 __fhstatvfs190 240 1.128 christos #endif 241 1.96 pooka #define REALSOCKET __socket30 242 1.96 pooka 243 1.96 pooka #define LSEEK_ALIAS _lseek 244 1.96 pooka #define VFORK __vfork14 245 1.96 pooka 246 1.97 pooka int REALSTAT(const char *, struct stat *); 247 1.97 pooka int REALLSTAT(const char *, struct stat *); 248 1.97 pooka int REALFSTAT(int, struct stat *); 249 1.97 pooka int REALMKNOD(const char *, mode_t, dev_t); 250 1.98 pooka int REALGETDENTS(int, char *, size_t); 251 1.97 pooka 252 1.97 pooka int __getcwd(char *, size_t); 253 1.97 pooka 254 1.97 pooka #elif defined(__linux__) /* glibc, really */ 255 1.96 pooka 256 1.96 pooka #define REALREAD read 257 1.96 pooka #define REALPREAD pread 258 1.96 pooka #define REALPWRITE pwrite 259 1.132 christos #define REALPSELECT pselect 260 1.96 pooka #define REALSELECT select 261 1.96 pooka #define REALPOLLTS ppoll 262 1.96 pooka #define REALUTIMES utimes 263 1.96 pooka #define REALLUTIMES lutimes 264 1.96 pooka #define REALFUTIMES futimes 265 1.96 pooka #define REALFHSTAT fhstat 266 1.96 pooka #define REALSOCKET socket 267 1.96 pooka 268 1.97 pooka #else /* !NetBSD && !linux */ 269 1.97 pooka 270 1.97 pooka #error platform not supported 271 1.97 pooka 272 1.97 pooka #endif /* platform */ 273 1.14 pooka 274 1.132 christos int REALPSELECT(int, fd_set *, fd_set *, fd_set *, const struct timespec *, 275 1.132 christos const sigset_t *); 276 1.29 pooka int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *); 277 1.29 pooka int REALPOLLTS(struct pollfd *, nfds_t, 278 1.20 pooka const struct timespec *, const sigset_t *); 279 1.34 pooka int REALKEVENT(int, const struct kevent *, size_t, struct kevent *, size_t, 280 1.34 pooka const struct timespec *); 281 1.31 pooka ssize_t REALREAD(int, void *, size_t); 282 1.60 pooka ssize_t REALPREAD(int, void *, size_t, off_t); 283 1.60 pooka ssize_t REALPWRITE(int, const void *, size_t, off_t); 284 1.45 pooka int REALUTIMES(const char *, const struct timeval [2]); 285 1.45 pooka int REALLUTIMES(const char *, const struct timeval [2]); 286 1.45 pooka int REALFUTIMES(int, const struct timeval [2]); 287 1.48 pooka int REALMOUNT(const char *, const char *, int, void *, size_t); 288 1.78 pooka int REALGETFH(const char *, void *, size_t *); 289 1.78 pooka int REALFHOPEN(const void *, size_t, int); 290 1.78 pooka int REALFHSTAT(const void *, size_t, struct stat *); 291 1.128 christos int REALSTATVFS1(const char *, struct statvfs *, int); 292 1.128 christos int REALFSTATVFS1(int, struct statvfs *, int); 293 1.78 pooka int REALFHSTATVFS1(const void *, size_t, struct statvfs *, int); 294 1.128 christos int REALGETVFSSTAT(struct statvfs *, size_t, int); 295 1.96 pooka int REALSOCKET(int, int, int); 296 1.96 pooka 297 1.17 pooka #define S(a) __STRING(a) 298 1.17 pooka struct sysnames { 299 1.17 pooka enum dualcall scm_callnum; 300 1.17 pooka const char *scm_hostname; 301 1.17 pooka const char *scm_rumpname; 302 1.83 pooka } syscnames[] = { 303 1.96 pooka { DUALCALL_SOCKET, S(REALSOCKET), RSYS_NAME(SOCKET) }, 304 1.17 pooka { DUALCALL_ACCEPT, "accept", RSYS_NAME(ACCEPT) }, 305 1.127 bad #ifndef __linux__ 306 1.122 ozaki { DUALCALL_PACCEPT, "paccept", RSYS_NAME(PACCEPT) }, 307 1.127 bad #endif 308 1.17 pooka { DUALCALL_BIND, "bind", RSYS_NAME(BIND) }, 309 1.17 pooka { DUALCALL_CONNECT, "connect", RSYS_NAME(CONNECT) }, 310 1.17 pooka { DUALCALL_GETPEERNAME, "getpeername", RSYS_NAME(GETPEERNAME) }, 311 1.17 pooka { DUALCALL_GETSOCKNAME, "getsockname", RSYS_NAME(GETSOCKNAME) }, 312 1.17 pooka { DUALCALL_LISTEN, "listen", RSYS_NAME(LISTEN) }, 313 1.17 pooka { DUALCALL_RECVFROM, "recvfrom", RSYS_NAME(RECVFROM) }, 314 1.17 pooka { DUALCALL_RECVMSG, "recvmsg", RSYS_NAME(RECVMSG) }, 315 1.17 pooka { DUALCALL_SENDTO, "sendto", RSYS_NAME(SENDTO) }, 316 1.17 pooka { DUALCALL_SENDMSG, "sendmsg", RSYS_NAME(SENDMSG) }, 317 1.17 pooka { DUALCALL_GETSOCKOPT, "getsockopt", RSYS_NAME(GETSOCKOPT) }, 318 1.17 pooka { DUALCALL_SETSOCKOPT, "setsockopt", RSYS_NAME(SETSOCKOPT) }, 319 1.17 pooka { DUALCALL_SHUTDOWN, "shutdown", RSYS_NAME(SHUTDOWN) }, 320 1.31 pooka { DUALCALL_READ, S(REALREAD), RSYS_NAME(READ) }, 321 1.17 pooka { DUALCALL_READV, "readv", RSYS_NAME(READV) }, 322 1.60 pooka { DUALCALL_PREAD, S(REALPREAD), RSYS_NAME(PREAD) }, 323 1.60 pooka { DUALCALL_PREADV, "preadv", RSYS_NAME(PREADV) }, 324 1.17 pooka { DUALCALL_WRITE, "write", RSYS_NAME(WRITE) }, 325 1.17 pooka { DUALCALL_WRITEV, "writev", RSYS_NAME(WRITEV) }, 326 1.60 pooka { DUALCALL_PWRITE, S(REALPWRITE), RSYS_NAME(PWRITE) }, 327 1.60 pooka { DUALCALL_PWRITEV, "pwritev", RSYS_NAME(PWRITEV) }, 328 1.17 pooka { DUALCALL_IOCTL, "ioctl", RSYS_NAME(IOCTL) }, 329 1.17 pooka { DUALCALL_FCNTL, "fcntl", RSYS_NAME(FCNTL) }, 330 1.140 ozaki { DUALCALL_FLOCK, "flock", RSYS_NAME(FLOCK) }, 331 1.17 pooka { DUALCALL_DUP2, "dup2", RSYS_NAME(DUP2) }, 332 1.17 pooka { DUALCALL_CLOSE, "close", RSYS_NAME(CLOSE) }, 333 1.29 pooka { DUALCALL_POLLTS, S(REALPOLLTS), RSYS_NAME(POLLTS) }, 334 1.97 pooka #ifndef __linux__ 335 1.45 pooka { DUALCALL_STAT, S(REALSTAT), RSYS_NAME(STAT) }, 336 1.45 pooka { DUALCALL_LSTAT, S(REALLSTAT), RSYS_NAME(LSTAT) }, 337 1.45 pooka { DUALCALL_FSTAT, S(REALFSTAT), RSYS_NAME(FSTAT) }, 338 1.97 pooka #endif 339 1.45 pooka { DUALCALL_CHOWN, "chown", RSYS_NAME(CHOWN) }, 340 1.45 pooka { DUALCALL_LCHOWN, "lchown", RSYS_NAME(LCHOWN) }, 341 1.45 pooka { DUALCALL_FCHOWN, "fchown", RSYS_NAME(FCHOWN) }, 342 1.45 pooka { DUALCALL_CHMOD, "chmod", RSYS_NAME(CHMOD) }, 343 1.45 pooka { DUALCALL_LCHMOD, "lchmod", RSYS_NAME(LCHMOD) }, 344 1.45 pooka { DUALCALL_FCHMOD, "fchmod", RSYS_NAME(FCHMOD) }, 345 1.45 pooka { DUALCALL_UTIMES, S(REALUTIMES), RSYS_NAME(UTIMES) }, 346 1.45 pooka { DUALCALL_LUTIMES, S(REALLUTIMES), RSYS_NAME(LUTIMES) }, 347 1.45 pooka { DUALCALL_FUTIMES, S(REALFUTIMES), RSYS_NAME(FUTIMES) }, 348 1.112 enami { DUALCALL_UTIMENSAT, "utimensat", RSYS_NAME(UTIMENSAT) }, 349 1.113 enami { DUALCALL_FUTIMENS, "futimens", RSYS_NAME(FUTIMENS) }, 350 1.45 pooka { DUALCALL_OPEN, "open", RSYS_NAME(OPEN) }, 351 1.45 pooka { DUALCALL_CHDIR, "chdir", RSYS_NAME(CHDIR) }, 352 1.45 pooka { DUALCALL_FCHDIR, "fchdir", RSYS_NAME(FCHDIR) }, 353 1.61 pooka { DUALCALL_LSEEK, "lseek", RSYS_NAME(LSEEK) }, 354 1.45 pooka { DUALCALL_UNLINK, "unlink", RSYS_NAME(UNLINK) }, 355 1.45 pooka { DUALCALL_SYMLINK, "symlink", RSYS_NAME(SYMLINK) }, 356 1.45 pooka { DUALCALL_READLINK, "readlink", RSYS_NAME(READLINK) }, 357 1.95 riastrad { DUALCALL_LINK, "link", RSYS_NAME(LINK) }, 358 1.45 pooka { DUALCALL_RENAME, "rename", RSYS_NAME(RENAME) }, 359 1.45 pooka { DUALCALL_MKDIR, "mkdir", RSYS_NAME(MKDIR) }, 360 1.45 pooka { DUALCALL_RMDIR, "rmdir", RSYS_NAME(RMDIR) }, 361 1.45 pooka { DUALCALL_TRUNCATE, "truncate", RSYS_NAME(TRUNCATE) }, 362 1.45 pooka { DUALCALL_FTRUNCATE, "ftruncate", RSYS_NAME(FTRUNCATE) }, 363 1.45 pooka { DUALCALL_FSYNC, "fsync", RSYS_NAME(FSYNC) }, 364 1.97 pooka { DUALCALL_ACCESS, "access", RSYS_NAME(ACCESS) }, 365 1.97 pooka 366 1.97 pooka #ifndef __linux__ 367 1.57 pooka { DUALCALL___GETCWD, "__getcwd", RSYS_NAME(__GETCWD) }, 368 1.98 pooka { DUALCALL_GETDENTS, S(REALGETDENTS),RSYS_NAME(GETDENTS) }, 369 1.97 pooka #endif 370 1.97 pooka 371 1.97 pooka #ifndef __linux__ 372 1.68 pooka { DUALCALL_MKNOD, S(REALMKNOD), RSYS_NAME(MKNOD) }, 373 1.97 pooka #endif 374 1.97 pooka 375 1.111 pooka #ifdef __NetBSD__ 376 1.79 bouyer { DUALCALL_GETFH, S(REALGETFH), RSYS_NAME(GETFH) }, 377 1.97 pooka { DUALCALL_FHOPEN, S(REALFHOPEN), RSYS_NAME(FHOPEN) }, 378 1.97 pooka { DUALCALL_FHSTAT, S(REALFHSTAT), RSYS_NAME(FHSTAT) }, 379 1.79 bouyer { DUALCALL_FHSTATVFS1, S(REALFHSTATVFS1),RSYS_NAME(FHSTATVFS1) }, 380 1.97 pooka #endif 381 1.97 pooka 382 1.111 pooka #ifdef HAVE_KQUEUE 383 1.97 pooka { DUALCALL_KEVENT, S(REALKEVENT), RSYS_NAME(KEVENT) }, 384 1.97 pooka #endif 385 1.96 pooka 386 1.111 pooka #ifdef __NetBSD__ 387 1.96 pooka { DUALCALL___SYSCTL, "__sysctl", RSYS_NAME(__SYSCTL) }, 388 1.126 hannken { DUALCALL_MODCTL, "modctl", RSYS_NAME(MODCTL) }, 389 1.96 pooka #endif 390 1.96 pooka 391 1.111 pooka #ifdef __NetBSD__ 392 1.96 pooka { DUALCALL_NFSSVC, "nfssvc", RSYS_NAME(NFSSVC) }, 393 1.96 pooka #endif 394 1.96 pooka 395 1.111 pooka #ifdef __NetBSD__ 396 1.128 christos { DUALCALL_STATVFS1, S(REALSTATVFS1),RSYS_NAME(STATVFS1) }, 397 1.128 christos { DUALCALL_FSTATVFS1, S(REALFSTATVFS1),RSYS_NAME(FSTATVFS1) }, 398 1.128 christos { DUALCALL_GETVFSSTAT, S(REALGETVFSSTAT),RSYS_NAME(GETVFSSTAT) }, 399 1.96 pooka #endif 400 1.96 pooka 401 1.111 pooka #ifdef __NetBSD__ 402 1.96 pooka { DUALCALL_MOUNT, S(REALMOUNT), RSYS_NAME(MOUNT) }, 403 1.96 pooka { DUALCALL_UNMOUNT, "unmount", RSYS_NAME(UNMOUNT) }, 404 1.96 pooka #endif 405 1.96 pooka 406 1.111 pooka #ifdef HAVE_FSYNC_RANGE 407 1.96 pooka { DUALCALL_FSYNC_RANGE, "fsync_range", RSYS_NAME(FSYNC_RANGE) }, 408 1.96 pooka #endif 409 1.96 pooka 410 1.111 pooka #ifdef HAVE_CHFLAGS 411 1.96 pooka { DUALCALL_CHFLAGS, "chflags", RSYS_NAME(CHFLAGS) }, 412 1.96 pooka { DUALCALL_LCHFLAGS, "lchflags", RSYS_NAME(LCHFLAGS) }, 413 1.96 pooka { DUALCALL_FCHFLAGS, "fchflags", RSYS_NAME(FCHFLAGS) }, 414 1.111 pooka #endif /* HAVE_CHFLAGS */ 415 1.96 pooka 416 1.111 pooka #ifdef HAVE___QUOTACTL 417 1.91 dholland { DUALCALL_QUOTACTL, "__quotactl", RSYS_NAME(__QUOTACTL) }, 418 1.111 pooka #endif /* HAVE___QUOTACTL */ 419 1.96 pooka 420 1.123 christos #ifdef __NetBSD__ 421 1.123 christos { DUALCALL_LINKAT, "linkat", RSYS_NAME(LINKAT) }, 422 1.123 christos #endif 423 1.131 christos { DUALCALL_PATHCONF, "pathconf", RSYS_NAME(PATHCONF) }, 424 1.131 christos { DUALCALL_LPATHCONF, "lpathconf", RSYS_NAME(LPATHCONF) }, 425 1.17 pooka }; 426 1.17 pooka #undef S 427 1.17 pooka 428 1.17 pooka struct bothsys { 429 1.17 pooka void *bs_host; 430 1.17 pooka void *bs_rump; 431 1.17 pooka } syscalls[DUALCALL__NUM]; 432 1.17 pooka #define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which 433 1.17 pooka 434 1.71 pooka static pid_t (*host_fork)(void); 435 1.71 pooka static int (*host_daemon)(int, int); 436 1.71 pooka static void * (*host_mmap)(void *, size_t, int, int, int, off_t); 437 1.71 pooka 438 1.75 pooka /* 439 1.75 pooka * This tracks if our process is in a subdirectory of /rump. 440 1.75 pooka * It's preserved over exec. 441 1.75 pooka */ 442 1.75 pooka static bool pwdinrump; 443 1.75 pooka 444 1.75 pooka enum pathtype { PATH_HOST, PATH_RUMP, PATH_RUMPBLANKET }; 445 1.75 pooka 446 1.75 pooka static bool fd_isrump(int); 447 1.75 pooka static enum pathtype path_isrump(const char *); 448 1.71 pooka 449 1.85 pooka /* default FD_SETSIZE is 256 ==> default fdoff is 128 */ 450 1.85 pooka static int hijack_fdoff = FD_SETSIZE/2; 451 1.85 pooka 452 1.71 pooka /* 453 1.71 pooka * Maintain a mapping table for the usual dup2 suspects. 454 1.74 pooka * Could use atomic ops to operate on dup2vec, but an application 455 1.74 pooka * racing there is not well-defined, so don't bother. 456 1.71 pooka */ 457 1.71 pooka /* note: you cannot change this without editing the env-passing code */ 458 1.71 pooka #define DUP2HIGH 2 459 1.71 pooka static uint32_t dup2vec[DUP2HIGH+1]; 460 1.129 kamil #define DUP2BIT (1U<<31) 461 1.130 kamil #define DUP2ALIAS (1U<<30) 462 1.130 kamil #define DUP2FDMASK ((1U<<30)-1) 463 1.71 pooka 464 1.71 pooka static bool 465 1.71 pooka isdup2d(int fd) 466 1.71 pooka { 467 1.71 pooka 468 1.71 pooka return fd <= DUP2HIGH && fd >= 0 && dup2vec[fd] & DUP2BIT; 469 1.71 pooka } 470 1.71 pooka 471 1.71 pooka static int 472 1.71 pooka mapdup2(int hostfd) 473 1.71 pooka { 474 1.71 pooka 475 1.71 pooka _DIAGASSERT(isdup2d(hostfd)); 476 1.71 pooka return dup2vec[hostfd] & DUP2FDMASK; 477 1.71 pooka } 478 1.71 pooka 479 1.71 pooka static int 480 1.71 pooka unmapdup2(int rumpfd) 481 1.71 pooka { 482 1.71 pooka int i; 483 1.71 pooka 484 1.71 pooka for (i = 0; i <= DUP2HIGH; i++) { 485 1.72 pooka if (dup2vec[i] & DUP2BIT && 486 1.72 pooka (dup2vec[i] & DUP2FDMASK) == (unsigned)rumpfd) 487 1.71 pooka return i; 488 1.71 pooka } 489 1.71 pooka return -1; 490 1.71 pooka } 491 1.71 pooka 492 1.71 pooka static void 493 1.71 pooka setdup2(int hostfd, int rumpfd) 494 1.71 pooka { 495 1.71 pooka 496 1.71 pooka if (hostfd > DUP2HIGH) { 497 1.132 christos _DIAGASSERT(/*CONSTCOND*/0); 498 1.71 pooka return; 499 1.71 pooka } 500 1.71 pooka 501 1.71 pooka dup2vec[hostfd] = DUP2BIT | DUP2ALIAS | rumpfd; 502 1.71 pooka } 503 1.71 pooka 504 1.71 pooka static void 505 1.71 pooka clrdup2(int hostfd) 506 1.71 pooka { 507 1.71 pooka 508 1.71 pooka if (hostfd > DUP2HIGH) { 509 1.132 christos _DIAGASSERT(/*CONSTCOND*/0); 510 1.71 pooka return; 511 1.71 pooka } 512 1.71 pooka 513 1.71 pooka dup2vec[hostfd] = 0; 514 1.71 pooka } 515 1.71 pooka 516 1.71 pooka static bool 517 1.71 pooka killdup2alias(int rumpfd) 518 1.71 pooka { 519 1.71 pooka int hostfd; 520 1.71 pooka 521 1.71 pooka if ((hostfd = unmapdup2(rumpfd)) == -1) 522 1.71 pooka return false; 523 1.71 pooka 524 1.71 pooka if (dup2vec[hostfd] & DUP2ALIAS) { 525 1.71 pooka dup2vec[hostfd] &= ~DUP2ALIAS; 526 1.71 pooka return true; 527 1.71 pooka } 528 1.71 pooka return false; 529 1.71 pooka } 530 1.17 pooka 531 1.17 pooka //#define DEBUGJACK 532 1.17 pooka #ifdef DEBUGJACK 533 1.17 pooka #define DPRINTF(x) mydprintf x 534 1.17 pooka static void 535 1.17 pooka mydprintf(const char *fmt, ...) 536 1.17 pooka { 537 1.17 pooka va_list ap; 538 1.17 pooka 539 1.71 pooka if (isdup2d(STDERR_FILENO)) 540 1.17 pooka return; 541 1.17 pooka 542 1.17 pooka va_start(ap, fmt); 543 1.17 pooka vfprintf(stderr, fmt, ap); 544 1.17 pooka va_end(ap); 545 1.17 pooka } 546 1.17 pooka 547 1.71 pooka static const char * 548 1.71 pooka whichfd(int fd) 549 1.71 pooka { 550 1.71 pooka 551 1.71 pooka if (fd == -1) 552 1.71 pooka return "-1"; 553 1.71 pooka else if (fd_isrump(fd)) 554 1.71 pooka return "rump"; 555 1.71 pooka else 556 1.71 pooka return "host"; 557 1.71 pooka } 558 1.71 pooka 559 1.71 pooka static const char * 560 1.71 pooka whichpath(const char *path) 561 1.71 pooka { 562 1.71 pooka 563 1.71 pooka if (path_isrump(path)) 564 1.71 pooka return "rump"; 565 1.71 pooka else 566 1.71 pooka return "host"; 567 1.71 pooka } 568 1.71 pooka 569 1.17 pooka #else 570 1.17 pooka #define DPRINTF(x) 571 1.14 pooka #endif 572 1.14 pooka 573 1.114 pooka #define ATCALL(type, name, rcname, args, proto, vars) \ 574 1.114 pooka type name args \ 575 1.114 pooka { \ 576 1.114 pooka type (*fun) proto; \ 577 1.114 pooka int isrump = -1; \ 578 1.114 pooka \ 579 1.115 pooka if (fd == AT_FDCWD || *path == '/') { \ 580 1.114 pooka isrump = path_isrump(path); \ 581 1.114 pooka } else { \ 582 1.114 pooka isrump = fd_isrump(fd); \ 583 1.114 pooka } \ 584 1.114 pooka \ 585 1.114 pooka DPRINTF(("%s -> %d:%s (%s)\n", __STRING(name), \ 586 1.114 pooka fd, path, isrump ? "rump" : "host")); \ 587 1.114 pooka \ 588 1.114 pooka assert(isrump != -1); \ 589 1.114 pooka if (isrump) { \ 590 1.114 pooka fun = syscalls[rcname].bs_rump; \ 591 1.114 pooka if (fd != AT_FDCWD) \ 592 1.114 pooka fd = fd_host2rump(fd); \ 593 1.114 pooka path = path_host2rump(path); \ 594 1.114 pooka } else { \ 595 1.114 pooka fun = syscalls[rcname].bs_host; \ 596 1.114 pooka } \ 597 1.114 pooka return fun vars; \ 598 1.114 pooka } 599 1.114 pooka 600 1.17 pooka #define FDCALL(type, name, rcname, args, proto, vars) \ 601 1.17 pooka type name args \ 602 1.17 pooka { \ 603 1.17 pooka type (*fun) proto; \ 604 1.17 pooka \ 605 1.71 pooka DPRINTF(("%s -> %d (%s)\n", __STRING(name), fd, whichfd(fd))); \ 606 1.17 pooka if (fd_isrump(fd)) { \ 607 1.17 pooka fun = syscalls[rcname].bs_rump; \ 608 1.17 pooka fd = fd_host2rump(fd); \ 609 1.17 pooka } else { \ 610 1.17 pooka fun = syscalls[rcname].bs_host; \ 611 1.17 pooka } \ 612 1.17 pooka \ 613 1.17 pooka return fun vars; \ 614 1.17 pooka } 615 1.17 pooka 616 1.45 pooka #define PATHCALL(type, name, rcname, args, proto, vars) \ 617 1.45 pooka type name args \ 618 1.45 pooka { \ 619 1.45 pooka type (*fun) proto; \ 620 1.75 pooka enum pathtype pt; \ 621 1.45 pooka \ 622 1.71 pooka DPRINTF(("%s -> %s (%s)\n", __STRING(name), path, \ 623 1.71 pooka whichpath(path))); \ 624 1.75 pooka if ((pt = path_isrump(path)) != PATH_HOST) { \ 625 1.45 pooka fun = syscalls[rcname].bs_rump; \ 626 1.75 pooka if (pt == PATH_RUMP) \ 627 1.75 pooka path = path_host2rump(path); \ 628 1.45 pooka } else { \ 629 1.45 pooka fun = syscalls[rcname].bs_host; \ 630 1.45 pooka } \ 631 1.45 pooka \ 632 1.45 pooka return fun vars; \ 633 1.45 pooka } 634 1.45 pooka 635 1.78 pooka #define VFSCALL(bit, type, name, rcname, args, proto, vars) \ 636 1.78 pooka type name args \ 637 1.78 pooka { \ 638 1.78 pooka type (*fun) proto; \ 639 1.78 pooka \ 640 1.78 pooka DPRINTF(("%s (0x%x, 0x%x)\n", __STRING(name), bit, vfsbits)); \ 641 1.78 pooka if (vfsbits & bit) { \ 642 1.78 pooka fun = syscalls[rcname].bs_rump; \ 643 1.78 pooka } else { \ 644 1.78 pooka fun = syscalls[rcname].bs_host; \ 645 1.78 pooka } \ 646 1.78 pooka \ 647 1.78 pooka return fun vars; \ 648 1.78 pooka } 649 1.78 pooka 650 1.14 pooka /* 651 1.49 pooka * These variables are set from the RUMPHIJACK string and control 652 1.49 pooka * which operations can product rump kernel file descriptors. 653 1.49 pooka * This should be easily extendable for future needs. 654 1.49 pooka */ 655 1.49 pooka #define RUMPHIJACK_DEFAULT "path=/rump,socket=all:nolocal" 656 1.49 pooka static bool rumpsockets[PF_MAX]; 657 1.49 pooka static const char *rumpprefix; 658 1.49 pooka static size_t rumpprefixlen; 659 1.49 pooka 660 1.49 pooka static struct { 661 1.49 pooka int pf; 662 1.49 pooka const char *name; 663 1.49 pooka } socketmap[] = { 664 1.51 pooka { PF_LOCAL, "local" }, 665 1.49 pooka { PF_INET, "inet" }, 666 1.96 pooka #ifdef PF_LINK 667 1.49 pooka { PF_LINK, "link" }, 668 1.96 pooka #endif 669 1.55 pooka #ifdef PF_OROUTE 670 1.56 pooka { PF_OROUTE, "oroute" }, 671 1.56 pooka #endif 672 1.49 pooka { PF_ROUTE, "route" }, 673 1.49 pooka { PF_INET6, "inet6" }, 674 1.55 pooka #ifdef PF_MPLS 675 1.55 pooka { PF_MPLS, "mpls" }, 676 1.55 pooka #endif 677 1.49 pooka { -1, NULL } 678 1.49 pooka }; 679 1.49 pooka 680 1.49 pooka static void 681 1.49 pooka sockparser(char *buf) 682 1.49 pooka { 683 1.96 pooka char *p, *l = NULL; 684 1.49 pooka bool value; 685 1.49 pooka int i; 686 1.49 pooka 687 1.49 pooka /* if "all" is present, it must be specified first */ 688 1.49 pooka if (strncmp(buf, "all", strlen("all")) == 0) { 689 1.50 pooka for (i = 0; i < (int)__arraycount(rumpsockets); i++) { 690 1.49 pooka rumpsockets[i] = true; 691 1.49 pooka } 692 1.49 pooka buf += strlen("all"); 693 1.49 pooka if (*buf == ':') 694 1.49 pooka buf++; 695 1.49 pooka } 696 1.49 pooka 697 1.49 pooka for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) { 698 1.49 pooka value = true; 699 1.49 pooka if (strncmp(p, "no", strlen("no")) == 0) { 700 1.49 pooka value = false; 701 1.49 pooka p += strlen("no"); 702 1.49 pooka } 703 1.45 pooka 704 1.49 pooka for (i = 0; socketmap[i].name; i++) { 705 1.49 pooka if (strcmp(p, socketmap[i].name) == 0) { 706 1.49 pooka rumpsockets[socketmap[i].pf] = value; 707 1.49 pooka break; 708 1.49 pooka } 709 1.49 pooka } 710 1.49 pooka if (socketmap[i].name == NULL) { 711 1.132 christos errx(EXIT_FAILURE, "invalid socket specifier %s", p); 712 1.49 pooka } 713 1.49 pooka } 714 1.49 pooka } 715 1.49 pooka 716 1.49 pooka static void 717 1.49 pooka pathparser(char *buf) 718 1.49 pooka { 719 1.49 pooka 720 1.57 pooka /* sanity-check */ 721 1.49 pooka if (*buf != '/') 722 1.132 christos errx(EXIT_FAILURE, 723 1.132 christos "hijack path specifier must begin with ``/''"); 724 1.57 pooka rumpprefixlen = strlen(buf); 725 1.57 pooka if (rumpprefixlen < 2) 726 1.132 christos errx(EXIT_FAILURE, "invalid hijack prefix: %s", buf); 727 1.57 pooka if (buf[rumpprefixlen-1] == '/' && strspn(buf, "/") != rumpprefixlen) 728 1.132 christos errx(EXIT_FAILURE, "hijack prefix may end in slash only if " 729 1.132 christos "pure slash, gave %s", buf); 730 1.49 pooka 731 1.49 pooka if ((rumpprefix = strdup(buf)) == NULL) 732 1.132 christos err(EXIT_FAILURE, "strdup"); 733 1.49 pooka rumpprefixlen = strlen(rumpprefix); 734 1.49 pooka } 735 1.49 pooka 736 1.75 pooka static struct blanket { 737 1.75 pooka const char *pfx; 738 1.75 pooka size_t len; 739 1.75 pooka } *blanket; 740 1.75 pooka static int nblanket; 741 1.75 pooka 742 1.75 pooka static void 743 1.75 pooka blanketparser(char *buf) 744 1.75 pooka { 745 1.96 pooka char *p, *l = NULL; 746 1.75 pooka int i; 747 1.75 pooka 748 1.75 pooka for (nblanket = 0, p = buf; p; p = strchr(p+1, ':'), nblanket++) 749 1.75 pooka continue; 750 1.75 pooka 751 1.75 pooka blanket = malloc(nblanket * sizeof(*blanket)); 752 1.75 pooka if (blanket == NULL) 753 1.132 christos err(EXIT_FAILURE, "alloc blanket %d", nblanket); 754 1.75 pooka 755 1.75 pooka for (p = strtok_r(buf, ":", &l), i = 0; p; 756 1.75 pooka p = strtok_r(NULL, ":", &l), i++) { 757 1.75 pooka blanket[i].pfx = strdup(p); 758 1.75 pooka if (blanket[i].pfx == NULL) 759 1.132 christos err(EXIT_FAILURE, "strdup blanket"); 760 1.75 pooka blanket[i].len = strlen(p); 761 1.75 pooka 762 1.75 pooka if (blanket[i].len == 0 || *blanket[i].pfx != '/') 763 1.132 christos errx(EXIT_FAILURE, "invalid blanket specifier %s", p); 764 1.75 pooka if (*(blanket[i].pfx + blanket[i].len-1) == '/') 765 1.132 christos errx(EXIT_FAILURE, "invalid blanket specifier %s", p); 766 1.75 pooka } 767 1.75 pooka } 768 1.75 pooka 769 1.78 pooka #define VFSBIT_NFSSVC 0x01 770 1.78 pooka #define VFSBIT_GETVFSSTAT 0x02 771 1.78 pooka #define VFSBIT_FHCALLS 0x04 772 1.78 pooka static unsigned vfsbits; 773 1.78 pooka 774 1.78 pooka static struct { 775 1.78 pooka int bit; 776 1.78 pooka const char *name; 777 1.78 pooka } vfscalls[] = { 778 1.78 pooka { VFSBIT_NFSSVC, "nfssvc" }, 779 1.78 pooka { VFSBIT_GETVFSSTAT, "getvfsstat" }, 780 1.78 pooka { VFSBIT_FHCALLS, "fhcalls" }, 781 1.78 pooka { -1, NULL } 782 1.78 pooka }; 783 1.78 pooka 784 1.78 pooka static void 785 1.78 pooka vfsparser(char *buf) 786 1.78 pooka { 787 1.96 pooka char *p, *l = NULL; 788 1.78 pooka bool turnon; 789 1.78 pooka unsigned int fullmask; 790 1.78 pooka int i; 791 1.78 pooka 792 1.78 pooka /* build the full mask and sanity-check while we're at it */ 793 1.78 pooka fullmask = 0; 794 1.78 pooka for (i = 0; vfscalls[i].name != NULL; i++) { 795 1.78 pooka if (fullmask & vfscalls[i].bit) 796 1.132 christos errx(EXIT_FAILURE, 797 1.132 christos "problem exists between vi and chair"); 798 1.78 pooka fullmask |= vfscalls[i].bit; 799 1.78 pooka } 800 1.78 pooka 801 1.78 pooka 802 1.78 pooka /* if "all" is present, it must be specified first */ 803 1.78 pooka if (strncmp(buf, "all", strlen("all")) == 0) { 804 1.78 pooka vfsbits = fullmask; 805 1.78 pooka buf += strlen("all"); 806 1.78 pooka if (*buf == ':') 807 1.78 pooka buf++; 808 1.78 pooka } 809 1.78 pooka 810 1.78 pooka for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) { 811 1.78 pooka turnon = true; 812 1.78 pooka if (strncmp(p, "no", strlen("no")) == 0) { 813 1.78 pooka turnon = false; 814 1.78 pooka p += strlen("no"); 815 1.78 pooka } 816 1.78 pooka 817 1.78 pooka for (i = 0; vfscalls[i].name; i++) { 818 1.78 pooka if (strcmp(p, vfscalls[i].name) == 0) { 819 1.78 pooka if (turnon) 820 1.78 pooka vfsbits |= vfscalls[i].bit; 821 1.78 pooka else 822 1.78 pooka vfsbits &= ~vfscalls[i].bit; 823 1.78 pooka break; 824 1.78 pooka } 825 1.78 pooka } 826 1.78 pooka if (vfscalls[i].name == NULL) { 827 1.132 christos errx(EXIT_FAILURE, "invalid vfscall specifier %s", p); 828 1.78 pooka } 829 1.78 pooka } 830 1.78 pooka } 831 1.78 pooka 832 1.78 pooka static bool rumpsysctl = false; 833 1.78 pooka 834 1.78 pooka static void 835 1.78 pooka sysctlparser(char *buf) 836 1.78 pooka { 837 1.78 pooka 838 1.78 pooka if (buf == NULL) { 839 1.78 pooka rumpsysctl = true; 840 1.78 pooka return; 841 1.78 pooka } 842 1.78 pooka 843 1.78 pooka if (strcasecmp(buf, "y") == 0 || strcasecmp(buf, "yes") == 0 || 844 1.78 pooka strcasecmp(buf, "yep") == 0 || strcasecmp(buf, "tottakai") == 0) { 845 1.78 pooka rumpsysctl = true; 846 1.78 pooka return; 847 1.78 pooka } 848 1.78 pooka if (strcasecmp(buf, "n") == 0 || strcasecmp(buf, "no") == 0) { 849 1.78 pooka rumpsysctl = false; 850 1.78 pooka return; 851 1.78 pooka } 852 1.78 pooka 853 1.132 christos errx(EXIT_FAILURE, "sysctl value should be y(es)/n(o), gave: %s", buf); 854 1.78 pooka } 855 1.78 pooka 856 1.126 hannken static bool rumpmodctl = false; 857 1.126 hannken 858 1.126 hannken static void 859 1.126 hannken modctlparser(char *buf) 860 1.126 hannken { 861 1.126 hannken 862 1.126 hannken if (buf == NULL) { 863 1.126 hannken rumpmodctl = true; 864 1.126 hannken return; 865 1.126 hannken } 866 1.126 hannken 867 1.126 hannken if (strcasecmp(buf, "y") == 0 || strcasecmp(buf, "yes") == 0 || 868 1.126 hannken strcasecmp(buf, "yep") == 0 || strcasecmp(buf, "tottakai") == 0) { 869 1.126 hannken rumpmodctl = true; 870 1.126 hannken return; 871 1.126 hannken } 872 1.126 hannken if (strcasecmp(buf, "n") == 0 || strcasecmp(buf, "no") == 0) { 873 1.126 hannken rumpmodctl = false; 874 1.126 hannken return; 875 1.126 hannken } 876 1.126 hannken 877 1.132 christos errx(EXIT_FAILURE, "modctl value should be y(es)/n(o), gave: %s", buf); 878 1.126 hannken } 879 1.126 hannken 880 1.85 pooka static void 881 1.85 pooka fdoffparser(char *buf) 882 1.85 pooka { 883 1.85 pooka unsigned long fdoff; 884 1.85 pooka char *ep; 885 1.85 pooka 886 1.85 pooka if (*buf == '-') { 887 1.132 christos errx(EXIT_FAILURE, "fdoff must not be negative"); 888 1.85 pooka } 889 1.85 pooka fdoff = strtoul(buf, &ep, 10); 890 1.85 pooka if (*ep != '\0') 891 1.132 christos errx(EXIT_FAILURE, "invalid fdoff specifier \"%s\"", buf); 892 1.85 pooka if (fdoff >= INT_MAX/2 || fdoff < 3) 893 1.132 christos errx(EXIT_FAILURE, "fdoff out of range"); 894 1.132 christos hijack_fdoff = (int)fdoff; 895 1.85 pooka } 896 1.85 pooka 897 1.49 pooka static struct { 898 1.49 pooka void (*parsefn)(char *); 899 1.49 pooka const char *name; 900 1.78 pooka bool needvalues; 901 1.49 pooka } hijackparse[] = { 902 1.78 pooka { sockparser, "socket", true }, 903 1.78 pooka { pathparser, "path", true }, 904 1.78 pooka { blanketparser, "blanket", true }, 905 1.78 pooka { vfsparser, "vfs", true }, 906 1.78 pooka { sysctlparser, "sysctl", false }, 907 1.126 hannken { modctlparser, "modctl", false }, 908 1.86 pooka { fdoffparser, "fdoff", true }, 909 1.78 pooka { NULL, NULL, false }, 910 1.49 pooka }; 911 1.49 pooka 912 1.49 pooka static void 913 1.49 pooka parsehijack(char *hijack) 914 1.49 pooka { 915 1.49 pooka char *p, *p2, *l; 916 1.49 pooka const char *hijackcopy; 917 1.78 pooka bool nop2; 918 1.49 pooka int i; 919 1.49 pooka 920 1.49 pooka if ((hijackcopy = strdup(hijack)) == NULL) 921 1.132 christos err(EXIT_FAILURE, "strdup"); 922 1.49 pooka 923 1.49 pooka /* disable everything explicitly */ 924 1.49 pooka for (i = 0; i < PF_MAX; i++) 925 1.49 pooka rumpsockets[i] = false; 926 1.49 pooka 927 1.49 pooka for (p = strtok_r(hijack, ",", &l); p; p = strtok_r(NULL, ",", &l)) { 928 1.78 pooka nop2 = false; 929 1.49 pooka p2 = strchr(p, '='); 930 1.78 pooka if (!p2) { 931 1.78 pooka nop2 = true; 932 1.78 pooka p2 = p + strlen(p); 933 1.78 pooka } 934 1.49 pooka 935 1.49 pooka for (i = 0; hijackparse[i].parsefn; i++) { 936 1.49 pooka if (strncmp(hijackparse[i].name, p, 937 1.49 pooka (size_t)(p2-p)) == 0) { 938 1.78 pooka if (nop2 && hijackparse[i].needvalues) 939 1.132 christos errx(EXIT_FAILURE, "invalid hijack specifier: %s", 940 1.78 pooka hijackcopy); 941 1.78 pooka hijackparse[i].parsefn(nop2 ? NULL : p2+1); 942 1.49 pooka break; 943 1.49 pooka } 944 1.49 pooka } 945 1.81 pooka 946 1.81 pooka if (hijackparse[i].parsefn == NULL) 947 1.132 christos errx(EXIT_FAILURE, 948 1.132 christos "invalid hijack specifier name in %s", p); 949 1.49 pooka } 950 1.49 pooka 951 1.49 pooka } 952 1.7 pooka 953 1.132 christos static void __attribute__((__constructor__)) 954 1.1 pooka rcinit(void) 955 1.1 pooka { 956 1.49 pooka char buf[1024]; 957 1.19 pooka unsigned i, j; 958 1.1 pooka 959 1.17 pooka host_fork = dlsym(RTLD_NEXT, "fork"); 960 1.25 pooka host_daemon = dlsym(RTLD_NEXT, "daemon"); 961 1.118 pooka if (host_mmap == NULL) 962 1.118 pooka host_mmap = dlsym(RTLD_NEXT, "mmap"); 963 1.17 pooka 964 1.17 pooka /* 965 1.17 pooka * In theory cannot print anything during lookups because 966 1.17 pooka * we might not have the call vector set up. so, the errx() 967 1.136 andvar * is a bit of a stretch, but it might work. 968 1.17 pooka */ 969 1.1 pooka 970 1.17 pooka for (i = 0; i < DUALCALL__NUM; i++) { 971 1.17 pooka /* build runtime O(1) access */ 972 1.83 pooka for (j = 0; j < __arraycount(syscnames); j++) { 973 1.83 pooka if (syscnames[j].scm_callnum == i) 974 1.83 pooka break; 975 1.83 pooka } 976 1.81 pooka 977 1.83 pooka if (j == __arraycount(syscnames)) 978 1.132 christos errx(EXIT_FAILURE, 979 1.132 christos "rumphijack error: syscall pos %d missing", i); 980 1.17 pooka 981 1.23 pooka syscalls[i].bs_host = dlsym(RTLD_NEXT, 982 1.83 pooka syscnames[j].scm_hostname); 983 1.83 pooka if (syscalls[i].bs_host == NULL) 984 1.132 christos errx(EXIT_FAILURE, "hostcall %s not found!", 985 1.83 pooka syscnames[j].scm_hostname); 986 1.17 pooka 987 1.23 pooka syscalls[i].bs_rump = dlsym(RTLD_NEXT, 988 1.83 pooka syscnames[j].scm_rumpname); 989 1.17 pooka if (syscalls[i].bs_rump == NULL) 990 1.132 christos errx(EXIT_FAILURE, "rumpcall %s not found!", 991 1.83 pooka syscnames[j].scm_rumpname); 992 1.132 christos #if 0 993 1.132 christos fprintf(stderr, "%s %p %s %p\n", 994 1.132 christos syscnames[j].scm_hostname, syscalls[i].bs_host, 995 1.132 christos syscnames[j].scm_rumpname, syscalls[i].bs_rump); 996 1.132 christos #endif 997 1.1 pooka } 998 1.1 pooka 999 1.22 pooka if (rumpclient_init() == -1) 1000 1.132 christos err(EXIT_FAILURE, "rumpclient init"); 1001 1.28 pooka 1002 1.49 pooka /* check which syscalls we're supposed to hijack */ 1003 1.49 pooka if (getenv_r("RUMPHIJACK", buf, sizeof(buf)) == -1) { 1004 1.49 pooka strcpy(buf, RUMPHIJACK_DEFAULT); 1005 1.49 pooka } 1006 1.49 pooka parsehijack(buf); 1007 1.49 pooka 1008 1.28 pooka /* set client persistence level */ 1009 1.44 pooka if (getenv_r("RUMPHIJACK_RETRYCONNECT", buf, sizeof(buf)) != -1) { 1010 1.28 pooka if (strcmp(buf, "die") == 0) 1011 1.28 pooka rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_DIE); 1012 1.28 pooka else if (strcmp(buf, "inftime") == 0) 1013 1.28 pooka rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_INFTIME); 1014 1.28 pooka else if (strcmp(buf, "once") == 0) 1015 1.28 pooka rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_ONCE); 1016 1.28 pooka else { 1017 1.28 pooka time_t timeout; 1018 1.44 pooka char *ep; 1019 1.28 pooka 1020 1.44 pooka timeout = (time_t)strtoll(buf, &ep, 10); 1021 1.44 pooka if (timeout <= 0 || ep != buf + strlen(buf)) 1022 1.132 christos errx(EXIT_FAILURE, 1023 1.132 christos "RUMPHIJACK_RETRYCONNECT must be " 1024 1.44 pooka "keyword or integer, got: %s", buf); 1025 1.28 pooka 1026 1.28 pooka rumpclient_setconnretry(timeout); 1027 1.28 pooka } 1028 1.28 pooka } 1029 1.39 pooka 1030 1.71 pooka if (getenv_r("RUMPHIJACK__DUP2INFO", buf, sizeof(buf)) == 0) { 1031 1.71 pooka if (sscanf(buf, "%u,%u,%u", 1032 1.71 pooka &dup2vec[0], &dup2vec[1], &dup2vec[2]) != 3) { 1033 1.71 pooka warnx("invalid dup2mask: %s", buf); 1034 1.71 pooka memset(dup2vec, 0, sizeof(dup2vec)); 1035 1.71 pooka } 1036 1.71 pooka unsetenv("RUMPHIJACK__DUP2INFO"); 1037 1.45 pooka } 1038 1.45 pooka if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) { 1039 1.49 pooka pwdinrump = true; 1040 1.45 pooka unsetenv("RUMPHIJACK__PWDINRUMP"); 1041 1.39 pooka } 1042 1.1 pooka } 1043 1.1 pooka 1044 1.2 pooka static int 1045 1.2 pooka fd_rump2host(int fd) 1046 1.2 pooka { 1047 1.2 pooka 1048 1.2 pooka if (fd == -1) 1049 1.2 pooka return fd; 1050 1.85 pooka return fd + hijack_fdoff; 1051 1.71 pooka } 1052 1.2 pooka 1053 1.71 pooka static int 1054 1.71 pooka fd_rump2host_withdup(int fd) 1055 1.71 pooka { 1056 1.71 pooka int hfd; 1057 1.2 pooka 1058 1.71 pooka _DIAGASSERT(fd != -1); 1059 1.71 pooka hfd = unmapdup2(fd); 1060 1.71 pooka if (hfd != -1) { 1061 1.71 pooka _DIAGASSERT(hfd <= DUP2HIGH); 1062 1.71 pooka return hfd; 1063 1.71 pooka } 1064 1.71 pooka return fd_rump2host(fd); 1065 1.2 pooka } 1066 1.2 pooka 1067 1.2 pooka static int 1068 1.2 pooka fd_host2rump(int fd) 1069 1.2 pooka { 1070 1.71 pooka if (!isdup2d(fd)) 1071 1.85 pooka return fd - hijack_fdoff; 1072 1.71 pooka else 1073 1.71 pooka return mapdup2(fd); 1074 1.2 pooka } 1075 1.2 pooka 1076 1.2 pooka static bool 1077 1.2 pooka fd_isrump(int fd) 1078 1.2 pooka { 1079 1.2 pooka 1080 1.85 pooka return isdup2d(fd) || fd >= hijack_fdoff; 1081 1.2 pooka } 1082 1.2 pooka 1083 1.85 pooka #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= hijack_fdoff) 1084 1.40 pooka 1085 1.75 pooka static enum pathtype 1086 1.45 pooka path_isrump(const char *path) 1087 1.45 pooka { 1088 1.76 pooka size_t plen; 1089 1.75 pooka int i; 1090 1.45 pooka 1091 1.75 pooka if (rumpprefix == NULL && nblanket == 0) 1092 1.75 pooka return PATH_HOST; 1093 1.49 pooka 1094 1.45 pooka if (*path == '/') { 1095 1.76 pooka plen = strlen(path); 1096 1.76 pooka if (rumpprefix && plen >= rumpprefixlen) { 1097 1.76 pooka if (strncmp(path, rumpprefix, rumpprefixlen) == 0 1098 1.76 pooka && (plen == rumpprefixlen 1099 1.76 pooka || *(path + rumpprefixlen) == '/')) { 1100 1.75 pooka return PATH_RUMP; 1101 1.75 pooka } 1102 1.75 pooka } 1103 1.75 pooka for (i = 0; i < nblanket; i++) { 1104 1.75 pooka if (strncmp(path, blanket[i].pfx, blanket[i].len) == 0) 1105 1.75 pooka return PATH_RUMPBLANKET; 1106 1.75 pooka } 1107 1.75 pooka 1108 1.75 pooka return PATH_HOST; 1109 1.45 pooka } else { 1110 1.75 pooka return pwdinrump ? PATH_RUMP : PATH_HOST; 1111 1.45 pooka } 1112 1.45 pooka } 1113 1.45 pooka 1114 1.45 pooka static const char *rootpath = "/"; 1115 1.45 pooka static const char * 1116 1.45 pooka path_host2rump(const char *path) 1117 1.45 pooka { 1118 1.45 pooka const char *rv; 1119 1.45 pooka 1120 1.45 pooka if (*path == '/') { 1121 1.49 pooka rv = path + rumpprefixlen; 1122 1.45 pooka if (*rv == '\0') 1123 1.45 pooka rv = rootpath; 1124 1.45 pooka } else { 1125 1.45 pooka rv = path; 1126 1.45 pooka } 1127 1.45 pooka 1128 1.45 pooka return rv; 1129 1.45 pooka } 1130 1.45 pooka 1131 1.40 pooka static int 1132 1.40 pooka dodup(int oldd, int minfd) 1133 1.40 pooka { 1134 1.40 pooka int (*op_fcntl)(int, int, ...); 1135 1.40 pooka int newd; 1136 1.40 pooka int isrump; 1137 1.40 pooka 1138 1.40 pooka DPRINTF(("dup -> %d (minfd %d)\n", oldd, minfd)); 1139 1.40 pooka if (fd_isrump(oldd)) { 1140 1.40 pooka op_fcntl = GETSYSCALL(rump, FCNTL); 1141 1.40 pooka oldd = fd_host2rump(oldd); 1142 1.85 pooka if (minfd >= hijack_fdoff) 1143 1.85 pooka minfd -= hijack_fdoff; 1144 1.40 pooka isrump = 1; 1145 1.40 pooka } else { 1146 1.120 kre if (minfd >= hijack_fdoff) { 1147 1.120 kre errno = EINVAL; 1148 1.120 kre return -1; 1149 1.120 kre } 1150 1.40 pooka op_fcntl = GETSYSCALL(host, FCNTL); 1151 1.40 pooka isrump = 0; 1152 1.40 pooka } 1153 1.40 pooka 1154 1.40 pooka newd = op_fcntl(oldd, F_DUPFD, minfd); 1155 1.40 pooka 1156 1.40 pooka if (isrump) 1157 1.40 pooka newd = fd_rump2host(newd); 1158 1.40 pooka DPRINTF(("dup <- %d\n", newd)); 1159 1.40 pooka 1160 1.40 pooka return newd; 1161 1.40 pooka } 1162 1.2 pooka 1163 1.47 pooka /* 1164 1.85 pooka * Check that host fd value does not exceed fdoffset and if necessary 1165 1.85 pooka * dup the file descriptor so that it doesn't collide with the dup2mask. 1166 1.47 pooka */ 1167 1.47 pooka static int 1168 1.85 pooka fd_host2host(int fd) 1169 1.47 pooka { 1170 1.47 pooka int (*op_fcntl)(int, int, ...) = GETSYSCALL(host, FCNTL); 1171 1.47 pooka int (*op_close)(int) = GETSYSCALL(host, CLOSE); 1172 1.47 pooka int ofd, i; 1173 1.47 pooka 1174 1.85 pooka if (fd >= hijack_fdoff) { 1175 1.85 pooka op_close(fd); 1176 1.85 pooka errno = ENFILE; 1177 1.85 pooka return -1; 1178 1.85 pooka } 1179 1.85 pooka 1180 1.71 pooka for (i = 1; isdup2d(fd); i++) { 1181 1.47 pooka ofd = fd; 1182 1.47 pooka fd = op_fcntl(ofd, F_DUPFD, i); 1183 1.47 pooka op_close(ofd); 1184 1.47 pooka } 1185 1.47 pooka 1186 1.47 pooka return fd; 1187 1.47 pooka } 1188 1.47 pooka 1189 1.45 pooka int 1190 1.45 pooka open(const char *path, int flags, ...) 1191 1.45 pooka { 1192 1.45 pooka int (*op_open)(const char *, int, ...); 1193 1.45 pooka bool isrump; 1194 1.45 pooka va_list ap; 1195 1.75 pooka enum pathtype pt; 1196 1.132 christos int fd, rfd; 1197 1.45 pooka 1198 1.132 christos DPRINTF(("open -> %s (%s)", path, whichpath(path))); 1199 1.71 pooka 1200 1.75 pooka if ((pt = path_isrump(path)) != PATH_HOST) { 1201 1.75 pooka if (pt == PATH_RUMP) 1202 1.75 pooka path = path_host2rump(path); 1203 1.45 pooka op_open = GETSYSCALL(rump, OPEN); 1204 1.45 pooka isrump = true; 1205 1.45 pooka } else { 1206 1.45 pooka op_open = GETSYSCALL(host, OPEN); 1207 1.45 pooka isrump = false; 1208 1.45 pooka } 1209 1.45 pooka 1210 1.45 pooka va_start(ap, flags); 1211 1.45 pooka fd = op_open(path, flags, va_arg(ap, mode_t)); 1212 1.45 pooka va_end(ap); 1213 1.45 pooka 1214 1.45 pooka if (isrump) 1215 1.132 christos rfd = fd_rump2host(fd); 1216 1.47 pooka else 1217 1.132 christos rfd = fd_host2host(fd); 1218 1.71 pooka 1219 1.132 christos DPRINTF((" <- %d/%d (%s)\n", fd, rfd, whichfd(rfd))); 1220 1.132 christos return rfd; 1221 1.45 pooka } 1222 1.45 pooka 1223 1.45 pooka int 1224 1.45 pooka chdir(const char *path) 1225 1.45 pooka { 1226 1.45 pooka int (*op_chdir)(const char *); 1227 1.75 pooka enum pathtype pt; 1228 1.45 pooka int rv; 1229 1.45 pooka 1230 1.75 pooka if ((pt = path_isrump(path)) != PATH_HOST) { 1231 1.45 pooka op_chdir = GETSYSCALL(rump, CHDIR); 1232 1.75 pooka if (pt == PATH_RUMP) 1233 1.75 pooka path = path_host2rump(path); 1234 1.45 pooka } else { 1235 1.45 pooka op_chdir = GETSYSCALL(host, CHDIR); 1236 1.45 pooka } 1237 1.45 pooka 1238 1.45 pooka rv = op_chdir(path); 1239 1.75 pooka if (rv == 0) 1240 1.75 pooka pwdinrump = pt != PATH_HOST; 1241 1.45 pooka 1242 1.45 pooka return rv; 1243 1.45 pooka } 1244 1.45 pooka 1245 1.45 pooka int 1246 1.45 pooka fchdir(int fd) 1247 1.45 pooka { 1248 1.45 pooka int (*op_fchdir)(int); 1249 1.45 pooka bool isrump; 1250 1.45 pooka int rv; 1251 1.45 pooka 1252 1.45 pooka if (fd_isrump(fd)) { 1253 1.45 pooka op_fchdir = GETSYSCALL(rump, FCHDIR); 1254 1.45 pooka isrump = true; 1255 1.45 pooka fd = fd_host2rump(fd); 1256 1.45 pooka } else { 1257 1.45 pooka op_fchdir = GETSYSCALL(host, FCHDIR); 1258 1.45 pooka isrump = false; 1259 1.45 pooka } 1260 1.45 pooka 1261 1.45 pooka rv = op_fchdir(fd); 1262 1.45 pooka if (rv == 0) { 1263 1.75 pooka pwdinrump = isrump; 1264 1.45 pooka } 1265 1.45 pooka 1266 1.45 pooka return rv; 1267 1.45 pooka } 1268 1.45 pooka 1269 1.97 pooka #ifndef __linux__ 1270 1.52 pooka int 1271 1.57 pooka __getcwd(char *bufp, size_t len) 1272 1.57 pooka { 1273 1.57 pooka int (*op___getcwd)(char *, size_t); 1274 1.75 pooka size_t prefixgap; 1275 1.75 pooka bool iamslash; 1276 1.57 pooka int rv; 1277 1.57 pooka 1278 1.75 pooka if (pwdinrump && rumpprefix) { 1279 1.57 pooka if (rumpprefix[rumpprefixlen-1] == '/') 1280 1.57 pooka iamslash = true; 1281 1.57 pooka else 1282 1.57 pooka iamslash = false; 1283 1.57 pooka 1284 1.57 pooka if (iamslash) 1285 1.57 pooka prefixgap = rumpprefixlen - 1; /* ``//+path'' */ 1286 1.57 pooka else 1287 1.57 pooka prefixgap = rumpprefixlen; /* ``/pfx+/path'' */ 1288 1.57 pooka if (len <= prefixgap) { 1289 1.66 pooka errno = ERANGE; 1290 1.66 pooka return -1; 1291 1.57 pooka } 1292 1.57 pooka 1293 1.57 pooka op___getcwd = GETSYSCALL(rump, __GETCWD); 1294 1.57 pooka rv = op___getcwd(bufp + prefixgap, len - prefixgap); 1295 1.57 pooka if (rv == -1) 1296 1.57 pooka return rv; 1297 1.57 pooka 1298 1.57 pooka /* augment the "/" part only for a non-root path */ 1299 1.57 pooka memcpy(bufp, rumpprefix, rumpprefixlen); 1300 1.57 pooka 1301 1.57 pooka /* append / only to non-root cwd */ 1302 1.57 pooka if (rv != 2) 1303 1.57 pooka bufp[prefixgap] = '/'; 1304 1.57 pooka 1305 1.57 pooka /* don't append extra slash in the purely-slash case */ 1306 1.57 pooka if (rv == 2 && !iamslash) 1307 1.57 pooka bufp[rumpprefixlen] = '\0'; 1308 1.75 pooka } else if (pwdinrump) { 1309 1.75 pooka /* assume blanket. we can't provide a prefix here */ 1310 1.75 pooka op___getcwd = GETSYSCALL(rump, __GETCWD); 1311 1.75 pooka rv = op___getcwd(bufp, len); 1312 1.57 pooka } else { 1313 1.57 pooka op___getcwd = GETSYSCALL(host, __GETCWD); 1314 1.75 pooka rv = op___getcwd(bufp, len); 1315 1.57 pooka } 1316 1.75 pooka 1317 1.75 pooka return rv; 1318 1.57 pooka } 1319 1.97 pooka #endif 1320 1.57 pooka 1321 1.95 riastrad static int 1322 1.95 riastrad moveish(const char *from, const char *to, 1323 1.95 riastrad int (*rump_op)(const char *, const char *), 1324 1.95 riastrad int (*host_op)(const char *, const char *)) 1325 1.52 pooka { 1326 1.95 riastrad int (*op)(const char *, const char *); 1327 1.75 pooka enum pathtype ptf, ptt; 1328 1.52 pooka 1329 1.75 pooka if ((ptf = path_isrump(from)) != PATH_HOST) { 1330 1.75 pooka if ((ptt = path_isrump(to)) == PATH_HOST) { 1331 1.66 pooka errno = EXDEV; 1332 1.66 pooka return -1; 1333 1.66 pooka } 1334 1.52 pooka 1335 1.75 pooka if (ptf == PATH_RUMP) 1336 1.75 pooka from = path_host2rump(from); 1337 1.75 pooka if (ptt == PATH_RUMP) 1338 1.75 pooka to = path_host2rump(to); 1339 1.95 riastrad op = rump_op; 1340 1.52 pooka } else { 1341 1.75 pooka if (path_isrump(to) != PATH_HOST) { 1342 1.66 pooka errno = EXDEV; 1343 1.66 pooka return -1; 1344 1.66 pooka } 1345 1.53 pooka 1346 1.95 riastrad op = host_op; 1347 1.52 pooka } 1348 1.52 pooka 1349 1.95 riastrad return op(from, to); 1350 1.95 riastrad } 1351 1.95 riastrad 1352 1.123 christos #ifdef __NetBSD__ 1353 1.123 christos int 1354 1.123 christos linkat(int fromfd, const char *from, int tofd, const char *to, int flags) 1355 1.123 christos { 1356 1.123 christos if (fromfd != AT_FDCWD || tofd != AT_FDCWD 1357 1.123 christos || flags != AT_SYMLINK_FOLLOW) 1358 1.123 christos return ENOSYS; 1359 1.123 christos 1360 1.123 christos return moveish(from, to, 1361 1.123 christos GETSYSCALL(rump, LINK), GETSYSCALL(host, LINK)); 1362 1.123 christos } 1363 1.123 christos #endif 1364 1.123 christos 1365 1.131 christos static long 1366 1.131 christos do_pathconf(const char *path, int name, int link) 1367 1.131 christos { 1368 1.131 christos long (*op_pathconf)(const char *, int); 1369 1.131 christos enum pathtype pt; 1370 1.131 christos 1371 1.131 christos if ((pt = path_isrump(path)) != PATH_HOST) { 1372 1.131 christos op_pathconf = link ? 1373 1.131 christos GETSYSCALL(rump, LPATHCONF) : 1374 1.131 christos GETSYSCALL(rump, PATHCONF); 1375 1.131 christos if (pt == PATH_RUMP) 1376 1.131 christos path = path_host2rump(path); 1377 1.131 christos } else { 1378 1.131 christos op_pathconf = link ? 1379 1.131 christos GETSYSCALL(host, LPATHCONF) : 1380 1.131 christos GETSYSCALL(host, PATHCONF); 1381 1.131 christos } 1382 1.131 christos 1383 1.131 christos return op_pathconf(path, name); 1384 1.131 christos } 1385 1.131 christos 1386 1.131 christos long 1387 1.131 christos lpathconf(const char *path, int name) 1388 1.131 christos { 1389 1.131 christos return do_pathconf(path, name, 1); 1390 1.131 christos } 1391 1.131 christos 1392 1.131 christos long 1393 1.131 christos pathconf(const char *path, int name) 1394 1.131 christos { 1395 1.131 christos return do_pathconf(path, name, 0); 1396 1.131 christos } 1397 1.131 christos 1398 1.95 riastrad int 1399 1.95 riastrad link(const char *from, const char *to) 1400 1.95 riastrad { 1401 1.95 riastrad return moveish(from, to, 1402 1.95 riastrad GETSYSCALL(rump, LINK), GETSYSCALL(host, LINK)); 1403 1.95 riastrad } 1404 1.95 riastrad 1405 1.95 riastrad int 1406 1.95 riastrad rename(const char *from, const char *to) 1407 1.95 riastrad { 1408 1.95 riastrad return moveish(from, to, 1409 1.95 riastrad GETSYSCALL(rump, RENAME), GETSYSCALL(host, RENAME)); 1410 1.52 pooka } 1411 1.52 pooka 1412 1.1 pooka int 1413 1.96 pooka REALSOCKET(int domain, int type, int protocol) 1414 1.1 pooka { 1415 1.17 pooka int (*op_socket)(int, int, int); 1416 1.132 christos int fd, rfd; 1417 1.49 pooka bool isrump; 1418 1.7 pooka 1419 1.49 pooka isrump = domain < PF_MAX && rumpsockets[domain]; 1420 1.1 pooka 1421 1.49 pooka if (isrump) 1422 1.49 pooka op_socket = GETSYSCALL(rump, SOCKET); 1423 1.49 pooka else 1424 1.17 pooka op_socket = GETSYSCALL(host, SOCKET); 1425 1.17 pooka fd = op_socket(domain, type, protocol); 1426 1.2 pooka 1427 1.49 pooka if (isrump) 1428 1.132 christos rfd = fd_rump2host(fd); 1429 1.47 pooka else 1430 1.132 christos rfd = fd_host2host(fd); 1431 1.132 christos DPRINTF(("socket <- %d/%d (%s)\n", fd, rfd, whichfd(rfd))); 1432 1.2 pooka 1433 1.132 christos return rfd; 1434 1.1 pooka } 1435 1.1 pooka 1436 1.1 pooka int 1437 1.1 pooka accept(int s, struct sockaddr *addr, socklen_t *addrlen) 1438 1.1 pooka { 1439 1.17 pooka int (*op_accept)(int, struct sockaddr *, socklen_t *); 1440 1.132 christos int fd, rfd; 1441 1.7 pooka bool isrump; 1442 1.7 pooka 1443 1.7 pooka isrump = fd_isrump(s); 1444 1.1 pooka 1445 1.2 pooka DPRINTF(("accept -> %d", s)); 1446 1.7 pooka if (isrump) { 1447 1.17 pooka op_accept = GETSYSCALL(rump, ACCEPT); 1448 1.7 pooka s = fd_host2rump(s); 1449 1.7 pooka } else { 1450 1.17 pooka op_accept = GETSYSCALL(host, ACCEPT); 1451 1.7 pooka } 1452 1.17 pooka fd = op_accept(s, addr, addrlen); 1453 1.7 pooka if (fd != -1 && isrump) 1454 1.132 christos rfd = fd_rump2host(fd); 1455 1.47 pooka else 1456 1.132 christos rfd = fd_host2host(fd); 1457 1.7 pooka 1458 1.132 christos DPRINTF((" <- %d/%d (%s)\n", fd, rfd, whichfd(rfd))); 1459 1.2 pooka 1460 1.132 christos return rfd; 1461 1.1 pooka } 1462 1.1 pooka 1463 1.127 bad #ifndef __linux__ 1464 1.122 ozaki int 1465 1.122 ozaki paccept(int s, struct sockaddr *addr, socklen_t *addrlen, 1466 1.122 ozaki const sigset_t * restrict sigmask, int flags) 1467 1.122 ozaki { 1468 1.122 ozaki int (*op_paccept)(int, struct sockaddr *, socklen_t *, 1469 1.122 ozaki const sigset_t * restrict, int); 1470 1.132 christos int fd, rfd; 1471 1.122 ozaki bool isrump; 1472 1.122 ozaki 1473 1.122 ozaki isrump = fd_isrump(s); 1474 1.122 ozaki 1475 1.122 ozaki DPRINTF(("paccept -> %d", s)); 1476 1.122 ozaki if (isrump) { 1477 1.122 ozaki op_paccept = GETSYSCALL(rump, PACCEPT); 1478 1.122 ozaki s = fd_host2rump(s); 1479 1.122 ozaki } else { 1480 1.122 ozaki op_paccept = GETSYSCALL(host, PACCEPT); 1481 1.122 ozaki } 1482 1.122 ozaki fd = op_paccept(s, addr, addrlen, sigmask, flags); 1483 1.122 ozaki if (fd != -1 && isrump) 1484 1.132 christos rfd = fd_rump2host(fd); 1485 1.122 ozaki else 1486 1.132 christos rfd = fd_host2host(fd); 1487 1.122 ozaki 1488 1.132 christos DPRINTF((" <- %d/%d (%s)\n", fd, rfd, whichfd(rfd))); 1489 1.122 ozaki 1490 1.132 christos return rfd; 1491 1.122 ozaki } 1492 1.127 bad #endif 1493 1.122 ozaki 1494 1.17 pooka /* 1495 1.103 pooka * ioctl() and fcntl() are varargs calls and need special treatment. 1496 1.103 pooka */ 1497 1.103 pooka 1498 1.103 pooka /* 1499 1.103 pooka * Various [Linux] libc's have various signatures for ioctl so we 1500 1.103 pooka * need to handle the discrepancies. On NetBSD, we use the 1501 1.103 pooka * one with unsigned long cmd. 1502 1.17 pooka */ 1503 1.1 pooka int 1504 1.103 pooka #ifdef HAVE_IOCTL_CMD_INT 1505 1.103 pooka ioctl(int fd, int cmd, ...) 1506 1.103 pooka { 1507 1.103 pooka int (*op_ioctl)(int, int cmd, ...); 1508 1.103 pooka #else 1509 1.17 pooka ioctl(int fd, unsigned long cmd, ...) 1510 1.1 pooka { 1511 1.17 pooka int (*op_ioctl)(int, unsigned long cmd, ...); 1512 1.103 pooka #endif 1513 1.17 pooka va_list ap; 1514 1.17 pooka int rv; 1515 1.1 pooka 1516 1.124 ozaki DPRINTF(("ioctl -> %d (%s)\n", fd, whichfd(fd))); 1517 1.17 pooka if (fd_isrump(fd)) { 1518 1.17 pooka fd = fd_host2rump(fd); 1519 1.17 pooka op_ioctl = GETSYSCALL(rump, IOCTL); 1520 1.7 pooka } else { 1521 1.17 pooka op_ioctl = GETSYSCALL(host, IOCTL); 1522 1.7 pooka } 1523 1.1 pooka 1524 1.17 pooka va_start(ap, cmd); 1525 1.17 pooka rv = op_ioctl(fd, cmd, va_arg(ap, void *)); 1526 1.17 pooka va_end(ap); 1527 1.124 ozaki DPRINTF(("ioctl <- %d\n", rv)); 1528 1.17 pooka return rv; 1529 1.1 pooka } 1530 1.1 pooka 1531 1.1 pooka int 1532 1.17 pooka fcntl(int fd, int cmd, ...) 1533 1.1 pooka { 1534 1.17 pooka int (*op_fcntl)(int, int, ...); 1535 1.17 pooka va_list ap; 1536 1.96 pooka int rv, minfd; 1537 1.40 pooka 1538 1.40 pooka DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd)); 1539 1.40 pooka 1540 1.40 pooka switch (cmd) { 1541 1.121 christos case F_DUPFD_CLOEXEC: /* Ignore CLOEXEC bit for now */ 1542 1.40 pooka case F_DUPFD: 1543 1.40 pooka va_start(ap, cmd); 1544 1.40 pooka minfd = va_arg(ap, int); 1545 1.40 pooka va_end(ap); 1546 1.40 pooka return dodup(fd, minfd); 1547 1.40 pooka 1548 1.96 pooka #ifdef F_CLOSEM 1549 1.96 pooka case F_CLOSEM: { 1550 1.96 pooka int maxdup2, i; 1551 1.96 pooka 1552 1.40 pooka /* 1553 1.40 pooka * So, if fd < HIJACKOFF, we want to do a host closem. 1554 1.40 pooka */ 1555 1.40 pooka 1556 1.85 pooka if (fd < hijack_fdoff) { 1557 1.40 pooka int closemfd = fd; 1558 1.1 pooka 1559 1.40 pooka if (rumpclient__closenotify(&closemfd, 1560 1.39 pooka RUMPCLIENT_CLOSE_FCLOSEM) == -1) 1561 1.39 pooka return -1; 1562 1.40 pooka op_fcntl = GETSYSCALL(host, FCNTL); 1563 1.40 pooka rv = op_fcntl(closemfd, cmd); 1564 1.40 pooka if (rv) 1565 1.40 pooka return rv; 1566 1.40 pooka } 1567 1.40 pooka 1568 1.40 pooka /* 1569 1.40 pooka * Additionally, we want to do a rump closem, but only 1570 1.71 pooka * for the file descriptors not dup2'd. 1571 1.40 pooka */ 1572 1.40 pooka 1573 1.110 pooka for (i = 0, maxdup2 = -1; i <= DUP2HIGH; i++) { 1574 1.72 pooka if (dup2vec[i] & DUP2BIT) { 1575 1.72 pooka int val; 1576 1.72 pooka 1577 1.72 pooka val = dup2vec[i] & DUP2FDMASK; 1578 1.72 pooka maxdup2 = MAX(val, maxdup2); 1579 1.72 pooka } 1580 1.40 pooka } 1581 1.40 pooka 1582 1.85 pooka if (fd >= hijack_fdoff) 1583 1.85 pooka fd -= hijack_fdoff; 1584 1.40 pooka else 1585 1.40 pooka fd = 0; 1586 1.71 pooka fd = MAX(maxdup2+1, fd); 1587 1.40 pooka 1588 1.40 pooka /* hmm, maybe we should close rump fd's not within dup2mask? */ 1589 1.40 pooka return rump_sys_fcntl(fd, F_CLOSEM); 1590 1.96 pooka } 1591 1.96 pooka #endif /* F_CLOSEM */ 1592 1.40 pooka 1593 1.96 pooka #ifdef F_MAXFD 1594 1.40 pooka case F_MAXFD: 1595 1.40 pooka /* 1596 1.40 pooka * For maxfd, if there's a rump kernel fd, return 1597 1.40 pooka * it hostified. Otherwise, return host's MAXFD 1598 1.40 pooka * return value. 1599 1.40 pooka */ 1600 1.40 pooka if ((rv = rump_sys_fcntl(fd, F_MAXFD)) != -1) { 1601 1.40 pooka /* 1602 1.40 pooka * This might go a little wrong in case 1603 1.40 pooka * of dup2 to [012], but I'm not sure if 1604 1.40 pooka * there's a justification for tracking 1605 1.40 pooka * that info. Consider e.g. 1606 1.40 pooka * dup2(rumpfd, 2) followed by rump_sys_open() 1607 1.40 pooka * returning 1. We should return 1+HIJACKOFF, 1608 1.40 pooka * not 2+HIJACKOFF. However, if [01] is not 1609 1.40 pooka * open, the correct return value is 2. 1610 1.40 pooka */ 1611 1.40 pooka return fd_rump2host(fd); 1612 1.40 pooka } else { 1613 1.40 pooka op_fcntl = GETSYSCALL(host, FCNTL); 1614 1.40 pooka return op_fcntl(fd, F_MAXFD); 1615 1.40 pooka } 1616 1.40 pooka /*NOTREACHED*/ 1617 1.96 pooka #endif /* F_MAXFD */ 1618 1.40 pooka 1619 1.40 pooka default: 1620 1.40 pooka if (fd_isrump(fd)) { 1621 1.40 pooka fd = fd_host2rump(fd); 1622 1.40 pooka op_fcntl = GETSYSCALL(rump, FCNTL); 1623 1.40 pooka } else { 1624 1.40 pooka op_fcntl = GETSYSCALL(host, FCNTL); 1625 1.40 pooka } 1626 1.40 pooka 1627 1.40 pooka va_start(ap, cmd); 1628 1.40 pooka rv = op_fcntl(fd, cmd, va_arg(ap, void *)); 1629 1.40 pooka va_end(ap); 1630 1.40 pooka return rv; 1631 1.7 pooka } 1632 1.40 pooka /*NOTREACHED*/ 1633 1.1 pooka } 1634 1.1 pooka 1635 1.39 pooka int 1636 1.140 ozaki flock(int fd, int operation) 1637 1.140 ozaki { 1638 1.140 ozaki int (*op_flock)(int, int); 1639 1.140 ozaki 1640 1.140 ozaki DPRINTF(("flock -> %d (operation %d)\n", fd, operation)); 1641 1.140 ozaki 1642 1.140 ozaki if (fd_isrump(fd)) { 1643 1.140 ozaki fd = fd_host2rump(fd); 1644 1.140 ozaki op_flock = GETSYSCALL(rump, FLOCK); 1645 1.140 ozaki } else { 1646 1.140 ozaki op_flock = GETSYSCALL(host, FLOCK); 1647 1.140 ozaki } 1648 1.140 ozaki 1649 1.140 ozaki return op_flock(fd, operation); 1650 1.140 ozaki } 1651 1.140 ozaki 1652 1.140 ozaki int 1653 1.39 pooka close(int fd) 1654 1.39 pooka { 1655 1.39 pooka int (*op_close)(int); 1656 1.39 pooka int rv; 1657 1.39 pooka 1658 1.39 pooka DPRINTF(("close -> %d\n", fd)); 1659 1.39 pooka if (fd_isrump(fd)) { 1660 1.71 pooka bool undup2 = false; 1661 1.71 pooka int ofd; 1662 1.71 pooka 1663 1.71 pooka if (isdup2d(ofd = fd)) { 1664 1.71 pooka undup2 = true; 1665 1.71 pooka } 1666 1.39 pooka 1667 1.47 pooka fd = fd_host2rump(fd); 1668 1.71 pooka if (!undup2 && killdup2alias(fd)) { 1669 1.47 pooka return 0; 1670 1.47 pooka } 1671 1.47 pooka 1672 1.39 pooka op_close = GETSYSCALL(rump, CLOSE); 1673 1.39 pooka rv = op_close(fd); 1674 1.71 pooka if (rv == 0 && undup2) { 1675 1.71 pooka clrdup2(ofd); 1676 1.71 pooka } 1677 1.39 pooka } else { 1678 1.39 pooka if (rumpclient__closenotify(&fd, RUMPCLIENT_CLOSE_CLOSE) == -1) 1679 1.39 pooka return -1; 1680 1.39 pooka op_close = GETSYSCALL(host, CLOSE); 1681 1.39 pooka rv = op_close(fd); 1682 1.39 pooka } 1683 1.39 pooka 1684 1.39 pooka return rv; 1685 1.39 pooka } 1686 1.39 pooka 1687 1.17 pooka /* 1688 1.17 pooka * write cannot issue a standard debug printf due to recursion 1689 1.17 pooka */ 1690 1.1 pooka ssize_t 1691 1.17 pooka write(int fd, const void *buf, size_t blen) 1692 1.1 pooka { 1693 1.17 pooka ssize_t (*op_write)(int, const void *, size_t); 1694 1.1 pooka 1695 1.17 pooka if (fd_isrump(fd)) { 1696 1.17 pooka fd = fd_host2rump(fd); 1697 1.17 pooka op_write = GETSYSCALL(rump, WRITE); 1698 1.16 pooka } else { 1699 1.17 pooka op_write = GETSYSCALL(host, WRITE); 1700 1.16 pooka } 1701 1.1 pooka 1702 1.17 pooka return op_write(fd, buf, blen); 1703 1.2 pooka } 1704 1.2 pooka 1705 1.2 pooka /* 1706 1.94 yamt * file descriptor passing 1707 1.94 yamt * 1708 1.94 yamt * we intercept sendmsg and recvmsg to convert file descriptors in 1709 1.94 yamt * control messages. an attempt to send a descriptor from a different kernel 1710 1.94 yamt * is rejected. (ENOTSUP) 1711 1.94 yamt */ 1712 1.94 yamt 1713 1.94 yamt static int 1714 1.125 ozaki _msg_convert_fds(struct msghdr *msg, int (*func)(int), bool dryrun) 1715 1.94 yamt { 1716 1.94 yamt struct cmsghdr *cmsg; 1717 1.94 yamt 1718 1.94 yamt for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; 1719 1.94 yamt cmsg = CMSG_NXTHDR(msg, cmsg)) { 1720 1.94 yamt if (cmsg->cmsg_level == SOL_SOCKET && 1721 1.94 yamt cmsg->cmsg_type == SCM_RIGHTS) { 1722 1.94 yamt int *fdp = (void *)CMSG_DATA(cmsg); 1723 1.94 yamt const size_t size = 1724 1.94 yamt cmsg->cmsg_len - __CMSG_ALIGN(sizeof(*cmsg)); 1725 1.99 martin const int nfds = (int)(size / sizeof(int)); 1726 1.94 yamt const int * const efdp = fdp + nfds; 1727 1.94 yamt 1728 1.94 yamt while (fdp < efdp) { 1729 1.94 yamt const int newval = func(*fdp); 1730 1.94 yamt 1731 1.94 yamt if (newval < 0) { 1732 1.94 yamt return ENOTSUP; 1733 1.94 yamt } 1734 1.125 ozaki if (!dryrun) 1735 1.125 ozaki *fdp = newval; 1736 1.94 yamt fdp++; 1737 1.94 yamt } 1738 1.94 yamt } 1739 1.94 yamt } 1740 1.94 yamt return 0; 1741 1.94 yamt } 1742 1.94 yamt 1743 1.125 ozaki static int 1744 1.125 ozaki msg_convert_fds(struct msghdr *msg, int (*func)(int)) 1745 1.125 ozaki { 1746 1.125 ozaki 1747 1.125 ozaki return _msg_convert_fds(msg, func, false); 1748 1.125 ozaki } 1749 1.125 ozaki 1750 1.125 ozaki static int 1751 1.125 ozaki msg_check_fds(struct msghdr *msg, int (*func)(int)) 1752 1.125 ozaki { 1753 1.125 ozaki 1754 1.125 ozaki return _msg_convert_fds(msg, func, true); 1755 1.125 ozaki } 1756 1.125 ozaki 1757 1.94 yamt ssize_t 1758 1.94 yamt recvmsg(int fd, struct msghdr *msg, int flags) 1759 1.94 yamt { 1760 1.94 yamt ssize_t (*op_recvmsg)(int, struct msghdr *, int); 1761 1.94 yamt ssize_t ret; 1762 1.94 yamt const bool isrump = fd_isrump(fd); 1763 1.132 christos 1764 1.132 christos DPRINTF(("%s -> %d (%s)\n", __func__, fd, whichfd(fd))); 1765 1.94 yamt if (isrump) { 1766 1.94 yamt fd = fd_host2rump(fd); 1767 1.94 yamt op_recvmsg = GETSYSCALL(rump, RECVMSG); 1768 1.94 yamt } else { 1769 1.94 yamt op_recvmsg = GETSYSCALL(host, RECVMSG); 1770 1.94 yamt } 1771 1.94 yamt ret = op_recvmsg(fd, msg, flags); 1772 1.94 yamt if (ret == -1) { 1773 1.94 yamt return ret; 1774 1.94 yamt } 1775 1.94 yamt /* 1776 1.94 yamt * convert descriptors in the message. 1777 1.94 yamt */ 1778 1.94 yamt if (isrump) { 1779 1.125 ozaki msg_convert_fds(msg, fd_rump2host); 1780 1.94 yamt } else { 1781 1.125 ozaki msg_convert_fds(msg, fd_host2host); 1782 1.94 yamt } 1783 1.94 yamt return ret; 1784 1.94 yamt } 1785 1.94 yamt 1786 1.97 pooka ssize_t 1787 1.97 pooka recv(int fd, void *buf, size_t len, int flags) 1788 1.97 pooka { 1789 1.97 pooka 1790 1.97 pooka return recvfrom(fd, buf, len, flags, NULL, NULL); 1791 1.97 pooka } 1792 1.97 pooka 1793 1.97 pooka ssize_t 1794 1.97 pooka send(int fd, const void *buf, size_t len, int flags) 1795 1.97 pooka { 1796 1.97 pooka 1797 1.97 pooka return sendto(fd, buf, len, flags, NULL, 0); 1798 1.97 pooka } 1799 1.97 pooka 1800 1.94 yamt static int 1801 1.94 yamt fd_check_rump(int fd) 1802 1.94 yamt { 1803 1.94 yamt 1804 1.94 yamt return fd_isrump(fd) ? 0 : -1; 1805 1.94 yamt } 1806 1.94 yamt 1807 1.94 yamt static int 1808 1.94 yamt fd_check_host(int fd) 1809 1.94 yamt { 1810 1.94 yamt 1811 1.94 yamt return !fd_isrump(fd) ? 0 : -1; 1812 1.94 yamt } 1813 1.94 yamt 1814 1.94 yamt ssize_t 1815 1.94 yamt sendmsg(int fd, const struct msghdr *msg, int flags) 1816 1.94 yamt { 1817 1.94 yamt ssize_t (*op_sendmsg)(int, const struct msghdr *, int); 1818 1.94 yamt const bool isrump = fd_isrump(fd); 1819 1.94 yamt int error; 1820 1.94 yamt 1821 1.132 christos DPRINTF(("%s -> %d (%s)\n", __func__, fd, whichfd(fd))); 1822 1.94 yamt /* 1823 1.94 yamt * reject descriptors from a different kernel. 1824 1.94 yamt */ 1825 1.125 ozaki error = msg_check_fds(__UNCONST(msg), 1826 1.94 yamt isrump ? fd_check_rump: fd_check_host); 1827 1.94 yamt if (error != 0) { 1828 1.94 yamt errno = error; 1829 1.94 yamt return -1; 1830 1.94 yamt } 1831 1.94 yamt /* 1832 1.94 yamt * convert descriptors in the message to raw values. 1833 1.94 yamt */ 1834 1.94 yamt if (isrump) { 1835 1.94 yamt fd = fd_host2rump(fd); 1836 1.94 yamt /* 1837 1.94 yamt * XXX we directly modify the given message assuming: 1838 1.94 yamt * - cmsg is writable (typically on caller's stack) 1839 1.94 yamt * - caller don't care cmsg's contents after calling sendmsg. 1840 1.94 yamt * (thus no need to restore values) 1841 1.94 yamt * 1842 1.94 yamt * it's safer to copy and modify instead. 1843 1.94 yamt */ 1844 1.125 ozaki msg_convert_fds(__UNCONST(msg), fd_host2rump); 1845 1.94 yamt op_sendmsg = GETSYSCALL(rump, SENDMSG); 1846 1.94 yamt } else { 1847 1.94 yamt op_sendmsg = GETSYSCALL(host, SENDMSG); 1848 1.94 yamt } 1849 1.94 yamt return op_sendmsg(fd, msg, flags); 1850 1.94 yamt } 1851 1.94 yamt 1852 1.94 yamt /* 1853 1.2 pooka * dup2 is special. we allow dup2 of a rump kernel fd to 0-2 since 1854 1.2 pooka * many programs do that. dup2 of a rump kernel fd to another value 1855 1.2 pooka * not >= fdoff is an error. 1856 1.2 pooka * 1857 1.2 pooka * Note: cannot rump2host newd, because it is often hardcoded. 1858 1.2 pooka */ 1859 1.2 pooka int 1860 1.2 pooka dup2(int oldd, int newd) 1861 1.2 pooka { 1862 1.17 pooka int (*host_dup2)(int, int); 1863 1.2 pooka int rv; 1864 1.2 pooka 1865 1.2 pooka DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd)); 1866 1.2 pooka 1867 1.2 pooka if (fd_isrump(oldd)) { 1868 1.71 pooka int (*op_close)(int) = GETSYSCALL(host, CLOSE); 1869 1.71 pooka 1870 1.71 pooka /* only allow fd 0-2 for cross-kernel dup */ 1871 1.71 pooka if (!(newd >= 0 && newd <= 2 && !fd_isrump(newd))) { 1872 1.66 pooka errno = EBADF; 1873 1.66 pooka return -1; 1874 1.66 pooka } 1875 1.71 pooka 1876 1.71 pooka /* regular dup2? */ 1877 1.71 pooka if (fd_isrump(newd)) { 1878 1.71 pooka newd = fd_host2rump(newd); 1879 1.71 pooka rv = rump_sys_dup2(oldd, newd); 1880 1.71 pooka return fd_rump2host(rv); 1881 1.71 pooka } 1882 1.71 pooka 1883 1.71 pooka /* 1884 1.71 pooka * dup2 rump => host? just establish an 1885 1.71 pooka * entry in the mapping table. 1886 1.71 pooka */ 1887 1.71 pooka op_close(newd); 1888 1.71 pooka setdup2(newd, fd_host2rump(oldd)); 1889 1.141 kre rv = newd; 1890 1.2 pooka } else { 1891 1.17 pooka host_dup2 = syscalls[DUALCALL_DUP2].bs_host; 1892 1.39 pooka if (rumpclient__closenotify(&newd, RUMPCLIENT_CLOSE_DUP2) == -1) 1893 1.39 pooka return -1; 1894 1.10 pooka rv = host_dup2(oldd, newd); 1895 1.2 pooka } 1896 1.10 pooka 1897 1.10 pooka return rv; 1898 1.2 pooka } 1899 1.2 pooka 1900 1.34 pooka int 1901 1.34 pooka dup(int oldd) 1902 1.34 pooka { 1903 1.34 pooka 1904 1.40 pooka return dodup(oldd, 0); 1905 1.34 pooka } 1906 1.34 pooka 1907 1.2 pooka pid_t 1908 1.93 abs fork(void) 1909 1.2 pooka { 1910 1.2 pooka pid_t rv; 1911 1.2 pooka 1912 1.2 pooka DPRINTF(("fork\n")); 1913 1.2 pooka 1914 1.43 pooka rv = rumpclient__dofork(host_fork); 1915 1.2 pooka 1916 1.2 pooka DPRINTF(("fork returns %d\n", rv)); 1917 1.2 pooka return rv; 1918 1.1 pooka } 1919 1.96 pooka #ifdef VFORK 1920 1.43 pooka /* we do not have the luxury of not requiring a stackframe */ 1921 1.117 riastrad #define __strong_alias_macro(m, f) __strong_alias(m, f) 1922 1.132 christos __strong_alias_macro(VFORK,fork) 1923 1.96 pooka #endif 1924 1.1 pooka 1925 1.25 pooka int 1926 1.25 pooka daemon(int nochdir, int noclose) 1927 1.25 pooka { 1928 1.25 pooka struct rumpclient_fork *rf; 1929 1.25 pooka 1930 1.25 pooka if ((rf = rumpclient_prefork()) == NULL) 1931 1.25 pooka return -1; 1932 1.25 pooka 1933 1.25 pooka if (host_daemon(nochdir, noclose) == -1) 1934 1.25 pooka return -1; 1935 1.25 pooka 1936 1.25 pooka if (rumpclient_fork_init(rf) == -1) 1937 1.25 pooka return -1; 1938 1.25 pooka 1939 1.25 pooka return 0; 1940 1.25 pooka } 1941 1.25 pooka 1942 1.39 pooka int 1943 1.42 pooka execve(const char *path, char *const argv[], char *const envp[]) 1944 1.39 pooka { 1945 1.39 pooka char buf[128]; 1946 1.39 pooka char *dup2str; 1947 1.49 pooka const char *pwdinrumpstr; 1948 1.42 pooka char **newenv; 1949 1.42 pooka size_t nelem; 1950 1.42 pooka int rv, sverrno; 1951 1.71 pooka int bonus = 2, i = 0; 1952 1.45 pooka 1953 1.71 pooka snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2INFO=%u,%u,%u", 1954 1.71 pooka dup2vec[0], dup2vec[1], dup2vec[2]); 1955 1.71 pooka dup2str = strdup(buf); 1956 1.71 pooka if (dup2str == NULL) { 1957 1.71 pooka errno = ENOMEM; 1958 1.71 pooka return -1; 1959 1.45 pooka } 1960 1.39 pooka 1961 1.45 pooka if (pwdinrump) { 1962 1.49 pooka pwdinrumpstr = "RUMPHIJACK__PWDINRUMP=true"; 1963 1.45 pooka bonus++; 1964 1.45 pooka } else { 1965 1.45 pooka pwdinrumpstr = NULL; 1966 1.45 pooka } 1967 1.39 pooka 1968 1.42 pooka for (nelem = 0; envp && envp[nelem]; nelem++) 1969 1.42 pooka continue; 1970 1.71 pooka newenv = malloc(sizeof(*newenv) * (nelem+bonus)); 1971 1.42 pooka if (newenv == NULL) { 1972 1.39 pooka free(dup2str); 1973 1.66 pooka errno = ENOMEM; 1974 1.66 pooka return -1; 1975 1.39 pooka } 1976 1.42 pooka memcpy(newenv, envp, nelem*sizeof(*newenv)); 1977 1.71 pooka newenv[nelem+i] = dup2str; 1978 1.71 pooka i++; 1979 1.71 pooka 1980 1.45 pooka if (pwdinrumpstr) { 1981 1.49 pooka newenv[nelem+i] = __UNCONST(pwdinrumpstr); 1982 1.45 pooka i++; 1983 1.45 pooka } 1984 1.45 pooka newenv[nelem+i] = NULL; 1985 1.45 pooka _DIAGASSERT(i < bonus); 1986 1.42 pooka 1987 1.42 pooka rv = rumpclient_exec(path, argv, newenv); 1988 1.42 pooka 1989 1.42 pooka _DIAGASSERT(rv != 0); 1990 1.42 pooka sverrno = errno; 1991 1.42 pooka free(newenv); 1992 1.42 pooka free(dup2str); 1993 1.42 pooka errno = sverrno; 1994 1.39 pooka return rv; 1995 1.39 pooka } 1996 1.39 pooka 1997 1.1 pooka /* 1998 1.17 pooka * select is done by calling poll. 1999 1.1 pooka */ 2000 1.1 pooka int 2001 1.132 christos REALPSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 2002 1.132 christos const struct timespec *timeout, const sigset_t *sigmask) 2003 1.1 pooka { 2004 1.4 pooka struct pollfd *pfds; 2005 1.19 pooka nfds_t realnfds; 2006 1.19 pooka int i, j; 2007 1.4 pooka int rv, incr; 2008 1.4 pooka 2009 1.132 christos DPRINTF(("pselect %d %p %p %p %p %p\n", nfds, 2010 1.132 christos readfds, writefds, exceptfds, timeout, sigmask)); 2011 1.7 pooka 2012 1.4 pooka /* 2013 1.4 pooka * Well, first we must scan the fds to figure out how many 2014 1.4 pooka * fds there really are. This is because up to and including 2015 1.17 pooka * nb5 poll() silently refuses nfds > process_maxopen_fds. 2016 1.4 pooka * Seems to be fixed in current, thank the maker. 2017 1.4 pooka * god damn cluster...bomb. 2018 1.4 pooka */ 2019 1.4 pooka 2020 1.4 pooka for (i = 0, realnfds = 0; i < nfds; i++) { 2021 1.4 pooka if (readfds && FD_ISSET(i, readfds)) { 2022 1.4 pooka realnfds++; 2023 1.4 pooka continue; 2024 1.4 pooka } 2025 1.4 pooka if (writefds && FD_ISSET(i, writefds)) { 2026 1.4 pooka realnfds++; 2027 1.4 pooka continue; 2028 1.4 pooka } 2029 1.4 pooka if (exceptfds && FD_ISSET(i, exceptfds)) { 2030 1.4 pooka realnfds++; 2031 1.4 pooka continue; 2032 1.1 pooka } 2033 1.1 pooka } 2034 1.1 pooka 2035 1.6 pooka if (realnfds) { 2036 1.38 pooka pfds = calloc(realnfds, sizeof(*pfds)); 2037 1.6 pooka if (!pfds) 2038 1.6 pooka return -1; 2039 1.6 pooka } else { 2040 1.6 pooka pfds = NULL; 2041 1.6 pooka } 2042 1.1 pooka 2043 1.4 pooka for (i = 0, j = 0; i < nfds; i++) { 2044 1.4 pooka incr = 0; 2045 1.4 pooka if (readfds && FD_ISSET(i, readfds)) { 2046 1.4 pooka pfds[j].fd = i; 2047 1.4 pooka pfds[j].events |= POLLIN; 2048 1.4 pooka incr=1; 2049 1.4 pooka } 2050 1.4 pooka if (writefds && FD_ISSET(i, writefds)) { 2051 1.4 pooka pfds[j].fd = i; 2052 1.4 pooka pfds[j].events |= POLLOUT; 2053 1.4 pooka incr=1; 2054 1.4 pooka } 2055 1.4 pooka if (exceptfds && FD_ISSET(i, exceptfds)) { 2056 1.4 pooka pfds[j].fd = i; 2057 1.4 pooka pfds[j].events |= POLLHUP|POLLERR; 2058 1.4 pooka incr=1; 2059 1.1 pooka } 2060 1.4 pooka if (incr) 2061 1.4 pooka j++; 2062 1.1 pooka } 2063 1.37 pooka assert(j == (int)realnfds); 2064 1.1 pooka 2065 1.132 christos rv = REALPOLLTS(pfds, realnfds, timeout, sigmask); 2066 1.36 pooka /* 2067 1.36 pooka * "If select() returns with an error the descriptor sets 2068 1.36 pooka * will be unmodified" 2069 1.36 pooka */ 2070 1.36 pooka if (rv < 0) 2071 1.4 pooka goto out; 2072 1.4 pooka 2073 1.4 pooka /* 2074 1.36 pooka * zero out results (can't use FD_ZERO for the 2075 1.36 pooka * obvious select-me-not reason). whee. 2076 1.36 pooka * 2077 1.36 pooka * We do this here since some software ignores the return 2078 1.36 pooka * value of select, and hence if the timeout expires, it may 2079 1.36 pooka * assume all input descriptors have activity. 2080 1.4 pooka */ 2081 1.4 pooka for (i = 0; i < nfds; i++) { 2082 1.4 pooka if (readfds) 2083 1.4 pooka FD_CLR(i, readfds); 2084 1.4 pooka if (writefds) 2085 1.4 pooka FD_CLR(i, writefds); 2086 1.4 pooka if (exceptfds) 2087 1.4 pooka FD_CLR(i, exceptfds); 2088 1.1 pooka } 2089 1.36 pooka if (rv == 0) 2090 1.36 pooka goto out; 2091 1.1 pooka 2092 1.36 pooka /* 2093 1.36 pooka * We have >0 fds with activity. Harvest the results. 2094 1.36 pooka */ 2095 1.19 pooka for (i = 0; i < (int)realnfds; i++) { 2096 1.4 pooka if (readfds) { 2097 1.4 pooka if (pfds[i].revents & POLLIN) { 2098 1.4 pooka FD_SET(pfds[i].fd, readfds); 2099 1.4 pooka } 2100 1.4 pooka } 2101 1.4 pooka if (writefds) { 2102 1.4 pooka if (pfds[i].revents & POLLOUT) { 2103 1.4 pooka FD_SET(pfds[i].fd, writefds); 2104 1.4 pooka } 2105 1.4 pooka } 2106 1.4 pooka if (exceptfds) { 2107 1.4 pooka if (pfds[i].revents & (POLLHUP|POLLERR)) { 2108 1.4 pooka FD_SET(pfds[i].fd, exceptfds); 2109 1.4 pooka } 2110 1.4 pooka } 2111 1.1 pooka } 2112 1.1 pooka 2113 1.4 pooka out: 2114 1.4 pooka free(pfds); 2115 1.1 pooka return rv; 2116 1.1 pooka } 2117 1.1 pooka 2118 1.132 christos int 2119 1.132 christos REALSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 2120 1.132 christos struct timeval *timeout) 2121 1.132 christos { 2122 1.132 christos struct timespec ts, *tsp = NULL; 2123 1.132 christos if (timeout) { 2124 1.132 christos TIMEVAL_TO_TIMESPEC(timeout, &ts); 2125 1.132 christos tsp = &ts; 2126 1.132 christos } 2127 1.132 christos return REALPSELECT(nfds, readfds, writefds, exceptfds, tsp, NULL); 2128 1.132 christos } 2129 1.132 christos 2130 1.132 christos 2131 1.1 pooka static void 2132 1.1 pooka checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall) 2133 1.1 pooka { 2134 1.1 pooka nfds_t i; 2135 1.1 pooka 2136 1.1 pooka for (i = 0; i < nfds; i++) { 2137 1.12 pooka if (fds[i].fd == -1) 2138 1.12 pooka continue; 2139 1.12 pooka 2140 1.2 pooka if (fd_isrump(fds[i].fd)) 2141 1.2 pooka (*rumpcall)++; 2142 1.2 pooka else 2143 1.1 pooka (*hostcall)++; 2144 1.1 pooka } 2145 1.1 pooka } 2146 1.1 pooka 2147 1.1 pooka static void 2148 1.2 pooka adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int)) 2149 1.1 pooka { 2150 1.1 pooka nfds_t i; 2151 1.1 pooka 2152 1.1 pooka for (i = 0; i < nfds; i++) { 2153 1.2 pooka fds[i].fd = fdadj(fds[i].fd); 2154 1.1 pooka } 2155 1.1 pooka } 2156 1.1 pooka 2157 1.1 pooka /* 2158 1.1 pooka * poll is easy as long as the call comes in the fds only in one 2159 1.1 pooka * kernel. otherwise its quite tricky... 2160 1.1 pooka */ 2161 1.1 pooka struct pollarg { 2162 1.1 pooka struct pollfd *pfds; 2163 1.1 pooka nfds_t nfds; 2164 1.3 pooka const struct timespec *ts; 2165 1.3 pooka const sigset_t *sigmask; 2166 1.1 pooka int pipefd; 2167 1.1 pooka int errnum; 2168 1.1 pooka }; 2169 1.1 pooka 2170 1.1 pooka static void * 2171 1.1 pooka hostpoll(void *arg) 2172 1.1 pooka { 2173 1.17 pooka int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *, 2174 1.17 pooka const sigset_t *); 2175 1.1 pooka struct pollarg *parg = arg; 2176 1.1 pooka intptr_t rv; 2177 1.1 pooka 2178 1.35 pooka op_pollts = GETSYSCALL(host, POLLTS); 2179 1.17 pooka rv = op_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask); 2180 1.1 pooka if (rv == -1) 2181 1.1 pooka parg->errnum = errno; 2182 1.1 pooka rump_sys_write(parg->pipefd, &rv, sizeof(rv)); 2183 1.1 pooka 2184 1.92 martin return (void *)rv; 2185 1.1 pooka } 2186 1.1 pooka 2187 1.1 pooka int 2188 1.29 pooka REALPOLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts, 2189 1.3 pooka const sigset_t *sigmask) 2190 1.1 pooka { 2191 1.3 pooka int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *, 2192 1.3 pooka const sigset_t *); 2193 1.17 pooka int (*host_close)(int); 2194 1.1 pooka int hostcall = 0, rumpcall = 0; 2195 1.1 pooka pthread_t pt; 2196 1.1 pooka nfds_t i; 2197 1.1 pooka int rv; 2198 1.1 pooka 2199 1.100 pooka DPRINTF(("poll %p %d %p %p\n", fds, (int)nfds, ts, sigmask)); 2200 1.1 pooka checkpoll(fds, nfds, &hostcall, &rumpcall); 2201 1.1 pooka 2202 1.1 pooka if (hostcall && rumpcall) { 2203 1.1 pooka struct pollfd *pfd_host = NULL, *pfd_rump = NULL; 2204 1.1 pooka int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1}; 2205 1.1 pooka struct pollarg parg; 2206 1.92 martin void *trv_val; 2207 1.99 martin int sverrno = 0, rv_rump, rv_host, errno_rump, errno_host; 2208 1.1 pooka 2209 1.1 pooka /* 2210 1.1 pooka * ok, this is where it gets tricky. We must support 2211 1.1 pooka * this since it's a very common operation in certain 2212 1.1 pooka * types of software (telnet, netcat, etc). We allocate 2213 1.1 pooka * two vectors and run two poll commands in separate 2214 1.1 pooka * threads. Whichever returns first "wins" and the 2215 1.1 pooka * other kernel's fds won't show activity. 2216 1.1 pooka */ 2217 1.1 pooka rv = -1; 2218 1.1 pooka 2219 1.1 pooka /* allocate full vector for O(n) joining after call */ 2220 1.1 pooka pfd_host = malloc(sizeof(*pfd_host)*(nfds+1)); 2221 1.1 pooka if (!pfd_host) 2222 1.1 pooka goto out; 2223 1.1 pooka pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1)); 2224 1.1 pooka if (!pfd_rump) { 2225 1.1 pooka goto out; 2226 1.1 pooka } 2227 1.1 pooka 2228 1.59 pooka /* 2229 1.59 pooka * then, open two pipes, one for notifications 2230 1.59 pooka * to each kernel. 2231 1.73 pooka * 2232 1.73 pooka * At least the rump pipe should probably be 2233 1.73 pooka * cached, along with the helper threads. This 2234 1.73 pooka * should give a microbenchmark improvement (haven't 2235 1.73 pooka * experienced a macro-level problem yet, though). 2236 1.59 pooka */ 2237 1.59 pooka if ((rv = rump_sys_pipe(rpipe)) == -1) { 2238 1.59 pooka sverrno = errno; 2239 1.59 pooka } 2240 1.59 pooka if (rv == 0 && (rv = pipe(hpipe)) == -1) { 2241 1.59 pooka sverrno = errno; 2242 1.59 pooka } 2243 1.59 pooka 2244 1.59 pooka /* split vectors (or signal errors) */ 2245 1.1 pooka for (i = 0; i < nfds; i++) { 2246 1.59 pooka int fd; 2247 1.59 pooka 2248 1.59 pooka fds[i].revents = 0; 2249 1.3 pooka if (fds[i].fd == -1) { 2250 1.3 pooka pfd_host[i].fd = -1; 2251 1.3 pooka pfd_rump[i].fd = -1; 2252 1.3 pooka } else if (fd_isrump(fds[i].fd)) { 2253 1.2 pooka pfd_host[i].fd = -1; 2254 1.59 pooka fd = fd_host2rump(fds[i].fd); 2255 1.59 pooka if (fd == rpipe[0] || fd == rpipe[1]) { 2256 1.59 pooka fds[i].revents = POLLNVAL; 2257 1.59 pooka if (rv != -1) 2258 1.59 pooka rv++; 2259 1.59 pooka } 2260 1.59 pooka pfd_rump[i].fd = fd; 2261 1.2 pooka pfd_rump[i].events = fds[i].events; 2262 1.2 pooka } else { 2263 1.2 pooka pfd_rump[i].fd = -1; 2264 1.59 pooka fd = fds[i].fd; 2265 1.59 pooka if (fd == hpipe[0] || fd == hpipe[1]) { 2266 1.59 pooka fds[i].revents = POLLNVAL; 2267 1.59 pooka if (rv != -1) 2268 1.59 pooka rv++; 2269 1.59 pooka } 2270 1.59 pooka pfd_host[i].fd = fd; 2271 1.1 pooka pfd_host[i].events = fds[i].events; 2272 1.1 pooka } 2273 1.39 pooka pfd_rump[i].revents = pfd_host[i].revents = 0; 2274 1.1 pooka } 2275 1.59 pooka if (rv) { 2276 1.1 pooka goto out; 2277 1.59 pooka } 2278 1.1 pooka 2279 1.1 pooka pfd_host[nfds].fd = hpipe[0]; 2280 1.1 pooka pfd_host[nfds].events = POLLIN; 2281 1.1 pooka pfd_rump[nfds].fd = rpipe[0]; 2282 1.1 pooka pfd_rump[nfds].events = POLLIN; 2283 1.1 pooka 2284 1.1 pooka /* 2285 1.1 pooka * then, create a thread to do host part and meanwhile 2286 1.1 pooka * do rump kernel part right here 2287 1.1 pooka */ 2288 1.1 pooka 2289 1.1 pooka parg.pfds = pfd_host; 2290 1.1 pooka parg.nfds = nfds+1; 2291 1.3 pooka parg.ts = ts; 2292 1.3 pooka parg.sigmask = sigmask; 2293 1.1 pooka parg.pipefd = rpipe[1]; 2294 1.1 pooka pthread_create(&pt, NULL, hostpoll, &parg); 2295 1.1 pooka 2296 1.35 pooka op_pollts = GETSYSCALL(rump, POLLTS); 2297 1.99 martin rv_rump = op_pollts(pfd_rump, nfds+1, ts, NULL); 2298 1.99 martin errno_rump = errno; 2299 1.1 pooka write(hpipe[1], &rv, sizeof(rv)); 2300 1.92 martin pthread_join(pt, &trv_val); 2301 1.99 martin rv_host = (int)(intptr_t)trv_val; 2302 1.99 martin errno_host = parg.errnum; 2303 1.1 pooka 2304 1.99 martin /* strip cross-thread notification from real results */ 2305 1.109 gson if (rv_host > 0 && pfd_host[nfds].revents & POLLIN) { 2306 1.99 martin rv_host--; 2307 1.99 martin } 2308 1.109 gson if (rv_rump > 0 && pfd_rump[nfds].revents & POLLIN) { 2309 1.99 martin rv_rump--; 2310 1.99 martin } 2311 1.99 martin 2312 1.99 martin /* then merge the results into what's reported to the caller */ 2313 1.99 martin if (rv_rump > 0 || rv_host > 0) { 2314 1.99 martin /* SUCCESS */ 2315 1.99 martin 2316 1.99 martin rv = 0; 2317 1.99 martin if (rv_rump > 0) { 2318 1.99 martin for (i = 0; i < nfds; i++) { 2319 1.99 martin if (pfd_rump[i].fd != -1) 2320 1.99 martin fds[i].revents 2321 1.99 martin = pfd_rump[i].revents; 2322 1.99 martin } 2323 1.99 martin rv += rv_rump; 2324 1.1 pooka } 2325 1.99 martin if (rv_host > 0) { 2326 1.99 martin for (i = 0; i < nfds; i++) { 2327 1.99 martin if (pfd_host[i].fd != -1) 2328 1.99 martin fds[i].revents 2329 1.99 martin = pfd_host[i].revents; 2330 1.99 martin } 2331 1.99 martin rv += rv_host; 2332 1.99 martin } 2333 1.99 martin assert(rv > 0); 2334 1.99 martin sverrno = 0; 2335 1.99 martin } else if (rv_rump == -1 || rv_host == -1) { 2336 1.99 martin /* ERROR */ 2337 1.99 martin 2338 1.99 martin /* just pick one kernel at "random" */ 2339 1.99 martin rv = -1; 2340 1.99 martin if (rv_host == -1) { 2341 1.99 martin sverrno = errno_host; 2342 1.99 martin } else if (rv_rump == -1) { 2343 1.99 martin sverrno = errno_rump; 2344 1.1 pooka } 2345 1.1 pooka } else { 2346 1.99 martin /* TIMEOUT */ 2347 1.99 martin 2348 1.1 pooka rv = 0; 2349 1.99 martin assert(rv_rump == 0 && rv_host == 0); 2350 1.1 pooka } 2351 1.1 pooka 2352 1.1 pooka out: 2353 1.35 pooka host_close = GETSYSCALL(host, CLOSE); 2354 1.1 pooka if (rpipe[0] != -1) 2355 1.1 pooka rump_sys_close(rpipe[0]); 2356 1.1 pooka if (rpipe[1] != -1) 2357 1.1 pooka rump_sys_close(rpipe[1]); 2358 1.1 pooka if (hpipe[0] != -1) 2359 1.9 pooka host_close(hpipe[0]); 2360 1.1 pooka if (hpipe[1] != -1) 2361 1.9 pooka host_close(hpipe[1]); 2362 1.1 pooka free(pfd_host); 2363 1.1 pooka free(pfd_rump); 2364 1.1 pooka errno = sverrno; 2365 1.1 pooka } else { 2366 1.1 pooka if (hostcall) { 2367 1.35 pooka op_pollts = GETSYSCALL(host, POLLTS); 2368 1.1 pooka } else { 2369 1.35 pooka op_pollts = GETSYSCALL(rump, POLLTS); 2370 1.2 pooka adjustpoll(fds, nfds, fd_host2rump); 2371 1.1 pooka } 2372 1.1 pooka 2373 1.3 pooka rv = op_pollts(fds, nfds, ts, sigmask); 2374 1.1 pooka if (rumpcall) 2375 1.71 pooka adjustpoll(fds, nfds, fd_rump2host_withdup); 2376 1.1 pooka } 2377 1.1 pooka 2378 1.1 pooka return rv; 2379 1.1 pooka } 2380 1.1 pooka 2381 1.1 pooka int 2382 1.24 pooka poll(struct pollfd *fds, nfds_t nfds, int timeout) 2383 1.1 pooka { 2384 1.3 pooka struct timespec ts; 2385 1.3 pooka struct timespec *tsp = NULL; 2386 1.3 pooka 2387 1.3 pooka if (timeout != INFTIM) { 2388 1.3 pooka ts.tv_sec = timeout / 1000; 2389 1.11 pooka ts.tv_nsec = (timeout % 1000) * 1000*1000; 2390 1.3 pooka 2391 1.3 pooka tsp = &ts; 2392 1.3 pooka } 2393 1.1 pooka 2394 1.29 pooka return REALPOLLTS(fds, nfds, tsp, NULL); 2395 1.1 pooka } 2396 1.10 pooka 2397 1.111 pooka #ifdef HAVE_KQUEUE 2398 1.10 pooka int 2399 1.34 pooka REALKEVENT(int kq, const struct kevent *changelist, size_t nchanges, 2400 1.34 pooka struct kevent *eventlist, size_t nevents, 2401 1.34 pooka const struct timespec *timeout) 2402 1.10 pooka { 2403 1.34 pooka int (*op_kevent)(int, const struct kevent *, size_t, 2404 1.34 pooka struct kevent *, size_t, const struct timespec *); 2405 1.34 pooka const struct kevent *ev; 2406 1.34 pooka size_t i; 2407 1.10 pooka 2408 1.34 pooka /* 2409 1.34 pooka * Check that we don't attempt to kevent rump kernel fd's. 2410 1.34 pooka * That needs similar treatment to select/poll, but is slightly 2411 1.34 pooka * trickier since we need to manage to different kq descriptors. 2412 1.34 pooka * (TODO, in case you're wondering). 2413 1.34 pooka */ 2414 1.34 pooka for (i = 0; i < nchanges; i++) { 2415 1.34 pooka ev = &changelist[i]; 2416 1.34 pooka if (ev->filter == EVFILT_READ || ev->filter == EVFILT_WRITE || 2417 1.34 pooka ev->filter == EVFILT_VNODE) { 2418 1.66 pooka if (fd_isrump((int)ev->ident)) { 2419 1.66 pooka errno = ENOTSUP; 2420 1.66 pooka return -1; 2421 1.66 pooka } 2422 1.34 pooka } 2423 1.27 pooka } 2424 1.10 pooka 2425 1.35 pooka op_kevent = GETSYSCALL(host, KEVENT); 2426 1.34 pooka return op_kevent(kq, changelist, nchanges, eventlist, nevents, timeout); 2427 1.10 pooka } 2428 1.111 pooka #endif /* HAVE_KQUEUE */ 2429 1.17 pooka 2430 1.17 pooka /* 2431 1.62 pooka * mmapping from a rump kernel is not supported, so disallow it. 2432 1.62 pooka */ 2433 1.62 pooka void * 2434 1.62 pooka mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset) 2435 1.62 pooka { 2436 1.62 pooka 2437 1.62 pooka if (flags & MAP_FILE && fd_isrump(fd)) { 2438 1.62 pooka errno = ENOSYS; 2439 1.62 pooka return MAP_FAILED; 2440 1.62 pooka } 2441 1.118 pooka if (__predict_false(host_mmap == NULL)) { 2442 1.119 pooka host_mmap = rumphijack_dlsym(RTLD_NEXT, "mmap"); 2443 1.118 pooka } 2444 1.62 pooka return host_mmap(addr, len, prot, flags, fd, offset); 2445 1.62 pooka } 2446 1.62 pooka 2447 1.111 pooka #ifdef __NetBSD__ 2448 1.62 pooka /* 2449 1.78 pooka * these go to one or the other on a per-process configuration 2450 1.78 pooka */ 2451 1.78 pooka int __sysctl(const int *, unsigned int, void *, size_t *, const void *, size_t); 2452 1.78 pooka int 2453 1.78 pooka __sysctl(const int *name, unsigned int namelen, void *old, size_t *oldlenp, 2454 1.78 pooka const void *new, size_t newlen) 2455 1.78 pooka { 2456 1.78 pooka int (*op___sysctl)(const int *, unsigned int, void *, size_t *, 2457 1.78 pooka const void *, size_t); 2458 1.78 pooka 2459 1.78 pooka if (rumpsysctl) { 2460 1.78 pooka op___sysctl = GETSYSCALL(rump, __SYSCTL); 2461 1.78 pooka } else { 2462 1.78 pooka op___sysctl = GETSYSCALL(host, __SYSCTL); 2463 1.78 pooka /* we haven't inited yet */ 2464 1.78 pooka if (__predict_false(op___sysctl == NULL)) { 2465 1.84 pooka op___sysctl = rumphijack_dlsym(RTLD_NEXT, "__sysctl"); 2466 1.78 pooka } 2467 1.78 pooka } 2468 1.78 pooka 2469 1.78 pooka return op___sysctl(name, namelen, old, oldlenp, new, newlen); 2470 1.78 pooka } 2471 1.126 hannken int modctl(int, void *); 2472 1.126 hannken int 2473 1.126 hannken modctl(int operation, void *argp) 2474 1.126 hannken { 2475 1.126 hannken int (*op_modctl)(int operation, void *argp); 2476 1.126 hannken 2477 1.126 hannken if (rumpmodctl) { 2478 1.126 hannken op_modctl = GETSYSCALL(rump, MODCTL); 2479 1.126 hannken } else { 2480 1.126 hannken op_modctl = GETSYSCALL(host, MODCTL); 2481 1.126 hannken } 2482 1.126 hannken 2483 1.126 hannken return op_modctl(operation, argp); 2484 1.126 hannken } 2485 1.96 pooka #endif 2486 1.78 pooka 2487 1.78 pooka /* 2488 1.17 pooka * Rest are std type calls. 2489 1.17 pooka */ 2490 1.17 pooka 2491 1.116 pooka #ifdef HAVE_UTIMENSAT 2492 1.114 pooka ATCALL(int, utimensat, DUALCALL_UTIMENSAT, \ 2493 1.114 pooka (int fd, const char *path, const struct timespec t[2], int f), \ 2494 1.114 pooka (int, const char *, const struct timespec [2], int), 2495 1.114 pooka (fd, path, t, f)) 2496 1.116 pooka #endif 2497 1.114 pooka 2498 1.17 pooka FDCALL(int, bind, DUALCALL_BIND, \ 2499 1.17 pooka (int fd, const struct sockaddr *name, socklen_t namelen), \ 2500 1.17 pooka (int, const struct sockaddr *, socklen_t), \ 2501 1.17 pooka (fd, name, namelen)) 2502 1.17 pooka 2503 1.17 pooka FDCALL(int, connect, DUALCALL_CONNECT, \ 2504 1.17 pooka (int fd, const struct sockaddr *name, socklen_t namelen), \ 2505 1.17 pooka (int, const struct sockaddr *, socklen_t), \ 2506 1.17 pooka (fd, name, namelen)) 2507 1.17 pooka 2508 1.17 pooka FDCALL(int, getpeername, DUALCALL_GETPEERNAME, \ 2509 1.17 pooka (int fd, struct sockaddr *name, socklen_t *namelen), \ 2510 1.17 pooka (int, struct sockaddr *, socklen_t *), \ 2511 1.17 pooka (fd, name, namelen)) 2512 1.17 pooka 2513 1.17 pooka FDCALL(int, getsockname, DUALCALL_GETSOCKNAME, \ 2514 1.17 pooka (int fd, struct sockaddr *name, socklen_t *namelen), \ 2515 1.17 pooka (int, struct sockaddr *, socklen_t *), \ 2516 1.17 pooka (fd, name, namelen)) 2517 1.17 pooka 2518 1.17 pooka FDCALL(int, listen, DUALCALL_LISTEN, \ 2519 1.17 pooka (int fd, int backlog), \ 2520 1.17 pooka (int, int), \ 2521 1.17 pooka (fd, backlog)) 2522 1.17 pooka 2523 1.17 pooka FDCALL(ssize_t, recvfrom, DUALCALL_RECVFROM, \ 2524 1.17 pooka (int fd, void *buf, size_t len, int flags, \ 2525 1.17 pooka struct sockaddr *from, socklen_t *fromlen), \ 2526 1.17 pooka (int, void *, size_t, int, struct sockaddr *, socklen_t *), \ 2527 1.17 pooka (fd, buf, len, flags, from, fromlen)) 2528 1.17 pooka 2529 1.17 pooka FDCALL(ssize_t, sendto, DUALCALL_SENDTO, \ 2530 1.17 pooka (int fd, const void *buf, size_t len, int flags, \ 2531 1.17 pooka const struct sockaddr *to, socklen_t tolen), \ 2532 1.17 pooka (int, const void *, size_t, int, \ 2533 1.17 pooka const struct sockaddr *, socklen_t), \ 2534 1.17 pooka (fd, buf, len, flags, to, tolen)) 2535 1.17 pooka 2536 1.17 pooka FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT, \ 2537 1.17 pooka (int fd, int level, int optn, void *optval, socklen_t *optlen), \ 2538 1.17 pooka (int, int, int, void *, socklen_t *), \ 2539 1.17 pooka (fd, level, optn, optval, optlen)) 2540 1.17 pooka 2541 1.17 pooka FDCALL(int, setsockopt, DUALCALL_SETSOCKOPT, \ 2542 1.17 pooka (int fd, int level, int optn, \ 2543 1.17 pooka const void *optval, socklen_t optlen), \ 2544 1.17 pooka (int, int, int, const void *, socklen_t), \ 2545 1.17 pooka (fd, level, optn, optval, optlen)) 2546 1.17 pooka 2547 1.17 pooka FDCALL(int, shutdown, DUALCALL_SHUTDOWN, \ 2548 1.17 pooka (int fd, int how), \ 2549 1.17 pooka (int, int), \ 2550 1.17 pooka (fd, how)) 2551 1.17 pooka 2552 1.31 pooka FDCALL(ssize_t, REALREAD, DUALCALL_READ, \ 2553 1.17 pooka (int fd, void *buf, size_t buflen), \ 2554 1.17 pooka (int, void *, size_t), \ 2555 1.17 pooka (fd, buf, buflen)) 2556 1.17 pooka 2557 1.100 pooka #ifdef __linux__ 2558 1.100 pooka ssize_t __read_chk(int, void *, size_t) 2559 1.100 pooka __attribute__((alias("read"))); 2560 1.100 pooka #endif 2561 1.100 pooka 2562 1.18 pooka FDCALL(ssize_t, readv, DUALCALL_READV, \ 2563 1.17 pooka (int fd, const struct iovec *iov, int iovcnt), \ 2564 1.17 pooka (int, const struct iovec *, int), \ 2565 1.17 pooka (fd, iov, iovcnt)) 2566 1.17 pooka 2567 1.60 pooka FDCALL(ssize_t, REALPREAD, DUALCALL_PREAD, \ 2568 1.60 pooka (int fd, void *buf, size_t nbytes, off_t offset), \ 2569 1.60 pooka (int, void *, size_t, off_t), \ 2570 1.60 pooka (fd, buf, nbytes, offset)) 2571 1.60 pooka 2572 1.60 pooka FDCALL(ssize_t, preadv, DUALCALL_PREADV, \ 2573 1.60 pooka (int fd, const struct iovec *iov, int iovcnt, off_t offset), \ 2574 1.60 pooka (int, const struct iovec *, int, off_t), \ 2575 1.60 pooka (fd, iov, iovcnt, offset)) 2576 1.60 pooka 2577 1.17 pooka FDCALL(ssize_t, writev, DUALCALL_WRITEV, \ 2578 1.17 pooka (int fd, const struct iovec *iov, int iovcnt), \ 2579 1.17 pooka (int, const struct iovec *, int), \ 2580 1.17 pooka (fd, iov, iovcnt)) 2581 1.45 pooka 2582 1.60 pooka FDCALL(ssize_t, REALPWRITE, DUALCALL_PWRITE, \ 2583 1.60 pooka (int fd, const void *buf, size_t nbytes, off_t offset), \ 2584 1.60 pooka (int, const void *, size_t, off_t), \ 2585 1.60 pooka (fd, buf, nbytes, offset)) 2586 1.60 pooka 2587 1.60 pooka FDCALL(ssize_t, pwritev, DUALCALL_PWRITEV, \ 2588 1.60 pooka (int fd, const struct iovec *iov, int iovcnt, off_t offset), \ 2589 1.60 pooka (int, const struct iovec *, int, off_t), \ 2590 1.60 pooka (fd, iov, iovcnt, offset)) 2591 1.60 pooka 2592 1.97 pooka #ifndef __linux__ 2593 1.45 pooka FDCALL(int, REALFSTAT, DUALCALL_FSTAT, \ 2594 1.45 pooka (int fd, struct stat *sb), \ 2595 1.45 pooka (int, struct stat *), \ 2596 1.45 pooka (fd, sb)) 2597 1.97 pooka #endif 2598 1.45 pooka 2599 1.111 pooka #ifdef __NetBSD__ 2600 1.128 christos FDCALL(int, REALFSTATVFS1, DUALCALL_FSTATVFS1, \ 2601 1.45 pooka (int fd, struct statvfs *buf, int flags), \ 2602 1.45 pooka (int, struct statvfs *, int), \ 2603 1.45 pooka (fd, buf, flags)) 2604 1.96 pooka #endif 2605 1.45 pooka 2606 1.61 pooka FDCALL(off_t, lseek, DUALCALL_LSEEK, \ 2607 1.45 pooka (int fd, off_t offset, int whence), \ 2608 1.45 pooka (int, off_t, int), \ 2609 1.45 pooka (fd, offset, whence)) 2610 1.96 pooka #ifdef LSEEK_ALIAS 2611 1.132 christos __strong_alias(LSEEK_ALIAS,lseek) 2612 1.96 pooka #endif 2613 1.45 pooka 2614 1.98 pooka #ifndef __linux__ 2615 1.45 pooka FDCALL(int, REALGETDENTS, DUALCALL_GETDENTS, \ 2616 1.45 pooka (int fd, char *buf, size_t nbytes), \ 2617 1.45 pooka (int, char *, size_t), \ 2618 1.45 pooka (fd, buf, nbytes)) 2619 1.98 pooka #endif 2620 1.45 pooka 2621 1.45 pooka FDCALL(int, fchown, DUALCALL_FCHOWN, \ 2622 1.45 pooka (int fd, uid_t owner, gid_t group), \ 2623 1.45 pooka (int, uid_t, gid_t), \ 2624 1.45 pooka (fd, owner, group)) 2625 1.45 pooka 2626 1.45 pooka FDCALL(int, fchmod, DUALCALL_FCHMOD, \ 2627 1.45 pooka (int fd, mode_t mode), \ 2628 1.45 pooka (int, mode_t), \ 2629 1.45 pooka (fd, mode)) 2630 1.45 pooka 2631 1.45 pooka FDCALL(int, ftruncate, DUALCALL_FTRUNCATE, \ 2632 1.45 pooka (int fd, off_t length), \ 2633 1.45 pooka (int, off_t), \ 2634 1.45 pooka (fd, length)) 2635 1.45 pooka 2636 1.45 pooka FDCALL(int, fsync, DUALCALL_FSYNC, \ 2637 1.45 pooka (int fd), \ 2638 1.45 pooka (int), \ 2639 1.45 pooka (fd)) 2640 1.45 pooka 2641 1.111 pooka #ifdef HAVE_FSYNC_RANGE 2642 1.45 pooka FDCALL(int, fsync_range, DUALCALL_FSYNC_RANGE, \ 2643 1.45 pooka (int fd, int how, off_t start, off_t length), \ 2644 1.45 pooka (int, int, off_t, off_t), \ 2645 1.45 pooka (fd, how, start, length)) 2646 1.96 pooka #endif 2647 1.45 pooka 2648 1.45 pooka FDCALL(int, futimes, DUALCALL_FUTIMES, \ 2649 1.139 mrg (int fd, const struct timeval tv[2]), \ 2650 1.139 mrg (int, const struct timeval[2]), \ 2651 1.45 pooka (fd, tv)) 2652 1.45 pooka 2653 1.113 enami FDCALL(int, futimens, DUALCALL_FUTIMENS, \ 2654 1.139 mrg (int fd, const struct timespec ts[2]), \ 2655 1.139 mrg (int, const struct timespec[2]), \ 2656 1.113 enami (fd, ts)) 2657 1.113 enami 2658 1.111 pooka #ifdef HAVE_CHFLAGS 2659 1.60 pooka FDCALL(int, fchflags, DUALCALL_FCHFLAGS, \ 2660 1.60 pooka (int fd, u_long flags), \ 2661 1.60 pooka (int, u_long), \ 2662 1.60 pooka (fd, flags)) 2663 1.96 pooka #endif 2664 1.60 pooka 2665 1.45 pooka /* 2666 1.45 pooka * path-based selectors 2667 1.45 pooka */ 2668 1.45 pooka 2669 1.97 pooka #ifndef __linux__ 2670 1.45 pooka PATHCALL(int, REALSTAT, DUALCALL_STAT, \ 2671 1.45 pooka (const char *path, struct stat *sb), \ 2672 1.45 pooka (const char *, struct stat *), \ 2673 1.45 pooka (path, sb)) 2674 1.45 pooka 2675 1.45 pooka PATHCALL(int, REALLSTAT, DUALCALL_LSTAT, \ 2676 1.45 pooka (const char *path, struct stat *sb), \ 2677 1.45 pooka (const char *, struct stat *), \ 2678 1.45 pooka (path, sb)) 2679 1.97 pooka #endif 2680 1.45 pooka 2681 1.45 pooka PATHCALL(int, chown, DUALCALL_CHOWN, \ 2682 1.45 pooka (const char *path, uid_t owner, gid_t group), \ 2683 1.45 pooka (const char *, uid_t, gid_t), \ 2684 1.45 pooka (path, owner, group)) 2685 1.45 pooka 2686 1.45 pooka PATHCALL(int, lchown, DUALCALL_LCHOWN, \ 2687 1.45 pooka (const char *path, uid_t owner, gid_t group), \ 2688 1.45 pooka (const char *, uid_t, gid_t), \ 2689 1.45 pooka (path, owner, group)) 2690 1.45 pooka 2691 1.45 pooka PATHCALL(int, chmod, DUALCALL_CHMOD, \ 2692 1.45 pooka (const char *path, mode_t mode), \ 2693 1.45 pooka (const char *, mode_t), \ 2694 1.45 pooka (path, mode)) 2695 1.45 pooka 2696 1.45 pooka PATHCALL(int, lchmod, DUALCALL_LCHMOD, \ 2697 1.45 pooka (const char *path, mode_t mode), \ 2698 1.45 pooka (const char *, mode_t), \ 2699 1.45 pooka (path, mode)) 2700 1.45 pooka 2701 1.111 pooka #ifdef __NetBSD__ 2702 1.128 christos PATHCALL(int, REALSTATVFS1, DUALCALL_STATVFS1, \ 2703 1.45 pooka (const char *path, struct statvfs *buf, int flags), \ 2704 1.45 pooka (const char *, struct statvfs *, int), \ 2705 1.45 pooka (path, buf, flags)) 2706 1.96 pooka #endif 2707 1.45 pooka 2708 1.45 pooka PATHCALL(int, unlink, DUALCALL_UNLINK, \ 2709 1.45 pooka (const char *path), \ 2710 1.45 pooka (const char *), \ 2711 1.45 pooka (path)) 2712 1.45 pooka 2713 1.45 pooka PATHCALL(int, symlink, DUALCALL_SYMLINK, \ 2714 1.58 pooka (const char *target, const char *path), \ 2715 1.45 pooka (const char *, const char *), \ 2716 1.58 pooka (target, path)) 2717 1.45 pooka 2718 1.100 pooka /* 2719 1.100 pooka * readlink() can be called from malloc which can be called 2720 1.100 pooka * from dlsym() during init 2721 1.100 pooka */ 2722 1.100 pooka ssize_t 2723 1.100 pooka readlink(const char *path, char *buf, size_t bufsiz) 2724 1.100 pooka { 2725 1.100 pooka int (*op_readlink)(const char *, char *, size_t); 2726 1.100 pooka enum pathtype pt; 2727 1.100 pooka 2728 1.100 pooka if ((pt = path_isrump(path)) != PATH_HOST) { 2729 1.100 pooka op_readlink = GETSYSCALL(rump, READLINK); 2730 1.100 pooka if (pt == PATH_RUMP) 2731 1.100 pooka path = path_host2rump(path); 2732 1.100 pooka } else { 2733 1.100 pooka op_readlink = GETSYSCALL(host, READLINK); 2734 1.100 pooka } 2735 1.100 pooka 2736 1.100 pooka if (__predict_false(op_readlink == NULL)) { 2737 1.100 pooka errno = ENOENT; 2738 1.100 pooka return -1; 2739 1.100 pooka } 2740 1.100 pooka 2741 1.100 pooka return op_readlink(path, buf, bufsiz); 2742 1.100 pooka } 2743 1.45 pooka 2744 1.45 pooka PATHCALL(int, mkdir, DUALCALL_MKDIR, \ 2745 1.45 pooka (const char *path, mode_t mode), \ 2746 1.45 pooka (const char *, mode_t), \ 2747 1.45 pooka (path, mode)) 2748 1.45 pooka 2749 1.45 pooka PATHCALL(int, rmdir, DUALCALL_RMDIR, \ 2750 1.45 pooka (const char *path), \ 2751 1.45 pooka (const char *), \ 2752 1.45 pooka (path)) 2753 1.45 pooka 2754 1.45 pooka PATHCALL(int, utimes, DUALCALL_UTIMES, \ 2755 1.139 mrg (const char *path, const struct timeval tv[2]), \ 2756 1.139 mrg (const char *, const struct timeval[2]), \ 2757 1.45 pooka (path, tv)) 2758 1.45 pooka 2759 1.45 pooka PATHCALL(int, lutimes, DUALCALL_LUTIMES, \ 2760 1.139 mrg (const char *path, const struct timeval tv[2]), \ 2761 1.139 mrg (const char *, const struct timeval[2]), \ 2762 1.45 pooka (path, tv)) 2763 1.45 pooka 2764 1.111 pooka #ifdef HAVE_CHFLAGS 2765 1.60 pooka PATHCALL(int, chflags, DUALCALL_CHFLAGS, \ 2766 1.60 pooka (const char *path, u_long flags), \ 2767 1.60 pooka (const char *, u_long), \ 2768 1.60 pooka (path, flags)) 2769 1.60 pooka 2770 1.60 pooka PATHCALL(int, lchflags, DUALCALL_LCHFLAGS, \ 2771 1.60 pooka (const char *path, u_long flags), \ 2772 1.60 pooka (const char *, u_long), \ 2773 1.60 pooka (path, flags)) 2774 1.111 pooka #endif /* HAVE_CHFLAGS */ 2775 1.60 pooka 2776 1.45 pooka PATHCALL(int, truncate, DUALCALL_TRUNCATE, \ 2777 1.45 pooka (const char *path, off_t length), \ 2778 1.45 pooka (const char *, off_t), \ 2779 1.45 pooka (path, length)) 2780 1.48 pooka 2781 1.65 pooka PATHCALL(int, access, DUALCALL_ACCESS, \ 2782 1.65 pooka (const char *path, int mode), \ 2783 1.65 pooka (const char *, int), \ 2784 1.65 pooka (path, mode)) 2785 1.65 pooka 2786 1.97 pooka #ifndef __linux__ 2787 1.68 pooka PATHCALL(int, REALMKNOD, DUALCALL_MKNOD, \ 2788 1.68 pooka (const char *path, mode_t mode, dev_t dev), \ 2789 1.68 pooka (const char *, mode_t, dev_t), \ 2790 1.68 pooka (path, mode, dev)) 2791 1.97 pooka #endif 2792 1.68 pooka 2793 1.48 pooka /* 2794 1.48 pooka * Note: with mount the decisive parameter is the mount 2795 1.48 pooka * destination directory. This is because we don't really know 2796 1.48 pooka * about the "source" directory in a generic call (and besides, 2797 1.48 pooka * it might not even exist, cf. nfs). 2798 1.48 pooka */ 2799 1.111 pooka #ifdef __NetBSD__ 2800 1.48 pooka PATHCALL(int, REALMOUNT, DUALCALL_MOUNT, \ 2801 1.48 pooka (const char *type, const char *path, int flags, \ 2802 1.48 pooka void *data, size_t dlen), \ 2803 1.48 pooka (const char *, const char *, int, void *, size_t), \ 2804 1.48 pooka (type, path, flags, data, dlen)) 2805 1.48 pooka 2806 1.48 pooka PATHCALL(int, unmount, DUALCALL_UNMOUNT, \ 2807 1.48 pooka (const char *path, int flags), \ 2808 1.48 pooka (const char *, int), \ 2809 1.48 pooka (path, flags)) 2810 1.111 pooka #endif /* __NetBSD__ */ 2811 1.78 pooka 2812 1.111 pooka #ifdef HAVE___QUOTACTL 2813 1.91 dholland PATHCALL(int, __quotactl, DUALCALL_QUOTACTL, \ 2814 1.91 dholland (const char *path, struct quotactl_args *args), \ 2815 1.91 dholland (const char *, struct quotactl_args *), \ 2816 1.91 dholland (path, args)) 2817 1.111 pooka #endif /* HAVE___QUOTACTL */ 2818 1.80 bouyer 2819 1.111 pooka #ifdef __NetBSD__ 2820 1.82 pooka PATHCALL(int, REALGETFH, DUALCALL_GETFH, \ 2821 1.82 pooka (const char *path, void *fhp, size_t *fh_size), \ 2822 1.82 pooka (const char *, void *, size_t *), \ 2823 1.82 pooka (path, fhp, fh_size)) 2824 1.97 pooka #endif 2825 1.82 pooka 2826 1.78 pooka /* 2827 1.78 pooka * These act different on a per-process vfs configuration 2828 1.78 pooka */ 2829 1.78 pooka 2830 1.111 pooka #ifdef __NetBSD__ 2831 1.128 christos VFSCALL(VFSBIT_GETVFSSTAT, int, REALGETVFSSTAT, DUALCALL_GETVFSSTAT, \ 2832 1.78 pooka (struct statvfs *buf, size_t buflen, int flags), \ 2833 1.78 pooka (struct statvfs *, size_t, int), \ 2834 1.78 pooka (buf, buflen, flags)) 2835 1.96 pooka #endif 2836 1.78 pooka 2837 1.111 pooka #ifdef __NetBSD__ 2838 1.78 pooka VFSCALL(VFSBIT_FHCALLS, int, REALFHOPEN, DUALCALL_FHOPEN, \ 2839 1.78 pooka (const void *fhp, size_t fh_size, int flags), \ 2840 1.78 pooka (const char *, size_t, int), \ 2841 1.78 pooka (fhp, fh_size, flags)) 2842 1.78 pooka 2843 1.78 pooka VFSCALL(VFSBIT_FHCALLS, int, REALFHSTAT, DUALCALL_FHSTAT, \ 2844 1.78 pooka (const void *fhp, size_t fh_size, struct stat *sb), \ 2845 1.78 pooka (const char *, size_t, struct stat *), \ 2846 1.78 pooka (fhp, fh_size, sb)) 2847 1.78 pooka 2848 1.78 pooka VFSCALL(VFSBIT_FHCALLS, int, REALFHSTATVFS1, DUALCALL_FHSTATVFS1, \ 2849 1.78 pooka (const void *fhp, size_t fh_size, struct statvfs *sb, int flgs),\ 2850 1.78 pooka (const char *, size_t, struct statvfs *, int), \ 2851 1.78 pooka (fhp, fh_size, sb, flgs)) 2852 1.97 pooka #endif 2853 1.78 pooka 2854 1.96 pooka 2855 1.111 pooka #ifdef __NetBSD__ 2856 1.96 pooka 2857 1.78 pooka /* finally, put nfssvc here. "keep the namespace clean" */ 2858 1.78 pooka #include <nfs/rpcv2.h> 2859 1.78 pooka #include <nfs/nfs.h> 2860 1.78 pooka 2861 1.78 pooka int 2862 1.78 pooka nfssvc(int flags, void *argstructp) 2863 1.78 pooka { 2864 1.78 pooka int (*op_nfssvc)(int, void *); 2865 1.78 pooka 2866 1.78 pooka if (vfsbits & VFSBIT_NFSSVC){ 2867 1.78 pooka struct nfsd_args *nfsdargs; 2868 1.78 pooka 2869 1.78 pooka /* massage the socket descriptor if necessary */ 2870 1.78 pooka if (flags == NFSSVC_ADDSOCK) { 2871 1.78 pooka nfsdargs = argstructp; 2872 1.78 pooka nfsdargs->sock = fd_host2rump(nfsdargs->sock); 2873 1.78 pooka } 2874 1.78 pooka op_nfssvc = GETSYSCALL(rump, NFSSVC); 2875 1.78 pooka } else 2876 1.78 pooka op_nfssvc = GETSYSCALL(host, NFSSVC); 2877 1.78 pooka 2878 1.78 pooka return op_nfssvc(flags, argstructp); 2879 1.78 pooka } 2880 1.111 pooka #endif /* __NetBSD__ */ 2881