1 /* $NetBSD: hijack.c,v 1.48 2011/02/17 17:18:08 pooka Exp $ */ 2 3 /*- 4 * Copyright (c) 2011 Antti Kantee. All Rights Reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 16 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __RCSID("$NetBSD: hijack.c,v 1.48 2011/02/17 17:18:08 pooka Exp $"); 30 31 #define __ssp_weak_name(fun) _hijack_ ## fun 32 33 #include <sys/param.h> 34 #include <sys/types.h> 35 #include <sys/event.h> 36 #include <sys/ioctl.h> 37 #include <sys/mount.h> 38 #include <sys/poll.h> 39 #include <sys/socket.h> 40 #include <sys/statvfs.h> 41 42 #include <rump/rumpclient.h> 43 #include <rump/rump_syscalls.h> 44 45 #include <assert.h> 46 #include <dlfcn.h> 47 #include <err.h> 48 #include <errno.h> 49 #include <fcntl.h> 50 #include <poll.h> 51 #include <pthread.h> 52 #include <signal.h> 53 #include <stdarg.h> 54 #include <stdbool.h> 55 #include <stdio.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include <time.h> 59 #include <unistd.h> 60 61 enum dualcall { 62 DUALCALL_WRITE, DUALCALL_WRITEV, 63 DUALCALL_IOCTL, DUALCALL_FCNTL, 64 DUALCALL_SOCKET, DUALCALL_ACCEPT, DUALCALL_BIND, DUALCALL_CONNECT, 65 DUALCALL_GETPEERNAME, DUALCALL_GETSOCKNAME, DUALCALL_LISTEN, 66 DUALCALL_RECVFROM, DUALCALL_RECVMSG, 67 DUALCALL_SENDTO, DUALCALL_SENDMSG, 68 DUALCALL_GETSOCKOPT, DUALCALL_SETSOCKOPT, 69 DUALCALL_SHUTDOWN, 70 DUALCALL_READ, DUALCALL_READV, 71 DUALCALL_DUP2, 72 DUALCALL_CLOSE, 73 DUALCALL_POLLTS, 74 DUALCALL_KEVENT, 75 DUALCALL_STAT, DUALCALL_LSTAT, DUALCALL_FSTAT, 76 DUALCALL_CHMOD, DUALCALL_LCHMOD, DUALCALL_FCHMOD, 77 DUALCALL_CHOWN, DUALCALL_LCHOWN, DUALCALL_FCHOWN, 78 DUALCALL_OPEN, 79 DUALCALL_STATVFS1, DUALCALL_FSTATVFS1, 80 DUALCALL_CHDIR, DUALCALL_FCHDIR, 81 DUALCALL_LSEEK, 82 DUALCALL_GETDENTS, 83 DUALCALL_UNLINK, DUALCALL_SYMLINK, DUALCALL_READLINK, 84 DUALCALL_RENAME, 85 DUALCALL_MKDIR, DUALCALL_RMDIR, 86 DUALCALL_UTIMES, DUALCALL_LUTIMES, DUALCALL_FUTIMES, 87 DUALCALL_TRUNCATE, DUALCALL_FTRUNCATE, 88 DUALCALL_FSYNC, DUALCALL_FSYNC_RANGE, 89 DUALCALL_MOUNT, DUALCALL_UNMOUNT, 90 DUALCALL__NUM 91 }; 92 93 #define RSYS_STRING(a) __STRING(a) 94 #define RSYS_NAME(a) RSYS_STRING(__CONCAT(RUMP_SYS_RENAME_,a)) 95 96 /* 97 * Would be nice to get this automatically in sync with libc. 98 * Also, this does not work for compat-using binaries! 99 */ 100 #if !__NetBSD_Prereq__(5,99,7) 101 #define REALSELECT select 102 #define REALPOLLTS pollts 103 #define REALKEVENT kevent 104 #define REALSTAT __stat30 105 #define REALLSTAT __lstat30 106 #define REALFSTAT __fstat30 107 #define REALUTIMES utimes 108 #define REALLUTIMES lutimes 109 #define REALFUTIMES futimes 110 #else 111 #define REALSELECT _sys___select50 112 #define REALPOLLTS _sys___pollts50 113 #define REALKEVENT _sys___kevent50 114 #define REALSTAT __stat50 115 #define REALLSTAT __lstat50 116 #define REALFSTAT __fstat50 117 #define REALUTIMES __utimes50 118 #define REALLUTIMES __lutimes50 119 #define REALFUTIMES __futimes50 120 #endif 121 #define REALREAD _sys_read 122 #define REALGETDENTS __getdents30 123 #define REALMOUNT __mount50 124 125 int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *); 126 int REALPOLLTS(struct pollfd *, nfds_t, 127 const struct timespec *, const sigset_t *); 128 int REALKEVENT(int, const struct kevent *, size_t, struct kevent *, size_t, 129 const struct timespec *); 130 ssize_t REALREAD(int, void *, size_t); 131 int REALSTAT(const char *, struct stat *); 132 int REALLSTAT(const char *, struct stat *); 133 int REALFSTAT(int, struct stat *); 134 int REALGETDENTS(int, char *, size_t); 135 int REALUTIMES(const char *, const struct timeval [2]); 136 int REALLUTIMES(const char *, const struct timeval [2]); 137 int REALFUTIMES(int, const struct timeval [2]); 138 int REALMOUNT(const char *, const char *, int, void *, size_t); 139 140 #define S(a) __STRING(a) 141 struct sysnames { 142 enum dualcall scm_callnum; 143 const char *scm_hostname; 144 const char *scm_rumpname; 145 } syscnames[] = { 146 { DUALCALL_SOCKET, "__socket30", RSYS_NAME(SOCKET) }, 147 { DUALCALL_ACCEPT, "accept", RSYS_NAME(ACCEPT) }, 148 { DUALCALL_BIND, "bind", RSYS_NAME(BIND) }, 149 { DUALCALL_CONNECT, "connect", RSYS_NAME(CONNECT) }, 150 { DUALCALL_GETPEERNAME, "getpeername", RSYS_NAME(GETPEERNAME) }, 151 { DUALCALL_GETSOCKNAME, "getsockname", RSYS_NAME(GETSOCKNAME) }, 152 { DUALCALL_LISTEN, "listen", RSYS_NAME(LISTEN) }, 153 { DUALCALL_RECVFROM, "recvfrom", RSYS_NAME(RECVFROM) }, 154 { DUALCALL_RECVMSG, "recvmsg", RSYS_NAME(RECVMSG) }, 155 { DUALCALL_SENDTO, "sendto", RSYS_NAME(SENDTO) }, 156 { DUALCALL_SENDMSG, "sendmsg", RSYS_NAME(SENDMSG) }, 157 { DUALCALL_GETSOCKOPT, "getsockopt", RSYS_NAME(GETSOCKOPT) }, 158 { DUALCALL_SETSOCKOPT, "setsockopt", RSYS_NAME(SETSOCKOPT) }, 159 { DUALCALL_SHUTDOWN, "shutdown", RSYS_NAME(SHUTDOWN) }, 160 { DUALCALL_READ, S(REALREAD), RSYS_NAME(READ) }, 161 { DUALCALL_READV, "readv", RSYS_NAME(READV) }, 162 { DUALCALL_WRITE, "write", RSYS_NAME(WRITE) }, 163 { DUALCALL_WRITEV, "writev", RSYS_NAME(WRITEV) }, 164 { DUALCALL_IOCTL, "ioctl", RSYS_NAME(IOCTL) }, 165 { DUALCALL_FCNTL, "fcntl", RSYS_NAME(FCNTL) }, 166 { DUALCALL_DUP2, "dup2", RSYS_NAME(DUP2) }, 167 { DUALCALL_CLOSE, "close", RSYS_NAME(CLOSE) }, 168 { DUALCALL_POLLTS, S(REALPOLLTS), RSYS_NAME(POLLTS) }, 169 { DUALCALL_KEVENT, S(REALKEVENT), RSYS_NAME(KEVENT) }, 170 { DUALCALL_STAT, S(REALSTAT), RSYS_NAME(STAT) }, 171 { DUALCALL_LSTAT, S(REALLSTAT), RSYS_NAME(LSTAT) }, 172 { DUALCALL_FSTAT, S(REALFSTAT), RSYS_NAME(FSTAT) }, 173 { DUALCALL_CHOWN, "chown", RSYS_NAME(CHOWN) }, 174 { DUALCALL_LCHOWN, "lchown", RSYS_NAME(LCHOWN) }, 175 { DUALCALL_FCHOWN, "fchown", RSYS_NAME(FCHOWN) }, 176 { DUALCALL_CHMOD, "chmod", RSYS_NAME(CHMOD) }, 177 { DUALCALL_LCHMOD, "lchmod", RSYS_NAME(LCHMOD) }, 178 { DUALCALL_FCHMOD, "fchmod", RSYS_NAME(FCHMOD) }, 179 { DUALCALL_UTIMES, S(REALUTIMES), RSYS_NAME(UTIMES) }, 180 { DUALCALL_LUTIMES, S(REALLUTIMES), RSYS_NAME(LUTIMES) }, 181 { DUALCALL_FUTIMES, S(REALFUTIMES), RSYS_NAME(FUTIMES) }, 182 { DUALCALL_OPEN, "open", RSYS_NAME(OPEN) }, 183 { DUALCALL_STATVFS1, "statvfs1", RSYS_NAME(STATVFS1) }, 184 { DUALCALL_FSTATVFS1, "fstatvfs1", RSYS_NAME(FSTATVFS1) }, 185 { DUALCALL_CHDIR, "chdir", RSYS_NAME(CHDIR) }, 186 { DUALCALL_FCHDIR, "fchdir", RSYS_NAME(FCHDIR) }, 187 { DUALCALL_LSEEK, "lseek", RSYS_NAME(LSEEK) }, 188 { DUALCALL_GETDENTS, "__getdents30", RSYS_NAME(GETDENTS) }, 189 { DUALCALL_UNLINK, "unlink", RSYS_NAME(UNLINK) }, 190 { DUALCALL_SYMLINK, "symlink", RSYS_NAME(SYMLINK) }, 191 { DUALCALL_READLINK, "readlink", RSYS_NAME(READLINK) }, 192 { DUALCALL_RENAME, "rename", RSYS_NAME(RENAME) }, 193 { DUALCALL_MKDIR, "mkdir", RSYS_NAME(MKDIR) }, 194 { DUALCALL_RMDIR, "rmdir", RSYS_NAME(RMDIR) }, 195 { DUALCALL_TRUNCATE, "truncate", RSYS_NAME(TRUNCATE) }, 196 { DUALCALL_FTRUNCATE, "ftruncate", RSYS_NAME(FTRUNCATE) }, 197 { DUALCALL_FSYNC, "fsync", RSYS_NAME(FSYNC) }, 198 { DUALCALL_FSYNC_RANGE, "fsync_range", RSYS_NAME(FSYNC_RANGE) }, 199 { DUALCALL_MOUNT, S(REALMOUNT), RSYS_NAME(MOUNT) }, 200 { DUALCALL_UNMOUNT, "unmount", RSYS_NAME(UNMOUNT) }, 201 }; 202 #undef S 203 204 struct bothsys { 205 void *bs_host; 206 void *bs_rump; 207 } syscalls[DUALCALL__NUM]; 208 #define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which 209 210 pid_t (*host_fork)(void); 211 int (*host_daemon)(int, int); 212 int (*host_execve)(const char *, char *const[], char *const[]); 213 214 /* ok, we need *two* bits per dup2'd fd to track fd+HIJACKOFF aliases */ 215 static uint32_t dup2mask; 216 #define ISDUP2D(fd) (((fd) < 16) && (1<<(fd) & dup2mask)) 217 #define SETDUP2(fd) \ 218 do { if ((fd) < 16) dup2mask |= (1<<(fd)); } while (/*CONSTCOND*/0) 219 #define CLRDUP2(fd) \ 220 do { if ((fd) < 16) dup2mask &= ~(1<<(fd)); } while (/*CONSTCOND*/0) 221 #define ISDUP2ALIAS(fd) (((fd) < 16) && (1<<((fd)+16) & dup2mask)) 222 #define SETDUP2ALIAS(fd) \ 223 do { if ((fd) < 16) dup2mask |= (1<<((fd)+16)); } while (/*CONSTCOND*/0) 224 #define CLRDUP2ALIAS(fd) \ 225 do { if ((fd) < 16) dup2mask &= ~(1<<((fd)+16)); } while (/*CONSTCOND*/0) 226 227 //#define DEBUGJACK 228 #ifdef DEBUGJACK 229 #define DPRINTF(x) mydprintf x 230 static void 231 mydprintf(const char *fmt, ...) 232 { 233 va_list ap; 234 235 if (ISDUP2D(STDERR_FILENO)) 236 return; 237 238 va_start(ap, fmt); 239 vfprintf(stderr, fmt, ap); 240 va_end(ap); 241 } 242 243 #else 244 #define DPRINTF(x) 245 #endif 246 247 #define FDCALL(type, name, rcname, args, proto, vars) \ 248 type name args \ 249 { \ 250 type (*fun) proto; \ 251 \ 252 DPRINTF(("%s -> %d\n", __STRING(name), fd)); \ 253 if (fd_isrump(fd)) { \ 254 fun = syscalls[rcname].bs_rump; \ 255 fd = fd_host2rump(fd); \ 256 } else { \ 257 fun = syscalls[rcname].bs_host; \ 258 } \ 259 \ 260 return fun vars; \ 261 } 262 263 #define PATHCALL(type, name, rcname, args, proto, vars) \ 264 type name args \ 265 { \ 266 type (*fun) proto; \ 267 \ 268 DPRINTF(("%s -> %s\n", __STRING(name), path)); \ 269 if (path_isrump(path)) { \ 270 fun = syscalls[rcname].bs_rump; \ 271 path = path_host2rump(path); \ 272 } else { \ 273 fun = syscalls[rcname].bs_host; \ 274 } \ 275 \ 276 return fun vars; \ 277 } 278 279 /* 280 * This is called from librumpclient in case of LD_PRELOAD. 281 * It ensures correct RTLD_NEXT. 282 * 283 * ... except, it's apparently extremely difficult to force 284 * at least gcc to generate an actual stack frame here. So 285 * sprinkle some volatile foobar and baz to throw the optimizer 286 * off the scent and generate a variable assignment with the 287 * return value. The posterboy for this meltdown is amd64 288 * with -O2. At least with gcc 4.1.3 i386 works regardless of 289 * optimization. 290 */ 291 volatile int rumphijack_unrope; /* there, unhang yourself */ 292 static void * 293 hijackdlsym(void *handle, const char *symbol) 294 { 295 void *rv; 296 297 rv = dlsym(handle, symbol); 298 rumphijack_unrope = *(volatile int *)rv; 299 300 return (void *)rv; 301 } 302 303 static int pwdinrump = 0; 304 305 /* low calorie sockets? */ 306 static bool hostlocalsockets = true; 307 308 static void __attribute__((constructor)) 309 rcinit(void) 310 { 311 char buf[64]; 312 extern void *(*rumpclient_dlsym)(void *, const char *); 313 unsigned i, j; 314 315 rumpclient_dlsym = hijackdlsym; 316 host_fork = dlsym(RTLD_NEXT, "fork"); 317 host_daemon = dlsym(RTLD_NEXT, "daemon"); 318 host_execve = dlsym(RTLD_NEXT, "execve"); 319 320 /* 321 * In theory cannot print anything during lookups because 322 * we might not have the call vector set up. so, the errx() 323 * is a bit of a strech, but it might work. 324 */ 325 326 for (i = 0; i < DUALCALL__NUM; i++) { 327 /* build runtime O(1) access */ 328 for (j = 0; j < __arraycount(syscnames); j++) { 329 if (syscnames[j].scm_callnum == i) 330 break; 331 } 332 333 if (j == __arraycount(syscnames)) 334 errx(1, "rumphijack error: syscall pos %d missing", i); 335 336 syscalls[i].bs_host = dlsym(RTLD_NEXT, 337 syscnames[j].scm_hostname); 338 if (syscalls[i].bs_host == NULL) 339 errx(1, "hostcall %s not found missing", 340 syscnames[j].scm_hostname); 341 342 syscalls[i].bs_rump = dlsym(RTLD_NEXT, 343 syscnames[j].scm_rumpname); 344 if (syscalls[i].bs_rump == NULL) 345 errx(1, "rumpcall %s not found missing", 346 syscnames[j].scm_rumpname); 347 } 348 349 if (rumpclient_init() == -1) 350 err(1, "rumpclient init"); 351 352 /* set client persistence level */ 353 if (getenv_r("RUMPHIJACK_RETRYCONNECT", buf, sizeof(buf)) != -1) { 354 if (strcmp(buf, "die") == 0) 355 rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_DIE); 356 else if (strcmp(buf, "inftime") == 0) 357 rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_INFTIME); 358 else if (strcmp(buf, "once") == 0) 359 rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_ONCE); 360 else { 361 time_t timeout; 362 char *ep; 363 364 timeout = (time_t)strtoll(buf, &ep, 10); 365 if (timeout <= 0 || ep != buf + strlen(buf)) 366 errx(1, "RUMPHIJACK_RETRYCONNECT must be " 367 "keyword or integer, got: %s", buf); 368 369 rumpclient_setconnretry(timeout); 370 } 371 } 372 373 if (getenv_r("RUMPHIJACK__DUP2MASK", buf, sizeof(buf)) == 0) { 374 dup2mask = strtoul(buf, NULL, 10); 375 unsetenv("RUMPHIJACK__DUP2MASK"); 376 } 377 if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) { 378 pwdinrump = strtoul(buf, NULL, 10); 379 unsetenv("RUMPHIJACK__PWDINRUMP"); 380 } 381 } 382 383 /* XXX: need runtime selection. low for now due to FD_SETSIZE */ 384 #define HIJACK_FDOFF 128 385 static int 386 fd_rump2host(int fd) 387 { 388 389 if (fd == -1) 390 return fd; 391 392 if (!ISDUP2D(fd)) 393 fd += HIJACK_FDOFF; 394 395 return fd; 396 } 397 398 static int 399 fd_host2rump(int fd) 400 { 401 402 if (!ISDUP2D(fd)) 403 fd -= HIJACK_FDOFF; 404 return fd; 405 } 406 407 static bool 408 fd_isrump(int fd) 409 { 410 411 return ISDUP2D(fd) || fd >= HIJACK_FDOFF; 412 } 413 414 #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_FDOFF) 415 416 #define RUMPPREFIX "/rump" 417 static int 418 path_isrump(const char *path) 419 { 420 421 if (*path == '/') { 422 if (strncmp(path, RUMPPREFIX, sizeof(RUMPPREFIX)-1) == 0) 423 return 1; 424 return 0; 425 } else { 426 return pwdinrump; 427 } 428 } 429 430 static const char *rootpath = "/"; 431 static const char * 432 path_host2rump(const char *path) 433 { 434 const char *rv; 435 436 if (*path == '/') { 437 rv = path + (sizeof(RUMPPREFIX)-1); 438 if (*rv == '\0') 439 rv = rootpath; 440 } else { 441 rv = path; 442 } 443 444 return rv; 445 } 446 447 static int 448 dodup(int oldd, int minfd) 449 { 450 int (*op_fcntl)(int, int, ...); 451 int newd; 452 int isrump; 453 454 DPRINTF(("dup -> %d (minfd %d)\n", oldd, minfd)); 455 if (fd_isrump(oldd)) { 456 op_fcntl = GETSYSCALL(rump, FCNTL); 457 oldd = fd_host2rump(oldd); 458 isrump = 1; 459 } else { 460 op_fcntl = GETSYSCALL(host, FCNTL); 461 isrump = 0; 462 } 463 464 newd = op_fcntl(oldd, F_DUPFD, minfd); 465 466 if (isrump) 467 newd = fd_rump2host(newd); 468 DPRINTF(("dup <- %d\n", newd)); 469 470 return newd; 471 } 472 473 /* 474 * dup a host file descriptor so that it doesn't collide with the dup2mask 475 */ 476 static int 477 fd_dupgood(int fd) 478 { 479 int (*op_fcntl)(int, int, ...) = GETSYSCALL(host, FCNTL); 480 int (*op_close)(int) = GETSYSCALL(host, CLOSE); 481 int ofd, i; 482 483 for (i = 1; ISDUP2D(fd); i++) { 484 ofd = fd; 485 fd = op_fcntl(ofd, F_DUPFD, i); 486 op_close(ofd); 487 } 488 489 return fd; 490 } 491 492 int 493 open(const char *path, int flags, ...) 494 { 495 int (*op_open)(const char *, int, ...); 496 bool isrump; 497 va_list ap; 498 int fd; 499 500 if (path_isrump(path)) { 501 path = path_host2rump(path); 502 op_open = GETSYSCALL(rump, OPEN); 503 isrump = true; 504 } else { 505 op_open = GETSYSCALL(host, OPEN); 506 isrump = false; 507 } 508 509 va_start(ap, flags); 510 fd = op_open(path, flags, va_arg(ap, mode_t)); 511 va_end(ap); 512 513 if (isrump) 514 fd = fd_rump2host(fd); 515 else 516 fd = fd_dupgood(fd); 517 return fd; 518 } 519 520 int 521 chdir(const char *path) 522 { 523 int (*op_chdir)(const char *); 524 bool isrump; 525 int rv; 526 527 if (path_isrump(path)) { 528 op_chdir = GETSYSCALL(rump, CHDIR); 529 isrump = true; 530 path = path_host2rump(path); 531 } else { 532 op_chdir = GETSYSCALL(host, CHDIR); 533 isrump = false; 534 } 535 536 rv = op_chdir(path); 537 if (rv == 0) { 538 if (isrump) 539 pwdinrump = true; 540 else 541 pwdinrump = false; 542 } 543 544 return rv; 545 } 546 547 int 548 fchdir(int fd) 549 { 550 int (*op_fchdir)(int); 551 bool isrump; 552 int rv; 553 554 if (fd_isrump(fd)) { 555 op_fchdir = GETSYSCALL(rump, FCHDIR); 556 isrump = true; 557 fd = fd_host2rump(fd); 558 } else { 559 op_fchdir = GETSYSCALL(host, FCHDIR); 560 isrump = false; 561 } 562 563 rv = op_fchdir(fd); 564 if (rv == 0) { 565 if (isrump) 566 pwdinrump = true; 567 else 568 pwdinrump = false; 569 } 570 571 return rv; 572 } 573 574 int __socket30(int, int, int); 575 int 576 __socket30(int domain, int type, int protocol) 577 { 578 int (*op_socket)(int, int, int); 579 int fd; 580 bool dohost; 581 582 dohost = hostlocalsockets && (domain == AF_LOCAL); 583 584 if (dohost) 585 op_socket = GETSYSCALL(host, SOCKET); 586 else 587 op_socket = GETSYSCALL(rump, SOCKET); 588 fd = op_socket(domain, type, protocol); 589 590 if (!dohost) 591 fd = fd_rump2host(fd); 592 else 593 fd = fd_dupgood(fd); 594 DPRINTF(("socket <- %d\n", fd)); 595 596 return fd; 597 } 598 599 int 600 accept(int s, struct sockaddr *addr, socklen_t *addrlen) 601 { 602 int (*op_accept)(int, struct sockaddr *, socklen_t *); 603 int fd; 604 bool isrump; 605 606 isrump = fd_isrump(s); 607 608 DPRINTF(("accept -> %d", s)); 609 if (isrump) { 610 op_accept = GETSYSCALL(rump, ACCEPT); 611 s = fd_host2rump(s); 612 } else { 613 op_accept = GETSYSCALL(host, ACCEPT); 614 } 615 fd = op_accept(s, addr, addrlen); 616 if (fd != -1 && isrump) 617 fd = fd_rump2host(fd); 618 else 619 fd = fd_dupgood(fd); 620 621 DPRINTF((" <- %d\n", fd)); 622 623 return fd; 624 } 625 626 /* 627 * ioctl and fcntl are varargs calls and need special treatment 628 */ 629 int 630 ioctl(int fd, unsigned long cmd, ...) 631 { 632 int (*op_ioctl)(int, unsigned long cmd, ...); 633 va_list ap; 634 int rv; 635 636 DPRINTF(("ioctl -> %d\n", fd)); 637 if (fd_isrump(fd)) { 638 fd = fd_host2rump(fd); 639 op_ioctl = GETSYSCALL(rump, IOCTL); 640 } else { 641 op_ioctl = GETSYSCALL(host, IOCTL); 642 } 643 644 va_start(ap, cmd); 645 rv = op_ioctl(fd, cmd, va_arg(ap, void *)); 646 va_end(ap); 647 return rv; 648 } 649 650 #include <syslog.h> 651 int 652 fcntl(int fd, int cmd, ...) 653 { 654 int (*op_fcntl)(int, int, ...); 655 va_list ap; 656 int rv, minfd, i; 657 658 DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd)); 659 660 switch (cmd) { 661 case F_DUPFD: 662 va_start(ap, cmd); 663 minfd = va_arg(ap, int); 664 va_end(ap); 665 return dodup(fd, minfd); 666 667 case F_CLOSEM: 668 /* 669 * So, if fd < HIJACKOFF, we want to do a host closem. 670 */ 671 672 if (fd < HIJACK_FDOFF) { 673 int closemfd = fd; 674 675 if (rumpclient__closenotify(&closemfd, 676 RUMPCLIENT_CLOSE_FCLOSEM) == -1) 677 return -1; 678 op_fcntl = GETSYSCALL(host, FCNTL); 679 rv = op_fcntl(closemfd, cmd); 680 if (rv) 681 return rv; 682 } 683 684 /* 685 * Additionally, we want to do a rump closem, but only 686 * for the file descriptors not within the dup2mask. 687 */ 688 689 /* why don't we offer fls()? */ 690 for (i = 15; i >= 0; i--) { 691 if (ISDUP2D(i)) 692 break; 693 } 694 695 if (fd >= HIJACK_FDOFF) 696 fd -= HIJACK_FDOFF; 697 else 698 fd = 0; 699 fd = MAX(i+1, fd); 700 701 /* hmm, maybe we should close rump fd's not within dup2mask? */ 702 703 return rump_sys_fcntl(fd, F_CLOSEM); 704 705 case F_MAXFD: 706 /* 707 * For maxfd, if there's a rump kernel fd, return 708 * it hostified. Otherwise, return host's MAXFD 709 * return value. 710 */ 711 if ((rv = rump_sys_fcntl(fd, F_MAXFD)) != -1) { 712 /* 713 * This might go a little wrong in case 714 * of dup2 to [012], but I'm not sure if 715 * there's a justification for tracking 716 * that info. Consider e.g. 717 * dup2(rumpfd, 2) followed by rump_sys_open() 718 * returning 1. We should return 1+HIJACKOFF, 719 * not 2+HIJACKOFF. However, if [01] is not 720 * open, the correct return value is 2. 721 */ 722 return fd_rump2host(fd); 723 } else { 724 op_fcntl = GETSYSCALL(host, FCNTL); 725 return op_fcntl(fd, F_MAXFD); 726 } 727 /*NOTREACHED*/ 728 729 default: 730 if (fd_isrump(fd)) { 731 fd = fd_host2rump(fd); 732 op_fcntl = GETSYSCALL(rump, FCNTL); 733 } else { 734 op_fcntl = GETSYSCALL(host, FCNTL); 735 } 736 737 va_start(ap, cmd); 738 rv = op_fcntl(fd, cmd, va_arg(ap, void *)); 739 va_end(ap); 740 return rv; 741 } 742 /*NOTREACHED*/ 743 } 744 745 int 746 close(int fd) 747 { 748 int (*op_close)(int); 749 int rv; 750 751 DPRINTF(("close -> %d\n", fd)); 752 if (fd_isrump(fd)) { 753 int undup2 = 0; 754 755 fd = fd_host2rump(fd); 756 if (ISDUP2ALIAS(fd)) { 757 _DIAGASSERT(ISDUP2D(fd)); 758 CLRDUP2ALIAS(fd); 759 return 0; 760 } 761 762 if (ISDUP2D(fd)) 763 undup2 = 1; 764 op_close = GETSYSCALL(rump, CLOSE); 765 rv = op_close(fd); 766 if (rv == 0 && undup2) 767 CLRDUP2(fd); 768 } else { 769 if (rumpclient__closenotify(&fd, RUMPCLIENT_CLOSE_CLOSE) == -1) 770 return -1; 771 op_close = GETSYSCALL(host, CLOSE); 772 rv = op_close(fd); 773 } 774 775 return rv; 776 } 777 778 /* 779 * write cannot issue a standard debug printf due to recursion 780 */ 781 ssize_t 782 write(int fd, const void *buf, size_t blen) 783 { 784 ssize_t (*op_write)(int, const void *, size_t); 785 786 if (fd_isrump(fd)) { 787 fd = fd_host2rump(fd); 788 op_write = GETSYSCALL(rump, WRITE); 789 } else { 790 op_write = GETSYSCALL(host, WRITE); 791 } 792 793 return op_write(fd, buf, blen); 794 } 795 796 /* 797 * dup2 is special. we allow dup2 of a rump kernel fd to 0-2 since 798 * many programs do that. dup2 of a rump kernel fd to another value 799 * not >= fdoff is an error. 800 * 801 * Note: cannot rump2host newd, because it is often hardcoded. 802 */ 803 int 804 dup2(int oldd, int newd) 805 { 806 int (*host_dup2)(int, int); 807 int rv; 808 809 DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd)); 810 811 if (fd_isrump(oldd)) { 812 if (!(newd >= 0 && newd <= 2)) 813 return EBADF; 814 oldd = fd_host2rump(oldd); 815 if (oldd == newd) { 816 SETDUP2(newd); 817 SETDUP2ALIAS(newd); 818 return newd; 819 } 820 rv = rump_sys_dup2(oldd, newd); 821 if (rv != -1) 822 SETDUP2(newd); 823 } else { 824 host_dup2 = syscalls[DUALCALL_DUP2].bs_host; 825 if (rumpclient__closenotify(&newd, RUMPCLIENT_CLOSE_DUP2) == -1) 826 return -1; 827 rv = host_dup2(oldd, newd); 828 } 829 830 return rv; 831 } 832 833 int 834 dup(int oldd) 835 { 836 837 return dodup(oldd, 0); 838 } 839 840 pid_t 841 fork() 842 { 843 pid_t rv; 844 845 DPRINTF(("fork\n")); 846 847 rv = rumpclient__dofork(host_fork); 848 849 DPRINTF(("fork returns %d\n", rv)); 850 return rv; 851 } 852 /* we do not have the luxury of not requiring a stackframe */ 853 __strong_alias(__vfork14,fork); 854 855 int 856 daemon(int nochdir, int noclose) 857 { 858 struct rumpclient_fork *rf; 859 860 if ((rf = rumpclient_prefork()) == NULL) 861 return -1; 862 863 if (host_daemon(nochdir, noclose) == -1) 864 return -1; 865 866 if (rumpclient_fork_init(rf) == -1) 867 return -1; 868 869 return 0; 870 } 871 872 int 873 execve(const char *path, char *const argv[], char *const envp[]) 874 { 875 char buf[128]; 876 char *dup2str; 877 char *pwdinrumpstr; 878 char **newenv; 879 size_t nelem; 880 int rv, sverrno; 881 int bonus = 1, i = 0; 882 883 if (dup2mask) { 884 snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2MASK=%u", dup2mask); 885 dup2str = malloc(strlen(buf)+1); 886 if (dup2str == NULL) 887 return ENOMEM; 888 strcpy(dup2str, buf); 889 bonus++; 890 } else { 891 dup2str = NULL; 892 } 893 894 if (pwdinrump) { 895 snprintf(buf, sizeof(buf), "RUMPHIJACK__PWDINRUMP=%u", 896 pwdinrump); 897 pwdinrumpstr = malloc(strlen(buf)+1); 898 if (pwdinrumpstr == NULL) { 899 free(dup2str); 900 return ENOMEM; 901 } 902 strcpy(pwdinrumpstr, buf); 903 bonus++; 904 } else { 905 pwdinrumpstr = NULL; 906 } 907 908 for (nelem = 0; envp && envp[nelem]; nelem++) 909 continue; 910 newenv = malloc(sizeof(*newenv) * nelem+bonus); 911 if (newenv == NULL) { 912 free(dup2str); 913 free(pwdinrumpstr); 914 return ENOMEM; 915 } 916 memcpy(newenv, envp, nelem*sizeof(*newenv)); 917 if (dup2str) { 918 newenv[nelem+i] = dup2str; 919 i++; 920 } 921 if (pwdinrumpstr) { 922 newenv[nelem+i] = pwdinrumpstr; 923 i++; 924 } 925 newenv[nelem+i] = NULL; 926 _DIAGASSERT(i < bonus); 927 928 rv = rumpclient_exec(path, argv, newenv); 929 930 _DIAGASSERT(rv != 0); 931 sverrno = errno; 932 free(newenv); 933 free(dup2str); 934 errno = sverrno; 935 return rv; 936 } 937 938 /* 939 * select is done by calling poll. 940 */ 941 int 942 REALSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 943 struct timeval *timeout) 944 { 945 struct pollfd *pfds; 946 struct timespec ts, *tsp = NULL; 947 nfds_t realnfds; 948 int i, j; 949 int rv, incr; 950 951 DPRINTF(("select\n")); 952 953 /* 954 * Well, first we must scan the fds to figure out how many 955 * fds there really are. This is because up to and including 956 * nb5 poll() silently refuses nfds > process_maxopen_fds. 957 * Seems to be fixed in current, thank the maker. 958 * god damn cluster...bomb. 959 */ 960 961 for (i = 0, realnfds = 0; i < nfds; i++) { 962 if (readfds && FD_ISSET(i, readfds)) { 963 realnfds++; 964 continue; 965 } 966 if (writefds && FD_ISSET(i, writefds)) { 967 realnfds++; 968 continue; 969 } 970 if (exceptfds && FD_ISSET(i, exceptfds)) { 971 realnfds++; 972 continue; 973 } 974 } 975 976 if (realnfds) { 977 pfds = calloc(realnfds, sizeof(*pfds)); 978 if (!pfds) 979 return -1; 980 } else { 981 pfds = NULL; 982 } 983 984 for (i = 0, j = 0; i < nfds; i++) { 985 incr = 0; 986 if (readfds && FD_ISSET(i, readfds)) { 987 pfds[j].fd = i; 988 pfds[j].events |= POLLIN; 989 incr=1; 990 } 991 if (writefds && FD_ISSET(i, writefds)) { 992 pfds[j].fd = i; 993 pfds[j].events |= POLLOUT; 994 incr=1; 995 } 996 if (exceptfds && FD_ISSET(i, exceptfds)) { 997 pfds[j].fd = i; 998 pfds[j].events |= POLLHUP|POLLERR; 999 incr=1; 1000 } 1001 if (incr) 1002 j++; 1003 } 1004 assert(j == (int)realnfds); 1005 1006 if (timeout) { 1007 TIMEVAL_TO_TIMESPEC(timeout, &ts); 1008 tsp = &ts; 1009 } 1010 rv = REALPOLLTS(pfds, realnfds, tsp, NULL); 1011 /* 1012 * "If select() returns with an error the descriptor sets 1013 * will be unmodified" 1014 */ 1015 if (rv < 0) 1016 goto out; 1017 1018 /* 1019 * zero out results (can't use FD_ZERO for the 1020 * obvious select-me-not reason). whee. 1021 * 1022 * We do this here since some software ignores the return 1023 * value of select, and hence if the timeout expires, it may 1024 * assume all input descriptors have activity. 1025 */ 1026 for (i = 0; i < nfds; i++) { 1027 if (readfds) 1028 FD_CLR(i, readfds); 1029 if (writefds) 1030 FD_CLR(i, writefds); 1031 if (exceptfds) 1032 FD_CLR(i, exceptfds); 1033 } 1034 if (rv == 0) 1035 goto out; 1036 1037 /* 1038 * We have >0 fds with activity. Harvest the results. 1039 */ 1040 for (i = 0; i < (int)realnfds; i++) { 1041 if (readfds) { 1042 if (pfds[i].revents & POLLIN) { 1043 FD_SET(pfds[i].fd, readfds); 1044 } 1045 } 1046 if (writefds) { 1047 if (pfds[i].revents & POLLOUT) { 1048 FD_SET(pfds[i].fd, writefds); 1049 } 1050 } 1051 if (exceptfds) { 1052 if (pfds[i].revents & (POLLHUP|POLLERR)) { 1053 FD_SET(pfds[i].fd, exceptfds); 1054 } 1055 } 1056 } 1057 1058 out: 1059 free(pfds); 1060 return rv; 1061 } 1062 1063 static void 1064 checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall) 1065 { 1066 nfds_t i; 1067 1068 for (i = 0; i < nfds; i++) { 1069 if (fds[i].fd == -1) 1070 continue; 1071 1072 if (fd_isrump(fds[i].fd)) 1073 (*rumpcall)++; 1074 else 1075 (*hostcall)++; 1076 } 1077 } 1078 1079 static void 1080 adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int)) 1081 { 1082 nfds_t i; 1083 1084 for (i = 0; i < nfds; i++) { 1085 fds[i].fd = fdadj(fds[i].fd); 1086 } 1087 } 1088 1089 /* 1090 * poll is easy as long as the call comes in the fds only in one 1091 * kernel. otherwise its quite tricky... 1092 */ 1093 struct pollarg { 1094 struct pollfd *pfds; 1095 nfds_t nfds; 1096 const struct timespec *ts; 1097 const sigset_t *sigmask; 1098 int pipefd; 1099 int errnum; 1100 }; 1101 1102 static void * 1103 hostpoll(void *arg) 1104 { 1105 int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *, 1106 const sigset_t *); 1107 struct pollarg *parg = arg; 1108 intptr_t rv; 1109 1110 op_pollts = GETSYSCALL(host, POLLTS); 1111 rv = op_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask); 1112 if (rv == -1) 1113 parg->errnum = errno; 1114 rump_sys_write(parg->pipefd, &rv, sizeof(rv)); 1115 1116 return (void *)(intptr_t)rv; 1117 } 1118 1119 int 1120 REALPOLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts, 1121 const sigset_t *sigmask) 1122 { 1123 int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *, 1124 const sigset_t *); 1125 int (*host_close)(int); 1126 int hostcall = 0, rumpcall = 0; 1127 pthread_t pt; 1128 nfds_t i; 1129 int rv; 1130 1131 DPRINTF(("poll\n")); 1132 checkpoll(fds, nfds, &hostcall, &rumpcall); 1133 1134 if (hostcall && rumpcall) { 1135 struct pollfd *pfd_host = NULL, *pfd_rump = NULL; 1136 int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1}; 1137 struct pollarg parg; 1138 uintptr_t lrv; 1139 int sverrno = 0, trv; 1140 1141 /* 1142 * ok, this is where it gets tricky. We must support 1143 * this since it's a very common operation in certain 1144 * types of software (telnet, netcat, etc). We allocate 1145 * two vectors and run two poll commands in separate 1146 * threads. Whichever returns first "wins" and the 1147 * other kernel's fds won't show activity. 1148 */ 1149 rv = -1; 1150 1151 /* allocate full vector for O(n) joining after call */ 1152 pfd_host = malloc(sizeof(*pfd_host)*(nfds+1)); 1153 if (!pfd_host) 1154 goto out; 1155 pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1)); 1156 if (!pfd_rump) { 1157 goto out; 1158 } 1159 1160 /* split vectors */ 1161 for (i = 0; i < nfds; i++) { 1162 if (fds[i].fd == -1) { 1163 pfd_host[i].fd = -1; 1164 pfd_rump[i].fd = -1; 1165 } else if (fd_isrump(fds[i].fd)) { 1166 pfd_host[i].fd = -1; 1167 pfd_rump[i].fd = fd_host2rump(fds[i].fd); 1168 pfd_rump[i].events = fds[i].events; 1169 } else { 1170 pfd_rump[i].fd = -1; 1171 pfd_host[i].fd = fds[i].fd; 1172 pfd_host[i].events = fds[i].events; 1173 } 1174 pfd_rump[i].revents = pfd_host[i].revents = 0; 1175 fds[i].revents = 0; 1176 } 1177 1178 /* 1179 * then, open two pipes, one for notifications 1180 * to each kernel. 1181 */ 1182 if (rump_sys_pipe(rpipe) == -1) 1183 goto out; 1184 if (pipe(hpipe) == -1) 1185 goto out; 1186 1187 pfd_host[nfds].fd = hpipe[0]; 1188 pfd_host[nfds].events = POLLIN; 1189 pfd_rump[nfds].fd = rpipe[0]; 1190 pfd_rump[nfds].events = POLLIN; 1191 1192 /* 1193 * then, create a thread to do host part and meanwhile 1194 * do rump kernel part right here 1195 */ 1196 1197 parg.pfds = pfd_host; 1198 parg.nfds = nfds+1; 1199 parg.ts = ts; 1200 parg.sigmask = sigmask; 1201 parg.pipefd = rpipe[1]; 1202 pthread_create(&pt, NULL, hostpoll, &parg); 1203 1204 op_pollts = GETSYSCALL(rump, POLLTS); 1205 lrv = op_pollts(pfd_rump, nfds+1, ts, NULL); 1206 sverrno = errno; 1207 write(hpipe[1], &rv, sizeof(rv)); 1208 pthread_join(pt, (void *)&trv); 1209 1210 /* check who "won" and merge results */ 1211 if (lrv != 0 && pfd_host[nfds].revents & POLLIN) { 1212 rv = trv; 1213 1214 for (i = 0; i < nfds; i++) { 1215 if (pfd_rump[i].fd != -1) 1216 fds[i].revents = pfd_rump[i].revents; 1217 } 1218 sverrno = parg.errnum; 1219 } else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) { 1220 rv = trv; 1221 1222 for (i = 0; i < nfds; i++) { 1223 if (pfd_host[i].fd != -1) 1224 fds[i].revents = pfd_host[i].revents; 1225 } 1226 } else { 1227 rv = 0; 1228 } 1229 1230 out: 1231 host_close = GETSYSCALL(host, CLOSE); 1232 if (rpipe[0] != -1) 1233 rump_sys_close(rpipe[0]); 1234 if (rpipe[1] != -1) 1235 rump_sys_close(rpipe[1]); 1236 if (hpipe[0] != -1) 1237 host_close(hpipe[0]); 1238 if (hpipe[1] != -1) 1239 host_close(hpipe[1]); 1240 free(pfd_host); 1241 free(pfd_rump); 1242 errno = sverrno; 1243 } else { 1244 if (hostcall) { 1245 op_pollts = GETSYSCALL(host, POLLTS); 1246 } else { 1247 op_pollts = GETSYSCALL(rump, POLLTS); 1248 adjustpoll(fds, nfds, fd_host2rump); 1249 } 1250 1251 rv = op_pollts(fds, nfds, ts, sigmask); 1252 if (rumpcall) 1253 adjustpoll(fds, nfds, fd_rump2host); 1254 } 1255 1256 return rv; 1257 } 1258 1259 int 1260 poll(struct pollfd *fds, nfds_t nfds, int timeout) 1261 { 1262 struct timespec ts; 1263 struct timespec *tsp = NULL; 1264 1265 if (timeout != INFTIM) { 1266 ts.tv_sec = timeout / 1000; 1267 ts.tv_nsec = (timeout % 1000) * 1000*1000; 1268 1269 tsp = &ts; 1270 } 1271 1272 return REALPOLLTS(fds, nfds, tsp, NULL); 1273 } 1274 1275 int 1276 REALKEVENT(int kq, const struct kevent *changelist, size_t nchanges, 1277 struct kevent *eventlist, size_t nevents, 1278 const struct timespec *timeout) 1279 { 1280 int (*op_kevent)(int, const struct kevent *, size_t, 1281 struct kevent *, size_t, const struct timespec *); 1282 const struct kevent *ev; 1283 size_t i; 1284 1285 /* 1286 * Check that we don't attempt to kevent rump kernel fd's. 1287 * That needs similar treatment to select/poll, but is slightly 1288 * trickier since we need to manage to different kq descriptors. 1289 * (TODO, in case you're wondering). 1290 */ 1291 for (i = 0; i < nchanges; i++) { 1292 ev = &changelist[i]; 1293 if (ev->filter == EVFILT_READ || ev->filter == EVFILT_WRITE || 1294 ev->filter == EVFILT_VNODE) { 1295 if (fd_isrump((int)ev->ident)) 1296 return ENOTSUP; 1297 } 1298 } 1299 1300 op_kevent = GETSYSCALL(host, KEVENT); 1301 return op_kevent(kq, changelist, nchanges, eventlist, nevents, timeout); 1302 } 1303 1304 /* 1305 * Rest are std type calls. 1306 */ 1307 1308 FDCALL(int, bind, DUALCALL_BIND, \ 1309 (int fd, const struct sockaddr *name, socklen_t namelen), \ 1310 (int, const struct sockaddr *, socklen_t), \ 1311 (fd, name, namelen)) 1312 1313 FDCALL(int, connect, DUALCALL_CONNECT, \ 1314 (int fd, const struct sockaddr *name, socklen_t namelen), \ 1315 (int, const struct sockaddr *, socklen_t), \ 1316 (fd, name, namelen)) 1317 1318 FDCALL(int, getpeername, DUALCALL_GETPEERNAME, \ 1319 (int fd, struct sockaddr *name, socklen_t *namelen), \ 1320 (int, struct sockaddr *, socklen_t *), \ 1321 (fd, name, namelen)) 1322 1323 FDCALL(int, getsockname, DUALCALL_GETSOCKNAME, \ 1324 (int fd, struct sockaddr *name, socklen_t *namelen), \ 1325 (int, struct sockaddr *, socklen_t *), \ 1326 (fd, name, namelen)) 1327 1328 FDCALL(int, listen, DUALCALL_LISTEN, \ 1329 (int fd, int backlog), \ 1330 (int, int), \ 1331 (fd, backlog)) 1332 1333 FDCALL(ssize_t, recvfrom, DUALCALL_RECVFROM, \ 1334 (int fd, void *buf, size_t len, int flags, \ 1335 struct sockaddr *from, socklen_t *fromlen), \ 1336 (int, void *, size_t, int, struct sockaddr *, socklen_t *), \ 1337 (fd, buf, len, flags, from, fromlen)) 1338 1339 FDCALL(ssize_t, sendto, DUALCALL_SENDTO, \ 1340 (int fd, const void *buf, size_t len, int flags, \ 1341 const struct sockaddr *to, socklen_t tolen), \ 1342 (int, const void *, size_t, int, \ 1343 const struct sockaddr *, socklen_t), \ 1344 (fd, buf, len, flags, to, tolen)) 1345 1346 FDCALL(ssize_t, recvmsg, DUALCALL_RECVMSG, \ 1347 (int fd, struct msghdr *msg, int flags), \ 1348 (int, struct msghdr *, int), \ 1349 (fd, msg, flags)) 1350 1351 FDCALL(ssize_t, sendmsg, DUALCALL_SENDMSG, \ 1352 (int fd, const struct msghdr *msg, int flags), \ 1353 (int, const struct msghdr *, int), \ 1354 (fd, msg, flags)) 1355 1356 FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT, \ 1357 (int fd, int level, int optn, void *optval, socklen_t *optlen), \ 1358 (int, int, int, void *, socklen_t *), \ 1359 (fd, level, optn, optval, optlen)) 1360 1361 FDCALL(int, setsockopt, DUALCALL_SETSOCKOPT, \ 1362 (int fd, int level, int optn, \ 1363 const void *optval, socklen_t optlen), \ 1364 (int, int, int, const void *, socklen_t), \ 1365 (fd, level, optn, optval, optlen)) 1366 1367 FDCALL(int, shutdown, DUALCALL_SHUTDOWN, \ 1368 (int fd, int how), \ 1369 (int, int), \ 1370 (fd, how)) 1371 1372 #if _FORTIFY_SOURCE > 0 1373 #define STUB(fun) __ssp_weak_name(fun) 1374 ssize_t _sys_readlink(const char * __restrict, char * __restrict, size_t); 1375 ssize_t 1376 STUB(readlink)(const char * __restrict path, char * __restrict buf, 1377 size_t bufsiz) 1378 { 1379 return _sys_readlink(path, buf, bufsiz); 1380 } 1381 1382 char *_sys_getcwd(char *, size_t); 1383 char * 1384 STUB(getcwd)(char *buf, size_t size) 1385 { 1386 return _sys_getcwd(buf, size); 1387 } 1388 #else 1389 #define STUB(fun) fun 1390 #endif 1391 1392 FDCALL(ssize_t, REALREAD, DUALCALL_READ, \ 1393 (int fd, void *buf, size_t buflen), \ 1394 (int, void *, size_t), \ 1395 (fd, buf, buflen)) 1396 1397 FDCALL(ssize_t, readv, DUALCALL_READV, \ 1398 (int fd, const struct iovec *iov, int iovcnt), \ 1399 (int, const struct iovec *, int), \ 1400 (fd, iov, iovcnt)) 1401 1402 FDCALL(ssize_t, writev, DUALCALL_WRITEV, \ 1403 (int fd, const struct iovec *iov, int iovcnt), \ 1404 (int, const struct iovec *, int), \ 1405 (fd, iov, iovcnt)) 1406 1407 FDCALL(int, REALFSTAT, DUALCALL_FSTAT, \ 1408 (int fd, struct stat *sb), \ 1409 (int, struct stat *), \ 1410 (fd, sb)) 1411 1412 FDCALL(int, fstatvfs1, DUALCALL_FSTATVFS1, \ 1413 (int fd, struct statvfs *buf, int flags), \ 1414 (int, struct statvfs *, int), \ 1415 (fd, buf, flags)) 1416 1417 FDCALL(off_t, lseek, DUALCALL_LSEEK, \ 1418 (int fd, off_t offset, int whence), \ 1419 (int, off_t, int), \ 1420 (fd, offset, whence)) 1421 1422 FDCALL(int, REALGETDENTS, DUALCALL_GETDENTS, \ 1423 (int fd, char *buf, size_t nbytes), \ 1424 (int, char *, size_t), \ 1425 (fd, buf, nbytes)) 1426 1427 FDCALL(int, fchown, DUALCALL_FCHOWN, \ 1428 (int fd, uid_t owner, gid_t group), \ 1429 (int, uid_t, gid_t), \ 1430 (fd, owner, group)) 1431 1432 FDCALL(int, fchmod, DUALCALL_FCHMOD, \ 1433 (int fd, mode_t mode), \ 1434 (int, mode_t), \ 1435 (fd, mode)) 1436 1437 FDCALL(int, ftruncate, DUALCALL_FTRUNCATE, \ 1438 (int fd, off_t length), \ 1439 (int, off_t), \ 1440 (fd, length)) 1441 1442 FDCALL(int, fsync, DUALCALL_FSYNC, \ 1443 (int fd), \ 1444 (int), \ 1445 (fd)) 1446 1447 FDCALL(int, fsync_range, DUALCALL_FSYNC_RANGE, \ 1448 (int fd, int how, off_t start, off_t length), \ 1449 (int, int, off_t, off_t), \ 1450 (fd, how, start, length)) 1451 1452 FDCALL(int, futimes, DUALCALL_FUTIMES, \ 1453 (int fd, const struct timeval *tv), \ 1454 (int, const struct timeval *), \ 1455 (fd, tv)) 1456 1457 /* 1458 * path-based selectors 1459 */ 1460 1461 PATHCALL(int, REALSTAT, DUALCALL_STAT, \ 1462 (const char *path, struct stat *sb), \ 1463 (const char *, struct stat *), \ 1464 (path, sb)) 1465 1466 PATHCALL(int, REALLSTAT, DUALCALL_LSTAT, \ 1467 (const char *path, struct stat *sb), \ 1468 (const char *, struct stat *), \ 1469 (path, sb)) 1470 1471 PATHCALL(int, chown, DUALCALL_CHOWN, \ 1472 (const char *path, uid_t owner, gid_t group), \ 1473 (const char *, uid_t, gid_t), \ 1474 (path, owner, group)) 1475 1476 PATHCALL(int, lchown, DUALCALL_LCHOWN, \ 1477 (const char *path, uid_t owner, gid_t group), \ 1478 (const char *, uid_t, gid_t), \ 1479 (path, owner, group)) 1480 1481 PATHCALL(int, chmod, DUALCALL_CHMOD, \ 1482 (const char *path, mode_t mode), \ 1483 (const char *, mode_t), \ 1484 (path, mode)) 1485 1486 PATHCALL(int, lchmod, DUALCALL_LCHMOD, \ 1487 (const char *path, mode_t mode), \ 1488 (const char *, mode_t), \ 1489 (path, mode)) 1490 1491 PATHCALL(int, statvfs1, DUALCALL_STATVFS1, \ 1492 (const char *path, struct statvfs *buf, int flags), \ 1493 (const char *, struct statvfs *, int), \ 1494 (path, buf, flags)) 1495 1496 PATHCALL(int, unlink, DUALCALL_UNLINK, \ 1497 (const char *path), \ 1498 (const char *), \ 1499 (path)) 1500 1501 PATHCALL(int, symlink, DUALCALL_SYMLINK, \ 1502 (const char *path, const char *target), \ 1503 (const char *, const char *), \ 1504 (path, target)) 1505 1506 PATHCALL(ssize_t, readlink, DUALCALL_READLINK, \ 1507 (const char *path, char *buf, size_t bufsiz), \ 1508 (const char *, char *, size_t), \ 1509 (path, buf, bufsiz)) 1510 1511 /* XXX: cross-kernel renames need to be blocked */ 1512 PATHCALL(int, rename, DUALCALL_RENAME, \ 1513 (const char *path, const char *to), \ 1514 (const char *, const char *), \ 1515 (path, to)) 1516 1517 PATHCALL(int, mkdir, DUALCALL_MKDIR, \ 1518 (const char *path, mode_t mode), \ 1519 (const char *, mode_t), \ 1520 (path, mode)) 1521 1522 PATHCALL(int, rmdir, DUALCALL_RMDIR, \ 1523 (const char *path), \ 1524 (const char *), \ 1525 (path)) 1526 1527 PATHCALL(int, utimes, DUALCALL_UTIMES, \ 1528 (const char *path, const struct timeval *tv), \ 1529 (const char *, const struct timeval *), \ 1530 (path, tv)) 1531 1532 PATHCALL(int, lutimes, DUALCALL_LUTIMES, \ 1533 (const char *path, const struct timeval *tv), \ 1534 (const char *, const struct timeval *), \ 1535 (path, tv)) 1536 1537 PATHCALL(int, truncate, DUALCALL_TRUNCATE, \ 1538 (const char *path, off_t length), \ 1539 (const char *, off_t), \ 1540 (path, length)) 1541 1542 /* 1543 * Note: with mount the decisive parameter is the mount 1544 * destination directory. This is because we don't really know 1545 * about the "source" directory in a generic call (and besides, 1546 * it might not even exist, cf. nfs). 1547 */ 1548 PATHCALL(int, REALMOUNT, DUALCALL_MOUNT, \ 1549 (const char *type, const char *path, int flags, \ 1550 void *data, size_t dlen), \ 1551 (const char *, const char *, int, void *, size_t), \ 1552 (type, path, flags, data, dlen)) 1553 1554 PATHCALL(int, unmount, DUALCALL_UNMOUNT, \ 1555 (const char *path, int flags), \ 1556 (const char *, int), \ 1557 (path, flags)) 1558