[BACK]Return to hijack.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / librumphijack

Annotation of src/lib/librumphijack/hijack.c, Revision 1.69

1.69    ! pooka       1: /*      $NetBSD: hijack.c,v 1.68 2011/02/25 18:29:00 pooka Exp $       */
1.1       pooka       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>
1.69    ! pooka      29: __RCSID("$NetBSD: hijack.c,v 1.68 2011/02/25 18:29:00 pooka Exp $");
1.21      christos   30:
                     31: #define __ssp_weak_name(fun) _hijack_ ## fun
1.1       pooka      32:
                     33: #include <sys/param.h>
                     34: #include <sys/types.h>
1.10      pooka      35: #include <sys/event.h>
1.1       pooka      36: #include <sys/ioctl.h>
1.62      pooka      37: #include <sys/mman.h>
1.48      pooka      38: #include <sys/mount.h>
                     39: #include <sys/poll.h>
1.1       pooka      40: #include <sys/socket.h>
1.45      pooka      41: #include <sys/statvfs.h>
1.1       pooka      42:
                     43: #include <rump/rumpclient.h>
                     44: #include <rump/rump_syscalls.h>
                     45:
                     46: #include <assert.h>
                     47: #include <dlfcn.h>
                     48: #include <err.h>
                     49: #include <errno.h>
                     50: #include <fcntl.h>
                     51: #include <poll.h>
                     52: #include <pthread.h>
1.3       pooka      53: #include <signal.h>
1.1       pooka      54: #include <stdarg.h>
1.8       pooka      55: #include <stdbool.h>
1.1       pooka      56: #include <stdio.h>
                     57: #include <stdlib.h>
1.28      pooka      58: #include <string.h>
1.3       pooka      59: #include <time.h>
1.1       pooka      60: #include <unistd.h>
                     61:
1.64      pooka      62: #include "hijack.h"
                     63:
1.17      pooka      64: enum dualcall {
1.60      pooka      65:        DUALCALL_WRITE, DUALCALL_WRITEV, DUALCALL_PWRITE, DUALCALL_PWRITEV,
1.17      pooka      66:        DUALCALL_IOCTL, DUALCALL_FCNTL,
                     67:        DUALCALL_SOCKET, DUALCALL_ACCEPT, DUALCALL_BIND, DUALCALL_CONNECT,
                     68:        DUALCALL_GETPEERNAME, DUALCALL_GETSOCKNAME, DUALCALL_LISTEN,
                     69:        DUALCALL_RECVFROM, DUALCALL_RECVMSG,
                     70:        DUALCALL_SENDTO, DUALCALL_SENDMSG,
                     71:        DUALCALL_GETSOCKOPT, DUALCALL_SETSOCKOPT,
                     72:        DUALCALL_SHUTDOWN,
1.60      pooka      73:        DUALCALL_READ, DUALCALL_READV, DUALCALL_PREAD, DUALCALL_PREADV,
1.41      pooka      74:        DUALCALL_DUP2,
1.34      pooka      75:        DUALCALL_CLOSE,
1.17      pooka      76:        DUALCALL_POLLTS,
1.34      pooka      77:        DUALCALL_KEVENT,
1.45      pooka      78:        DUALCALL_STAT, DUALCALL_LSTAT, DUALCALL_FSTAT,
                     79:        DUALCALL_CHMOD, DUALCALL_LCHMOD, DUALCALL_FCHMOD,
                     80:        DUALCALL_CHOWN, DUALCALL_LCHOWN, DUALCALL_FCHOWN,
                     81:        DUALCALL_OPEN,
                     82:        DUALCALL_STATVFS1, DUALCALL_FSTATVFS1,
                     83:        DUALCALL_CHDIR, DUALCALL_FCHDIR,
                     84:        DUALCALL_LSEEK,
                     85:        DUALCALL_GETDENTS,
                     86:        DUALCALL_UNLINK, DUALCALL_SYMLINK, DUALCALL_READLINK,
                     87:        DUALCALL_RENAME,
                     88:        DUALCALL_MKDIR, DUALCALL_RMDIR,
                     89:        DUALCALL_UTIMES, DUALCALL_LUTIMES, DUALCALL_FUTIMES,
                     90:        DUALCALL_TRUNCATE, DUALCALL_FTRUNCATE,
                     91:        DUALCALL_FSYNC, DUALCALL_FSYNC_RANGE,
1.48      pooka      92:        DUALCALL_MOUNT, DUALCALL_UNMOUNT,
1.57      pooka      93:        DUALCALL___GETCWD,
1.60      pooka      94:        DUALCALL_CHFLAGS, DUALCALL_LCHFLAGS, DUALCALL_FCHFLAGS,
1.65      pooka      95:        DUALCALL_ACCESS,
1.68      pooka      96:        DUALCALL_MKNOD,
1.17      pooka      97:        DUALCALL__NUM
1.1       pooka      98: };
                     99:
1.8       pooka     100: #define RSYS_STRING(a) __STRING(a)
                    101: #define RSYS_NAME(a) RSYS_STRING(__CONCAT(RUMP_SYS_RENAME_,a))
                    102:
1.1       pooka     103: /*
1.14      pooka     104:  * Would be nice to get this automatically in sync with libc.
                    105:  * Also, this does not work for compat-using binaries!
                    106:  */
                    107: #if !__NetBSD_Prereq__(5,99,7)
1.29      pooka     108: #define REALSELECT select
                    109: #define REALPOLLTS pollts
1.34      pooka     110: #define REALKEVENT kevent
1.45      pooka     111: #define REALSTAT __stat30
                    112: #define REALLSTAT __lstat30
                    113: #define REALFSTAT __fstat30
                    114: #define REALUTIMES utimes
                    115: #define REALLUTIMES lutimes
                    116: #define REALFUTIMES futimes
1.68      pooka     117: #define REALMKNOD mknod
1.14      pooka     118: #else
1.29      pooka     119: #define REALSELECT _sys___select50
                    120: #define REALPOLLTS _sys___pollts50
1.34      pooka     121: #define REALKEVENT _sys___kevent50
1.45      pooka     122: #define REALSTAT __stat50
                    123: #define REALLSTAT __lstat50
                    124: #define REALFSTAT __fstat50
                    125: #define REALUTIMES __utimes50
                    126: #define REALLUTIMES __lutimes50
1.69    ! pooka     127: #define REALFUTIMES __futimes50
1.68      pooka     128: #define REALMKNOD __mknod50
1.17      pooka     129: #endif
1.31      pooka     130: #define REALREAD _sys_read
1.60      pooka     131: #define REALPREAD _sys_pread
                    132: #define REALPWRITE _sys_pwrite
1.45      pooka     133: #define REALGETDENTS __getdents30
1.48      pooka     134: #define REALMOUNT __mount50
1.14      pooka     135:
1.29      pooka     136: int REALSELECT(int, fd_set *, fd_set *, fd_set *, struct timeval *);
                    137: int REALPOLLTS(struct pollfd *, nfds_t,
1.20      pooka     138:               const struct timespec *, const sigset_t *);
1.34      pooka     139: int REALKEVENT(int, const struct kevent *, size_t, struct kevent *, size_t,
                    140:               const struct timespec *);
1.31      pooka     141: ssize_t REALREAD(int, void *, size_t);
1.60      pooka     142: ssize_t REALPREAD(int, void *, size_t, off_t);
                    143: ssize_t REALPWRITE(int, const void *, size_t, off_t);
1.45      pooka     144: int REALSTAT(const char *, struct stat *);
                    145: int REALLSTAT(const char *, struct stat *);
                    146: int REALFSTAT(int, struct stat *);
                    147: int REALGETDENTS(int, char *, size_t);
                    148: int REALUTIMES(const char *, const struct timeval [2]);
                    149: int REALLUTIMES(const char *, const struct timeval [2]);
                    150: int REALFUTIMES(int, const struct timeval [2]);
1.48      pooka     151: int REALMOUNT(const char *, const char *, int, void *, size_t);
1.57      pooka     152: int __getcwd(char *, size_t);
1.68      pooka     153: int REALMKNOD(const char *, mode_t, dev_t);
1.17      pooka     154:
                    155: #define S(a) __STRING(a)
                    156: struct sysnames {
                    157:        enum dualcall scm_callnum;
                    158:        const char *scm_hostname;
                    159:        const char *scm_rumpname;
                    160: } syscnames[] = {
                    161:        { DUALCALL_SOCKET,      "__socket30",   RSYS_NAME(SOCKET)       },
                    162:        { DUALCALL_ACCEPT,      "accept",       RSYS_NAME(ACCEPT)       },
                    163:        { DUALCALL_BIND,        "bind",         RSYS_NAME(BIND)         },
                    164:        { DUALCALL_CONNECT,     "connect",      RSYS_NAME(CONNECT)      },
                    165:        { DUALCALL_GETPEERNAME, "getpeername",  RSYS_NAME(GETPEERNAME)  },
                    166:        { DUALCALL_GETSOCKNAME, "getsockname",  RSYS_NAME(GETSOCKNAME)  },
                    167:        { DUALCALL_LISTEN,      "listen",       RSYS_NAME(LISTEN)       },
                    168:        { DUALCALL_RECVFROM,    "recvfrom",     RSYS_NAME(RECVFROM)     },
                    169:        { DUALCALL_RECVMSG,     "recvmsg",      RSYS_NAME(RECVMSG)      },
                    170:        { DUALCALL_SENDTO,      "sendto",       RSYS_NAME(SENDTO)       },
                    171:        { DUALCALL_SENDMSG,     "sendmsg",      RSYS_NAME(SENDMSG)      },
                    172:        { DUALCALL_GETSOCKOPT,  "getsockopt",   RSYS_NAME(GETSOCKOPT)   },
                    173:        { DUALCALL_SETSOCKOPT,  "setsockopt",   RSYS_NAME(SETSOCKOPT)   },
                    174:        { DUALCALL_SHUTDOWN,    "shutdown",     RSYS_NAME(SHUTDOWN)     },
1.31      pooka     175:        { DUALCALL_READ,        S(REALREAD),    RSYS_NAME(READ)         },
1.17      pooka     176:        { DUALCALL_READV,       "readv",        RSYS_NAME(READV)        },
1.60      pooka     177:        { DUALCALL_PREAD,       S(REALPREAD),   RSYS_NAME(PREAD)        },
                    178:        { DUALCALL_PREADV,      "preadv",       RSYS_NAME(PREADV)       },
1.17      pooka     179:        { DUALCALL_WRITE,       "write",        RSYS_NAME(WRITE)        },
                    180:        { DUALCALL_WRITEV,      "writev",       RSYS_NAME(WRITEV)       },
1.60      pooka     181:        { DUALCALL_PWRITE,      S(REALPWRITE),  RSYS_NAME(PWRITE)       },
                    182:        { DUALCALL_PWRITEV,     "pwritev",      RSYS_NAME(PWRITEV)      },
1.17      pooka     183:        { DUALCALL_IOCTL,       "ioctl",        RSYS_NAME(IOCTL)        },
                    184:        { DUALCALL_FCNTL,       "fcntl",        RSYS_NAME(FCNTL)        },
                    185:        { DUALCALL_DUP2,        "dup2",         RSYS_NAME(DUP2)         },
                    186:        { DUALCALL_CLOSE,       "close",        RSYS_NAME(CLOSE)        },
1.29      pooka     187:        { DUALCALL_POLLTS,      S(REALPOLLTS),  RSYS_NAME(POLLTS)       },
1.34      pooka     188:        { DUALCALL_KEVENT,      S(REALKEVENT),  RSYS_NAME(KEVENT)       },
1.45      pooka     189:        { DUALCALL_STAT,        S(REALSTAT),    RSYS_NAME(STAT)         },
                    190:        { DUALCALL_LSTAT,       S(REALLSTAT),   RSYS_NAME(LSTAT)        },
                    191:        { DUALCALL_FSTAT,       S(REALFSTAT),   RSYS_NAME(FSTAT)        },
                    192:        { DUALCALL_CHOWN,       "chown",        RSYS_NAME(CHOWN)        },
                    193:        { DUALCALL_LCHOWN,      "lchown",       RSYS_NAME(LCHOWN)       },
                    194:        { DUALCALL_FCHOWN,      "fchown",       RSYS_NAME(FCHOWN)       },
                    195:        { DUALCALL_CHMOD,       "chmod",        RSYS_NAME(CHMOD)        },
                    196:        { DUALCALL_LCHMOD,      "lchmod",       RSYS_NAME(LCHMOD)       },
                    197:        { DUALCALL_FCHMOD,      "fchmod",       RSYS_NAME(FCHMOD)       },
                    198:        { DUALCALL_UTIMES,      S(REALUTIMES),  RSYS_NAME(UTIMES)       },
                    199:        { DUALCALL_LUTIMES,     S(REALLUTIMES), RSYS_NAME(LUTIMES)      },
                    200:        { DUALCALL_FUTIMES,     S(REALFUTIMES), RSYS_NAME(FUTIMES)      },
                    201:        { DUALCALL_OPEN,        "open",         RSYS_NAME(OPEN)         },
                    202:        { DUALCALL_STATVFS1,    "statvfs1",     RSYS_NAME(STATVFS1)     },
                    203:        { DUALCALL_FSTATVFS1,   "fstatvfs1",    RSYS_NAME(FSTATVFS1)    },
                    204:        { DUALCALL_CHDIR,       "chdir",        RSYS_NAME(CHDIR)        },
                    205:        { DUALCALL_FCHDIR,      "fchdir",       RSYS_NAME(FCHDIR)       },
1.61      pooka     206:        { DUALCALL_LSEEK,       "lseek",        RSYS_NAME(LSEEK)        },
1.45      pooka     207:        { DUALCALL_GETDENTS,    "__getdents30", RSYS_NAME(GETDENTS)     },
                    208:        { DUALCALL_UNLINK,      "unlink",       RSYS_NAME(UNLINK)       },
                    209:        { DUALCALL_SYMLINK,     "symlink",      RSYS_NAME(SYMLINK)      },
                    210:        { DUALCALL_READLINK,    "readlink",     RSYS_NAME(READLINK)     },
                    211:        { DUALCALL_RENAME,      "rename",       RSYS_NAME(RENAME)       },
                    212:        { DUALCALL_MKDIR,       "mkdir",        RSYS_NAME(MKDIR)        },
                    213:        { DUALCALL_RMDIR,       "rmdir",        RSYS_NAME(RMDIR)        },
                    214:        { DUALCALL_TRUNCATE,    "truncate",     RSYS_NAME(TRUNCATE)     },
                    215:        { DUALCALL_FTRUNCATE,   "ftruncate",    RSYS_NAME(FTRUNCATE)    },
                    216:        { DUALCALL_FSYNC,       "fsync",        RSYS_NAME(FSYNC)        },
                    217:        { DUALCALL_FSYNC_RANGE, "fsync_range",  RSYS_NAME(FSYNC_RANGE)  },
1.48      pooka     218:        { DUALCALL_MOUNT,       S(REALMOUNT),   RSYS_NAME(MOUNT)        },
                    219:        { DUALCALL_UNMOUNT,     "unmount",      RSYS_NAME(UNMOUNT)      },
1.57      pooka     220:        { DUALCALL___GETCWD,    "__getcwd",     RSYS_NAME(__GETCWD)     },
1.60      pooka     221:        { DUALCALL_CHFLAGS,     "chflags",      RSYS_NAME(CHFLAGS)      },
                    222:        { DUALCALL_LCHFLAGS,    "lchflags",     RSYS_NAME(LCHFLAGS)     },
                    223:        { DUALCALL_FCHFLAGS,    "fchflags",     RSYS_NAME(FCHFLAGS)     },
1.65      pooka     224:        { DUALCALL_ACCESS,      "access",       RSYS_NAME(ACCESS)       },
1.68      pooka     225:        { DUALCALL_MKNOD,       S(REALMKNOD),   RSYS_NAME(MKNOD)        },
1.17      pooka     226: };
                    227: #undef S
                    228:
                    229: struct bothsys {
                    230:        void *bs_host;
                    231:        void *bs_rump;
                    232: } syscalls[DUALCALL__NUM];
                    233: #define GETSYSCALL(which, name) syscalls[DUALCALL_##name].bs_##which
                    234:
1.25      pooka     235: pid_t  (*host_fork)(void);
                    236: int    (*host_daemon)(int, int);
1.39      pooka     237: int    (*host_execve)(const char *, char *const[], char *const[]);
1.62      pooka     238: void * (*host_mmap)(void *, size_t, int, int, int, off_t);
1.17      pooka     239:
1.47      pooka     240: /* ok, we need *two* bits per dup2'd fd to track fd+HIJACKOFF aliases */
1.40      pooka     241: static uint32_t dup2mask;
1.47      pooka     242: #define ISDUP2D(fd) (((fd) < 16) && (1<<(fd) & dup2mask))
1.40      pooka     243: #define SETDUP2(fd) \
1.47      pooka     244:     do { if ((fd) < 16) dup2mask |= (1<<(fd)); } while (/*CONSTCOND*/0)
1.40      pooka     245: #define CLRDUP2(fd) \
1.47      pooka     246:     do { if ((fd) < 16) dup2mask &= ~(1<<(fd)); } while (/*CONSTCOND*/0)
                    247: #define ISDUP2ALIAS(fd) (((fd) < 16) && (1<<((fd)+16) & dup2mask))
                    248: #define SETDUP2ALIAS(fd) \
                    249:     do { if ((fd) < 16) dup2mask |= (1<<((fd)+16)); } while (/*CONSTCOND*/0)
                    250: #define CLRDUP2ALIAS(fd) \
                    251:     do { if ((fd) < 16) dup2mask &= ~(1<<((fd)+16)); } while (/*CONSTCOND*/0)
1.17      pooka     252:
                    253: //#define DEBUGJACK
                    254: #ifdef DEBUGJACK
                    255: #define DPRINTF(x) mydprintf x
                    256: static void
                    257: mydprintf(const char *fmt, ...)
                    258: {
                    259:        va_list ap;
                    260:
                    261:        if (ISDUP2D(STDERR_FILENO))
                    262:                return;
                    263:
                    264:        va_start(ap, fmt);
                    265:        vfprintf(stderr, fmt, ap);
                    266:        va_end(ap);
                    267: }
                    268:
                    269: #else
                    270: #define DPRINTF(x)
1.14      pooka     271: #endif
                    272:
1.17      pooka     273: #define FDCALL(type, name, rcname, args, proto, vars)                  \
                    274: type name args                                                         \
                    275: {                                                                      \
                    276:        type (*fun) proto;                                              \
                    277:                                                                        \
1.33      pooka     278:        DPRINTF(("%s -> %d\n", __STRING(name), fd));                    \
1.17      pooka     279:        if (fd_isrump(fd)) {                                            \
                    280:                fun = syscalls[rcname].bs_rump;                         \
                    281:                fd = fd_host2rump(fd);                                  \
                    282:        } else {                                                        \
                    283:                fun = syscalls[rcname].bs_host;                         \
                    284:        }                                                               \
                    285:                                                                        \
                    286:        return fun vars;                                                \
                    287: }
                    288:
1.45      pooka     289: #define PATHCALL(type, name, rcname, args, proto, vars)                        \
                    290: type name args                                                         \
                    291: {                                                                      \
                    292:        type (*fun) proto;                                              \
                    293:                                                                        \
                    294:        DPRINTF(("%s -> %s\n", __STRING(name), path));                  \
                    295:        if (path_isrump(path)) {                                        \
                    296:                fun = syscalls[rcname].bs_rump;                         \
                    297:                path = path_host2rump(path);                            \
                    298:        } else {                                                        \
                    299:                fun = syscalls[rcname].bs_host;                         \
                    300:        }                                                               \
                    301:                                                                        \
                    302:        return fun vars;                                                \
                    303: }
                    304:
1.14      pooka     305: /*
1.49      pooka     306:  * This tracks if our process is in a subdirectory of /rump.
                    307:  * It's preserved over exec.
                    308:  */
                    309: static bool pwdinrump = false;
                    310:
                    311: /*
                    312:  * These variables are set from the RUMPHIJACK string and control
                    313:  * which operations can product rump kernel file descriptors.
                    314:  * This should be easily extendable for future needs.
                    315:  */
                    316: #define RUMPHIJACK_DEFAULT "path=/rump,socket=all:nolocal"
                    317: static bool rumpsockets[PF_MAX];
                    318: static const char *rumpprefix;
                    319: static size_t rumpprefixlen;
                    320:
                    321: static struct {
                    322:        int pf;
                    323:        const char *name;
                    324: } socketmap[] = {
1.51      pooka     325:        { PF_LOCAL, "local" },
1.49      pooka     326:        { PF_INET, "inet" },
                    327:        { PF_LINK, "link" },
1.55      pooka     328: #ifdef PF_OROUTE
1.56      pooka     329:        { PF_OROUTE, "oroute" },
                    330: #endif
1.49      pooka     331:        { PF_ROUTE, "route" },
                    332:        { PF_INET6, "inet6" },
1.55      pooka     333: #ifdef PF_MPLS
                    334:        { PF_MPLS, "mpls" },
                    335: #endif
1.49      pooka     336:        { -1, NULL }
                    337: };
                    338:
                    339: static void
                    340: sockparser(char *buf)
                    341: {
                    342:        char *p, *l;
                    343:        bool value;
                    344:        int i;
                    345:
                    346:        /* if "all" is present, it must be specified first */
                    347:        if (strncmp(buf, "all", strlen("all")) == 0) {
1.50      pooka     348:                for (i = 0; i < (int)__arraycount(rumpsockets); i++) {
1.49      pooka     349:                        rumpsockets[i] = true;
                    350:                }
                    351:                buf += strlen("all");
                    352:                if (*buf == ':')
                    353:                        buf++;
                    354:        }
                    355:
                    356:        for (p = strtok_r(buf, ":", &l); p; p = strtok_r(NULL, ":", &l)) {
                    357:                value = true;
                    358:                if (strncmp(p, "no", strlen("no")) == 0) {
                    359:                        value = false;
                    360:                        p += strlen("no");
                    361:                }
1.45      pooka     362:
1.49      pooka     363:                for (i = 0; socketmap[i].name; i++) {
                    364:                        if (strcmp(p, socketmap[i].name) == 0) {
                    365:                                rumpsockets[socketmap[i].pf] = value;
                    366:                                break;
                    367:                        }
                    368:                }
                    369:                if (socketmap[i].name == NULL) {
                    370:                        warnx("invalid socket specifier %s", p);
                    371:                }
                    372:        }
                    373: }
                    374:
                    375: static void
                    376: pathparser(char *buf)
                    377: {
                    378:
1.57      pooka     379:        /* sanity-check */
1.49      pooka     380:        if (*buf != '/')
                    381:                errx(1, "hijack path specifier must begin with ``/''");
1.57      pooka     382:        rumpprefixlen = strlen(buf);
                    383:        if (rumpprefixlen < 2)
                    384:                errx(1, "invalid hijack prefix: %s", buf);
                    385:        if (buf[rumpprefixlen-1] == '/' && strspn(buf, "/") != rumpprefixlen)
                    386:                errx(1, "hijack prefix may end in slash only if pure "
                    387:                    "slash, gave %s", buf);
1.49      pooka     388:
                    389:        if ((rumpprefix = strdup(buf)) == NULL)
                    390:                err(1, "strdup");
                    391:        rumpprefixlen = strlen(rumpprefix);
                    392: }
                    393:
                    394: static struct {
                    395:        void (*parsefn)(char *);
                    396:        const char *name;
                    397: } hijackparse[] = {
                    398:        { sockparser, "socket" },
                    399:        { pathparser, "path" },
                    400:        { NULL, NULL },
                    401: };
                    402:
                    403: static void
                    404: parsehijack(char *hijack)
                    405: {
                    406:        char *p, *p2, *l;
                    407:        const char *hijackcopy;
                    408:        int i;
                    409:
                    410:        if ((hijackcopy = strdup(hijack)) == NULL)
                    411:                err(1, "strdup");
                    412:
                    413:        /* disable everything explicitly */
                    414:        for (i = 0; i < PF_MAX; i++)
                    415:                rumpsockets[i] = false;
                    416:
                    417:        for (p = strtok_r(hijack, ",", &l); p; p = strtok_r(NULL, ",", &l)) {
                    418:                p2 = strchr(p, '=');
                    419:                if (!p2)
                    420:                        errx(1, "invalid hijack specifier: %s", hijackcopy);
                    421:
                    422:                for (i = 0; hijackparse[i].parsefn; i++) {
                    423:                        if (strncmp(hijackparse[i].name, p,
                    424:                            (size_t)(p2-p)) == 0) {
                    425:                                hijackparse[i].parsefn(p2+1);
                    426:                                break;
                    427:                        }
                    428:                }
                    429:        }
                    430:
                    431: }
1.7       pooka     432:
1.1       pooka     433: static void __attribute__((constructor))
                    434: rcinit(void)
                    435: {
1.49      pooka     436:        char buf[1024];
1.19      pooka     437:        unsigned i, j;
1.1       pooka     438:
1.17      pooka     439:        host_fork = dlsym(RTLD_NEXT, "fork");
1.25      pooka     440:        host_daemon = dlsym(RTLD_NEXT, "daemon");
1.39      pooka     441:        host_execve = dlsym(RTLD_NEXT, "execve");
1.62      pooka     442:        host_mmap = dlsym(RTLD_NEXT, "mmap");
1.17      pooka     443:
                    444:        /*
                    445:         * In theory cannot print anything during lookups because
                    446:         * we might not have the call vector set up.  so, the errx()
                    447:         * is a bit of a strech, but it might work.
                    448:         */
1.1       pooka     449:
1.17      pooka     450:        for (i = 0; i < DUALCALL__NUM; i++) {
                    451:                /* build runtime O(1) access */
                    452:                for (j = 0; j < __arraycount(syscnames); j++) {
                    453:                        if (syscnames[j].scm_callnum == i)
                    454:                                break;
                    455:                }
                    456:
                    457:                if (j == __arraycount(syscnames))
                    458:                        errx(1, "rumphijack error: syscall pos %d missing", i);
                    459:
1.23      pooka     460:                syscalls[i].bs_host = dlsym(RTLD_NEXT,
                    461:                    syscnames[j].scm_hostname);
1.17      pooka     462:                if (syscalls[i].bs_host == NULL)
                    463:                        errx(1, "hostcall %s not found missing",
                    464:                            syscnames[j].scm_hostname);
                    465:
1.23      pooka     466:                syscalls[i].bs_rump = dlsym(RTLD_NEXT,
                    467:                    syscnames[j].scm_rumpname);
1.17      pooka     468:                if (syscalls[i].bs_rump == NULL)
                    469:                        errx(1, "rumpcall %s not found missing",
                    470:                            syscnames[j].scm_rumpname);
1.1       pooka     471:        }
                    472:
1.22      pooka     473:        if (rumpclient_init() == -1)
1.1       pooka     474:                err(1, "rumpclient init");
1.28      pooka     475:
1.49      pooka     476:        /* check which syscalls we're supposed to hijack */
                    477:        if (getenv_r("RUMPHIJACK", buf, sizeof(buf)) == -1) {
                    478:                strcpy(buf, RUMPHIJACK_DEFAULT);
                    479:        }
                    480:        parsehijack(buf);
                    481:
1.28      pooka     482:        /* set client persistence level */
1.44      pooka     483:        if (getenv_r("RUMPHIJACK_RETRYCONNECT", buf, sizeof(buf)) != -1) {
1.28      pooka     484:                if (strcmp(buf, "die") == 0)
                    485:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_DIE);
                    486:                else if (strcmp(buf, "inftime") == 0)
                    487:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_INFTIME);
                    488:                else if (strcmp(buf, "once") == 0)
                    489:                        rumpclient_setconnretry(RUMPCLIENT_RETRYCONN_ONCE);
                    490:                else {
                    491:                        time_t timeout;
1.44      pooka     492:                        char *ep;
1.28      pooka     493:
1.44      pooka     494:                        timeout = (time_t)strtoll(buf, &ep, 10);
                    495:                        if (timeout <= 0 || ep != buf + strlen(buf))
                    496:                                errx(1, "RUMPHIJACK_RETRYCONNECT must be "
                    497:                                    "keyword or integer, got: %s", buf);
1.28      pooka     498:
                    499:                        rumpclient_setconnretry(timeout);
                    500:                }
                    501:        }
1.39      pooka     502:
                    503:        if (getenv_r("RUMPHIJACK__DUP2MASK", buf, sizeof(buf)) == 0) {
1.40      pooka     504:                dup2mask = strtoul(buf, NULL, 10);
1.45      pooka     505:                unsetenv("RUMPHIJACK__DUP2MASK");
                    506:        }
                    507:        if (getenv_r("RUMPHIJACK__PWDINRUMP", buf, sizeof(buf)) == 0) {
1.49      pooka     508:                pwdinrump = true;
1.45      pooka     509:                unsetenv("RUMPHIJACK__PWDINRUMP");
1.39      pooka     510:        }
1.1       pooka     511: }
                    512:
1.2       pooka     513: /* XXX: need runtime selection.  low for now due to FD_SETSIZE */
                    514: #define HIJACK_FDOFF 128
                    515: static int
                    516: fd_rump2host(int fd)
                    517: {
                    518:
                    519:        if (fd == -1)
                    520:                return fd;
                    521:
                    522:        if (!ISDUP2D(fd))
                    523:                fd += HIJACK_FDOFF;
                    524:
                    525:        return fd;
                    526: }
                    527:
                    528: static int
                    529: fd_host2rump(int fd)
                    530: {
                    531:
                    532:        if (!ISDUP2D(fd))
                    533:                fd -= HIJACK_FDOFF;
                    534:        return fd;
                    535: }
                    536:
                    537: static bool
                    538: fd_isrump(int fd)
                    539: {
                    540:
                    541:        return ISDUP2D(fd) || fd >= HIJACK_FDOFF;
                    542: }
                    543:
1.40      pooka     544: #define assertfd(_fd_) assert(ISDUP2D(_fd_) || (_fd_) >= HIJACK_FDOFF)
                    545:
1.49      pooka     546: static bool
1.45      pooka     547: path_isrump(const char *path)
                    548: {
                    549:
1.49      pooka     550:        if (rumpprefix == NULL)
                    551:                return false;
                    552:
1.45      pooka     553:        if (*path == '/') {
1.49      pooka     554:                if (strncmp(path, rumpprefix, rumpprefixlen) == 0)
                    555:                        return true;
                    556:                return false;
1.45      pooka     557:        } else {
                    558:                return pwdinrump;
                    559:        }
                    560: }
                    561:
                    562: static const char *rootpath = "/";
                    563: static const char *
                    564: path_host2rump(const char *path)
                    565: {
                    566:        const char *rv;
                    567:
                    568:        if (*path == '/') {
1.49      pooka     569:                rv = path + rumpprefixlen;
1.45      pooka     570:                if (*rv == '\0')
                    571:                        rv = rootpath;
                    572:        } else {
                    573:                rv = path;
                    574:        }
                    575:
                    576:        return rv;
                    577: }
                    578:
1.40      pooka     579: static int
                    580: dodup(int oldd, int minfd)
                    581: {
                    582:        int (*op_fcntl)(int, int, ...);
                    583:        int newd;
                    584:        int isrump;
                    585:
                    586:        DPRINTF(("dup -> %d (minfd %d)\n", oldd, minfd));
                    587:        if (fd_isrump(oldd)) {
                    588:                op_fcntl = GETSYSCALL(rump, FCNTL);
                    589:                oldd = fd_host2rump(oldd);
1.63      pooka     590:                if (minfd >= HIJACK_FDOFF)
                    591:                        minfd -= HIJACK_FDOFF;
1.40      pooka     592:                isrump = 1;
                    593:        } else {
                    594:                op_fcntl = GETSYSCALL(host, FCNTL);
                    595:                isrump = 0;
                    596:        }
                    597:
                    598:        newd = op_fcntl(oldd, F_DUPFD, minfd);
                    599:
                    600:        if (isrump)
                    601:                newd = fd_rump2host(newd);
                    602:        DPRINTF(("dup <- %d\n", newd));
                    603:
                    604:        return newd;
                    605: }
1.2       pooka     606:
1.47      pooka     607: /*
                    608:  * dup a host file descriptor so that it doesn't collide with the dup2mask
                    609:  */
                    610: static int
                    611: fd_dupgood(int fd)
                    612: {
                    613:        int (*op_fcntl)(int, int, ...) = GETSYSCALL(host, FCNTL);
                    614:        int (*op_close)(int) = GETSYSCALL(host, CLOSE);
                    615:        int ofd, i;
                    616:
                    617:        for (i = 1; ISDUP2D(fd); i++) {
                    618:                ofd = fd;
                    619:                fd = op_fcntl(ofd, F_DUPFD, i);
                    620:                op_close(ofd);
                    621:        }
                    622:
                    623:        return fd;
                    624: }
                    625:
1.45      pooka     626: int
                    627: open(const char *path, int flags, ...)
                    628: {
                    629:        int (*op_open)(const char *, int, ...);
                    630:        bool isrump;
                    631:        va_list ap;
                    632:        int fd;
                    633:
                    634:        if (path_isrump(path)) {
                    635:                path = path_host2rump(path);
                    636:                op_open = GETSYSCALL(rump, OPEN);
                    637:                isrump = true;
                    638:        } else {
                    639:                op_open = GETSYSCALL(host, OPEN);
                    640:                isrump = false;
                    641:        }
                    642:
                    643:        va_start(ap, flags);
                    644:        fd = op_open(path, flags, va_arg(ap, mode_t));
                    645:        va_end(ap);
                    646:
                    647:        if (isrump)
                    648:                fd = fd_rump2host(fd);
1.47      pooka     649:        else
                    650:                fd = fd_dupgood(fd);
1.45      pooka     651:        return fd;
                    652: }
                    653:
                    654: int
                    655: chdir(const char *path)
                    656: {
                    657:        int (*op_chdir)(const char *);
                    658:        bool isrump;
                    659:        int rv;
                    660:
                    661:        if (path_isrump(path)) {
                    662:                op_chdir = GETSYSCALL(rump, CHDIR);
                    663:                isrump = true;
                    664:                path = path_host2rump(path);
                    665:        } else {
                    666:                op_chdir = GETSYSCALL(host, CHDIR);
                    667:                isrump = false;
                    668:        }
                    669:
                    670:        rv = op_chdir(path);
                    671:        if (rv == 0) {
                    672:                if (isrump)
                    673:                        pwdinrump = true;
                    674:                else
                    675:                        pwdinrump = false;
                    676:        }
                    677:
                    678:        return rv;
                    679: }
                    680:
                    681: int
                    682: fchdir(int fd)
                    683: {
                    684:        int (*op_fchdir)(int);
                    685:        bool isrump;
                    686:        int rv;
                    687:
                    688:        if (fd_isrump(fd)) {
                    689:                op_fchdir = GETSYSCALL(rump, FCHDIR);
                    690:                isrump = true;
                    691:                fd = fd_host2rump(fd);
                    692:        } else {
                    693:                op_fchdir = GETSYSCALL(host, FCHDIR);
                    694:                isrump = false;
                    695:        }
                    696:
                    697:        rv = op_fchdir(fd);
                    698:        if (rv == 0) {
                    699:                if (isrump)
                    700:                        pwdinrump = true;
                    701:                else
                    702:                        pwdinrump = false;
                    703:        }
                    704:
                    705:        return rv;
                    706: }
                    707:
1.52      pooka     708: int
1.57      pooka     709: __getcwd(char *bufp, size_t len)
                    710: {
                    711:        int (*op___getcwd)(char *, size_t);
                    712:        int rv;
                    713:
                    714:        if (pwdinrump) {
                    715:                size_t prefixgap;
                    716:                bool iamslash;
                    717:
                    718:                if (rumpprefix[rumpprefixlen-1] == '/')
                    719:                        iamslash = true;
                    720:                else
                    721:                        iamslash = false;
                    722:
                    723:                if (iamslash)
                    724:                        prefixgap = rumpprefixlen - 1; /* ``//+path'' */
                    725:                else
                    726:                        prefixgap = rumpprefixlen; /* ``/pfx+/path'' */
                    727:                if (len <= prefixgap) {
1.66      pooka     728:                        errno = ERANGE;
                    729:                        return -1;
1.57      pooka     730:                }
                    731:
                    732:                op___getcwd = GETSYSCALL(rump, __GETCWD);
                    733:                rv = op___getcwd(bufp + prefixgap, len - prefixgap);
                    734:                if (rv == -1)
                    735:                        return rv;
                    736:
                    737:                /* augment the "/" part only for a non-root path */
                    738:                memcpy(bufp, rumpprefix, rumpprefixlen);
                    739:
                    740:                /* append / only to non-root cwd */
                    741:                if (rv != 2)
                    742:                        bufp[prefixgap] = '/';
                    743:
                    744:                /* don't append extra slash in the purely-slash case */
                    745:                if (rv == 2 && !iamslash)
                    746:                        bufp[rumpprefixlen] = '\0';
                    747:
                    748:                return rv;
                    749:        } else {
                    750:                op___getcwd = GETSYSCALL(host, __GETCWD);
                    751:                return op___getcwd(bufp, len);
                    752:        }
                    753: }
                    754:
                    755: int
1.52      pooka     756: rename(const char *from, const char *to)
                    757: {
                    758:        int (*op_rename)(const char *, const char *);
                    759:
                    760:        if (path_isrump(from)) {
1.66      pooka     761:                if (!path_isrump(to)) {
                    762:                        errno = EXDEV;
                    763:                        return -1;
                    764:                }
1.52      pooka     765:
                    766:                from = path_host2rump(from);
                    767:                to = path_host2rump(to);
                    768:                op_rename = GETSYSCALL(rump, RENAME);
                    769:        } else {
1.66      pooka     770:                if (path_isrump(to)) {
                    771:                        errno = EXDEV;
                    772:                        return -1;
                    773:                }
1.53      pooka     774:
1.52      pooka     775:                op_rename = GETSYSCALL(host, RENAME);
                    776:        }
                    777:
                    778:        return op_rename(from, to);
                    779: }
                    780:
1.1       pooka     781: int __socket30(int, int, int);
                    782: int
                    783: __socket30(int domain, int type, int protocol)
                    784: {
1.17      pooka     785:        int (*op_socket)(int, int, int);
1.1       pooka     786:        int fd;
1.49      pooka     787:        bool isrump;
1.7       pooka     788:
1.49      pooka     789:        isrump = domain < PF_MAX && rumpsockets[domain];
1.1       pooka     790:
1.49      pooka     791:        if (isrump)
                    792:                op_socket = GETSYSCALL(rump, SOCKET);
                    793:        else
1.17      pooka     794:                op_socket = GETSYSCALL(host, SOCKET);
                    795:        fd = op_socket(domain, type, protocol);
1.2       pooka     796:
1.49      pooka     797:        if (isrump)
1.7       pooka     798:                fd = fd_rump2host(fd);
1.47      pooka     799:        else
                    800:                fd = fd_dupgood(fd);
1.7       pooka     801:        DPRINTF(("socket <- %d\n", fd));
1.2       pooka     802:
1.7       pooka     803:        return fd;
1.1       pooka     804: }
                    805:
                    806: int
                    807: accept(int s, struct sockaddr *addr, socklen_t *addrlen)
                    808: {
1.17      pooka     809:        int (*op_accept)(int, struct sockaddr *, socklen_t *);
1.1       pooka     810:        int fd;
1.7       pooka     811:        bool isrump;
                    812:
                    813:        isrump = fd_isrump(s);
1.1       pooka     814:
1.2       pooka     815:        DPRINTF(("accept -> %d", s));
1.7       pooka     816:        if (isrump) {
1.17      pooka     817:                op_accept = GETSYSCALL(rump, ACCEPT);
1.7       pooka     818:                s = fd_host2rump(s);
                    819:        } else {
1.17      pooka     820:                op_accept = GETSYSCALL(host, ACCEPT);
1.7       pooka     821:        }
1.17      pooka     822:        fd = op_accept(s, addr, addrlen);
1.7       pooka     823:        if (fd != -1 && isrump)
                    824:                fd = fd_rump2host(fd);
1.47      pooka     825:        else
                    826:                fd = fd_dupgood(fd);
1.7       pooka     827:
                    828:        DPRINTF((" <- %d\n", fd));
1.2       pooka     829:
1.7       pooka     830:        return fd;
1.1       pooka     831: }
                    832:
1.17      pooka     833: /*
                    834:  * ioctl and fcntl are varargs calls and need special treatment
                    835:  */
1.1       pooka     836: int
1.17      pooka     837: ioctl(int fd, unsigned long cmd, ...)
1.1       pooka     838: {
1.17      pooka     839:        int (*op_ioctl)(int, unsigned long cmd, ...);
                    840:        va_list ap;
                    841:        int rv;
1.1       pooka     842:
1.17      pooka     843:        DPRINTF(("ioctl -> %d\n", fd));
                    844:        if (fd_isrump(fd)) {
                    845:                fd = fd_host2rump(fd);
                    846:                op_ioctl = GETSYSCALL(rump, IOCTL);
1.7       pooka     847:        } else {
1.17      pooka     848:                op_ioctl = GETSYSCALL(host, IOCTL);
1.7       pooka     849:        }
1.1       pooka     850:
1.17      pooka     851:        va_start(ap, cmd);
                    852:        rv = op_ioctl(fd, cmd, va_arg(ap, void *));
                    853:        va_end(ap);
                    854:        return rv;
1.1       pooka     855: }
                    856:
1.40      pooka     857: #include <syslog.h>
1.1       pooka     858: int
1.17      pooka     859: fcntl(int fd, int cmd, ...)
1.1       pooka     860: {
1.17      pooka     861:        int (*op_fcntl)(int, int, ...);
                    862:        va_list ap;
1.40      pooka     863:        int rv, minfd, i;
                    864:
                    865:        DPRINTF(("fcntl -> %d (cmd %d)\n", fd, cmd));
                    866:
                    867:        switch (cmd) {
                    868:        case F_DUPFD:
                    869:                va_start(ap, cmd);
                    870:                minfd = va_arg(ap, int);
                    871:                va_end(ap);
                    872:                return dodup(fd, minfd);
                    873:
                    874:        case F_CLOSEM:
                    875:                /*
                    876:                 * So, if fd < HIJACKOFF, we want to do a host closem.
                    877:                 */
                    878:
                    879:                if (fd < HIJACK_FDOFF) {
                    880:                        int closemfd = fd;
1.1       pooka     881:
1.40      pooka     882:                        if (rumpclient__closenotify(&closemfd,
1.39      pooka     883:                            RUMPCLIENT_CLOSE_FCLOSEM) == -1)
                    884:                                return -1;
1.40      pooka     885:                        op_fcntl = GETSYSCALL(host, FCNTL);
                    886:                        rv = op_fcntl(closemfd, cmd);
                    887:                        if (rv)
                    888:                                return rv;
                    889:                }
                    890:
                    891:                /*
                    892:                 * Additionally, we want to do a rump closem, but only
                    893:                 * for the file descriptors not within the dup2mask.
                    894:                 */
                    895:
                    896:                /* why don't we offer fls()? */
1.47      pooka     897:                for (i = 15; i >= 0; i--) {
                    898:                        if (ISDUP2D(i))
1.40      pooka     899:                                break;
                    900:                }
                    901:
                    902:                if (fd >= HIJACK_FDOFF)
                    903:                        fd -= HIJACK_FDOFF;
                    904:                else
                    905:                        fd = 0;
                    906:                fd = MAX(i+1, fd);
                    907:
                    908:                /* hmm, maybe we should close rump fd's not within dup2mask? */
                    909:
                    910:                return rump_sys_fcntl(fd, F_CLOSEM);
                    911:
                    912:        case F_MAXFD:
                    913:                /*
                    914:                 * For maxfd, if there's a rump kernel fd, return
                    915:                 * it hostified.  Otherwise, return host's MAXFD
                    916:                 * return value.
                    917:                 */
                    918:                if ((rv = rump_sys_fcntl(fd, F_MAXFD)) != -1) {
                    919:                        /*
                    920:                         * This might go a little wrong in case
                    921:                         * of dup2 to [012], but I'm not sure if
                    922:                         * there's a justification for tracking
                    923:                         * that info.  Consider e.g.
                    924:                         * dup2(rumpfd, 2) followed by rump_sys_open()
                    925:                         * returning 1.  We should return 1+HIJACKOFF,
                    926:                         * not 2+HIJACKOFF.  However, if [01] is not
                    927:                         * open, the correct return value is 2.
                    928:                         */
                    929:                        return fd_rump2host(fd);
                    930:                } else {
                    931:                        op_fcntl = GETSYSCALL(host, FCNTL);
                    932:                        return op_fcntl(fd, F_MAXFD);
                    933:                }
                    934:                /*NOTREACHED*/
                    935:
                    936:        default:
                    937:                if (fd_isrump(fd)) {
                    938:                        fd = fd_host2rump(fd);
                    939:                        op_fcntl = GETSYSCALL(rump, FCNTL);
                    940:                } else {
                    941:                        op_fcntl = GETSYSCALL(host, FCNTL);
                    942:                }
                    943:
                    944:                va_start(ap, cmd);
                    945:                rv = op_fcntl(fd, cmd, va_arg(ap, void *));
                    946:                va_end(ap);
                    947:                return rv;
1.7       pooka     948:        }
1.40      pooka     949:        /*NOTREACHED*/
1.1       pooka     950: }
                    951:
1.39      pooka     952: int
                    953: close(int fd)
                    954: {
                    955:        int (*op_close)(int);
                    956:        int rv;
                    957:
                    958:        DPRINTF(("close -> %d\n", fd));
                    959:        if (fd_isrump(fd)) {
                    960:                int undup2 = 0;
                    961:
1.47      pooka     962:                fd = fd_host2rump(fd);
                    963:                if (ISDUP2ALIAS(fd)) {
                    964:                        _DIAGASSERT(ISDUP2D(fd));
                    965:                        CLRDUP2ALIAS(fd);
                    966:                        return 0;
                    967:                }
                    968:
1.39      pooka     969:                if (ISDUP2D(fd))
                    970:                        undup2 = 1;
                    971:                op_close = GETSYSCALL(rump, CLOSE);
                    972:                rv = op_close(fd);
                    973:                if (rv == 0 && undup2)
1.40      pooka     974:                        CLRDUP2(fd);
1.39      pooka     975:        } else {
                    976:                if (rumpclient__closenotify(&fd, RUMPCLIENT_CLOSE_CLOSE) == -1)
                    977:                        return -1;
                    978:                op_close = GETSYSCALL(host, CLOSE);
                    979:                rv = op_close(fd);
                    980:        }
                    981:
                    982:        return rv;
                    983: }
                    984:
1.17      pooka     985: /*
                    986:  * write cannot issue a standard debug printf due to recursion
                    987:  */
1.1       pooka     988: ssize_t
1.17      pooka     989: write(int fd, const void *buf, size_t blen)
1.1       pooka     990: {
1.17      pooka     991:        ssize_t (*op_write)(int, const void *, size_t);
1.1       pooka     992:
1.17      pooka     993:        if (fd_isrump(fd)) {
                    994:                fd = fd_host2rump(fd);
                    995:                op_write = GETSYSCALL(rump, WRITE);
1.16      pooka     996:        } else {
1.17      pooka     997:                op_write = GETSYSCALL(host, WRITE);
1.16      pooka     998:        }
1.1       pooka     999:
1.17      pooka    1000:        return op_write(fd, buf, blen);
1.2       pooka    1001: }
                   1002:
                   1003: /*
                   1004:  * dup2 is special.  we allow dup2 of a rump kernel fd to 0-2 since
                   1005:  * many programs do that.  dup2 of a rump kernel fd to another value
                   1006:  * not >= fdoff is an error.
                   1007:  *
                   1008:  * Note: cannot rump2host newd, because it is often hardcoded.
                   1009:  */
                   1010: int
                   1011: dup2(int oldd, int newd)
                   1012: {
1.17      pooka    1013:        int (*host_dup2)(int, int);
1.2       pooka    1014:        int rv;
                   1015:
                   1016:        DPRINTF(("dup2 -> %d (o) -> %d (n)\n", oldd, newd));
                   1017:
                   1018:        if (fd_isrump(oldd)) {
1.66      pooka    1019:                if (!(newd >= 0 && newd <= 2)) {
                   1020:                        errno = EBADF;
                   1021:                        return -1;
                   1022:                }
1.2       pooka    1023:                oldd = fd_host2rump(oldd);
1.47      pooka    1024:                if (oldd == newd) {
                   1025:                        SETDUP2(newd);
                   1026:                        SETDUP2ALIAS(newd);
                   1027:                        return newd;
                   1028:                }
1.2       pooka    1029:                rv = rump_sys_dup2(oldd, newd);
                   1030:                if (rv != -1)
1.40      pooka    1031:                        SETDUP2(newd);
1.2       pooka    1032:        } else {
1.17      pooka    1033:                host_dup2 = syscalls[DUALCALL_DUP2].bs_host;
1.39      pooka    1034:                if (rumpclient__closenotify(&newd, RUMPCLIENT_CLOSE_DUP2) == -1)
                   1035:                        return -1;
1.10      pooka    1036:                rv = host_dup2(oldd, newd);
1.2       pooka    1037:        }
1.10      pooka    1038:
                   1039:        return rv;
1.2       pooka    1040: }
                   1041:
1.34      pooka    1042: int
                   1043: dup(int oldd)
                   1044: {
                   1045:
1.40      pooka    1046:        return dodup(oldd, 0);
1.34      pooka    1047: }
                   1048:
1.2       pooka    1049: pid_t
                   1050: fork()
                   1051: {
                   1052:        pid_t rv;
                   1053:
                   1054:        DPRINTF(("fork\n"));
                   1055:
1.43      pooka    1056:        rv = rumpclient__dofork(host_fork);
1.2       pooka    1057:
                   1058:        DPRINTF(("fork returns %d\n", rv));
                   1059:        return rv;
1.1       pooka    1060: }
1.43      pooka    1061: /* we do not have the luxury of not requiring a stackframe */
                   1062: __strong_alias(__vfork14,fork);
1.1       pooka    1063:
1.25      pooka    1064: int
                   1065: daemon(int nochdir, int noclose)
                   1066: {
                   1067:        struct rumpclient_fork *rf;
                   1068:
                   1069:        if ((rf = rumpclient_prefork()) == NULL)
                   1070:                return -1;
                   1071:
                   1072:        if (host_daemon(nochdir, noclose) == -1)
                   1073:                return -1;
                   1074:
                   1075:        if (rumpclient_fork_init(rf) == -1)
                   1076:                return -1;
                   1077:
                   1078:        return 0;
                   1079: }
                   1080:
1.39      pooka    1081: int
1.42      pooka    1082: execve(const char *path, char *const argv[], char *const envp[])
1.39      pooka    1083: {
                   1084:        char buf[128];
                   1085:        char *dup2str;
1.49      pooka    1086:        const char *pwdinrumpstr;
1.42      pooka    1087:        char **newenv;
                   1088:        size_t nelem;
                   1089:        int rv, sverrno;
1.45      pooka    1090:        int bonus = 1, i = 0;
                   1091:
                   1092:        if (dup2mask) {
                   1093:                snprintf(buf, sizeof(buf), "RUMPHIJACK__DUP2MASK=%u", dup2mask);
                   1094:                dup2str = malloc(strlen(buf)+1);
1.66      pooka    1095:                if (dup2str == NULL) {
                   1096:                        errno = ENOMEM;
                   1097:                        return -1;
                   1098:                }
1.45      pooka    1099:                strcpy(dup2str, buf);
                   1100:                bonus++;
                   1101:        } else {
                   1102:                dup2str = NULL;
                   1103:        }
1.39      pooka    1104:
1.45      pooka    1105:        if (pwdinrump) {
1.49      pooka    1106:                pwdinrumpstr = "RUMPHIJACK__PWDINRUMP=true";
1.45      pooka    1107:                bonus++;
                   1108:        } else {
                   1109:                pwdinrumpstr = NULL;
                   1110:        }
1.39      pooka    1111:
1.42      pooka    1112:        for (nelem = 0; envp && envp[nelem]; nelem++)
                   1113:                continue;
1.45      pooka    1114:        newenv = malloc(sizeof(*newenv) * nelem+bonus);
1.42      pooka    1115:        if (newenv == NULL) {
1.39      pooka    1116:                free(dup2str);
1.66      pooka    1117:                errno = ENOMEM;
                   1118:                return -1;
1.39      pooka    1119:        }
1.42      pooka    1120:        memcpy(newenv, envp, nelem*sizeof(*newenv));
1.45      pooka    1121:        if (dup2str) {
                   1122:                newenv[nelem+i] = dup2str;
                   1123:                i++;
                   1124:        }
                   1125:        if (pwdinrumpstr) {
1.49      pooka    1126:                newenv[nelem+i] = __UNCONST(pwdinrumpstr);
1.45      pooka    1127:                i++;
                   1128:        }
                   1129:        newenv[nelem+i] = NULL;
                   1130:        _DIAGASSERT(i < bonus);
1.42      pooka    1131:
                   1132:        rv = rumpclient_exec(path, argv, newenv);
                   1133:
                   1134:        _DIAGASSERT(rv != 0);
                   1135:        sverrno = errno;
                   1136:        free(newenv);
                   1137:        free(dup2str);
                   1138:        errno = sverrno;
1.39      pooka    1139:        return rv;
                   1140: }
                   1141:
1.1       pooka    1142: /*
1.17      pooka    1143:  * select is done by calling poll.
1.1       pooka    1144:  */
                   1145: int
1.29      pooka    1146: REALSELECT(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
1.4       pooka    1147:        struct timeval *timeout)
1.1       pooka    1148: {
1.4       pooka    1149:        struct pollfd *pfds;
                   1150:        struct timespec ts, *tsp = NULL;
1.19      pooka    1151:        nfds_t realnfds;
                   1152:        int i, j;
1.4       pooka    1153:        int rv, incr;
                   1154:
1.7       pooka    1155:        DPRINTF(("select\n"));
                   1156:
1.4       pooka    1157:        /*
                   1158:         * Well, first we must scan the fds to figure out how many
                   1159:         * fds there really are.  This is because up to and including
1.17      pooka    1160:         * nb5 poll() silently refuses nfds > process_maxopen_fds.
1.4       pooka    1161:         * Seems to be fixed in current, thank the maker.
                   1162:         * god damn cluster...bomb.
                   1163:         */
                   1164:
                   1165:        for (i = 0, realnfds = 0; i < nfds; i++) {
                   1166:                if (readfds && FD_ISSET(i, readfds)) {
                   1167:                        realnfds++;
                   1168:                        continue;
                   1169:                }
                   1170:                if (writefds && FD_ISSET(i, writefds)) {
                   1171:                        realnfds++;
                   1172:                        continue;
                   1173:                }
                   1174:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1175:                        realnfds++;
                   1176:                        continue;
1.1       pooka    1177:                }
                   1178:        }
                   1179:
1.6       pooka    1180:        if (realnfds) {
1.38      pooka    1181:                pfds = calloc(realnfds, sizeof(*pfds));
1.6       pooka    1182:                if (!pfds)
                   1183:                        return -1;
                   1184:        } else {
                   1185:                pfds = NULL;
                   1186:        }
1.1       pooka    1187:
1.4       pooka    1188:        for (i = 0, j = 0; i < nfds; i++) {
                   1189:                incr = 0;
                   1190:                if (readfds && FD_ISSET(i, readfds)) {
                   1191:                        pfds[j].fd = i;
                   1192:                        pfds[j].events |= POLLIN;
                   1193:                        incr=1;
                   1194:                }
                   1195:                if (writefds && FD_ISSET(i, writefds)) {
                   1196:                        pfds[j].fd = i;
                   1197:                        pfds[j].events |= POLLOUT;
                   1198:                        incr=1;
                   1199:                }
                   1200:                if (exceptfds && FD_ISSET(i, exceptfds)) {
                   1201:                        pfds[j].fd = i;
                   1202:                        pfds[j].events |= POLLHUP|POLLERR;
                   1203:                        incr=1;
1.1       pooka    1204:                }
1.4       pooka    1205:                if (incr)
                   1206:                        j++;
1.1       pooka    1207:        }
1.37      pooka    1208:        assert(j == (int)realnfds);
1.1       pooka    1209:
1.4       pooka    1210:        if (timeout) {
                   1211:                TIMEVAL_TO_TIMESPEC(timeout, &ts);
                   1212:                tsp = &ts;
                   1213:        }
1.29      pooka    1214:        rv = REALPOLLTS(pfds, realnfds, tsp, NULL);
1.36      pooka    1215:        /*
                   1216:         * "If select() returns with an error the descriptor sets
                   1217:         * will be unmodified"
                   1218:         */
                   1219:        if (rv < 0)
1.4       pooka    1220:                goto out;
                   1221:
                   1222:        /*
1.36      pooka    1223:         * zero out results (can't use FD_ZERO for the
                   1224:         * obvious select-me-not reason).  whee.
                   1225:         *
                   1226:         * We do this here since some software ignores the return
                   1227:         * value of select, and hence if the timeout expires, it may
                   1228:         * assume all input descriptors have activity.
1.4       pooka    1229:         */
                   1230:        for (i = 0; i < nfds; i++) {
                   1231:                if (readfds)
                   1232:                        FD_CLR(i, readfds);
                   1233:                if (writefds)
                   1234:                        FD_CLR(i, writefds);
                   1235:                if (exceptfds)
                   1236:                        FD_CLR(i, exceptfds);
1.1       pooka    1237:        }
1.36      pooka    1238:        if (rv == 0)
                   1239:                goto out;
1.1       pooka    1240:
1.36      pooka    1241:        /*
                   1242:         * We have >0 fds with activity.  Harvest the results.
                   1243:         */
1.19      pooka    1244:        for (i = 0; i < (int)realnfds; i++) {
1.4       pooka    1245:                if (readfds) {
                   1246:                        if (pfds[i].revents & POLLIN) {
                   1247:                                FD_SET(pfds[i].fd, readfds);
                   1248:                        }
                   1249:                }
                   1250:                if (writefds) {
                   1251:                        if (pfds[i].revents & POLLOUT) {
                   1252:                                FD_SET(pfds[i].fd, writefds);
                   1253:                        }
                   1254:                }
                   1255:                if (exceptfds) {
                   1256:                        if (pfds[i].revents & (POLLHUP|POLLERR)) {
                   1257:                                FD_SET(pfds[i].fd, exceptfds);
                   1258:                        }
                   1259:                }
1.1       pooka    1260:        }
                   1261:
1.4       pooka    1262:  out:
                   1263:        free(pfds);
1.1       pooka    1264:        return rv;
                   1265: }
                   1266:
                   1267: static void
                   1268: checkpoll(struct pollfd *fds, nfds_t nfds, int *hostcall, int *rumpcall)
                   1269: {
                   1270:        nfds_t i;
                   1271:
                   1272:        for (i = 0; i < nfds; i++) {
1.12      pooka    1273:                if (fds[i].fd == -1)
                   1274:                        continue;
                   1275:
1.2       pooka    1276:                if (fd_isrump(fds[i].fd))
                   1277:                        (*rumpcall)++;
                   1278:                else
1.1       pooka    1279:                        (*hostcall)++;
                   1280:        }
                   1281: }
                   1282:
                   1283: static void
1.2       pooka    1284: adjustpoll(struct pollfd *fds, nfds_t nfds, int (*fdadj)(int))
1.1       pooka    1285: {
                   1286:        nfds_t i;
                   1287:
                   1288:        for (i = 0; i < nfds; i++) {
1.2       pooka    1289:                fds[i].fd = fdadj(fds[i].fd);
1.1       pooka    1290:        }
                   1291: }
                   1292:
                   1293: /*
                   1294:  * poll is easy as long as the call comes in the fds only in one
                   1295:  * kernel.  otherwise its quite tricky...
                   1296:  */
                   1297: struct pollarg {
                   1298:        struct pollfd *pfds;
                   1299:        nfds_t nfds;
1.3       pooka    1300:        const struct timespec *ts;
                   1301:        const sigset_t *sigmask;
1.1       pooka    1302:        int pipefd;
                   1303:        int errnum;
                   1304: };
                   1305:
                   1306: static void *
                   1307: hostpoll(void *arg)
                   1308: {
1.17      pooka    1309:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   1310:                         const sigset_t *);
1.1       pooka    1311:        struct pollarg *parg = arg;
                   1312:        intptr_t rv;
                   1313:
1.35      pooka    1314:        op_pollts = GETSYSCALL(host, POLLTS);
1.17      pooka    1315:        rv = op_pollts(parg->pfds, parg->nfds, parg->ts, parg->sigmask);
1.1       pooka    1316:        if (rv == -1)
                   1317:                parg->errnum = errno;
                   1318:        rump_sys_write(parg->pipefd, &rv, sizeof(rv));
                   1319:
                   1320:        return (void *)(intptr_t)rv;
                   1321: }
                   1322:
                   1323: int
1.29      pooka    1324: REALPOLLTS(struct pollfd *fds, nfds_t nfds, const struct timespec *ts,
1.3       pooka    1325:        const sigset_t *sigmask)
1.1       pooka    1326: {
1.3       pooka    1327:        int (*op_pollts)(struct pollfd *, nfds_t, const struct timespec *,
                   1328:                         const sigset_t *);
1.17      pooka    1329:        int (*host_close)(int);
1.1       pooka    1330:        int hostcall = 0, rumpcall = 0;
                   1331:        pthread_t pt;
                   1332:        nfds_t i;
                   1333:        int rv;
                   1334:
1.2       pooka    1335:        DPRINTF(("poll\n"));
1.1       pooka    1336:        checkpoll(fds, nfds, &hostcall, &rumpcall);
                   1337:
                   1338:        if (hostcall && rumpcall) {
                   1339:                struct pollfd *pfd_host = NULL, *pfd_rump = NULL;
                   1340:                int rpipe[2] = {-1,-1}, hpipe[2] = {-1,-1};
                   1341:                struct pollarg parg;
                   1342:                uintptr_t lrv;
                   1343:                int sverrno = 0, trv;
                   1344:
                   1345:                /*
                   1346:                 * ok, this is where it gets tricky.  We must support
                   1347:                 * this since it's a very common operation in certain
                   1348:                 * types of software (telnet, netcat, etc).  We allocate
                   1349:                 * two vectors and run two poll commands in separate
                   1350:                 * threads.  Whichever returns first "wins" and the
                   1351:                 * other kernel's fds won't show activity.
                   1352:                 */
                   1353:                rv = -1;
                   1354:
                   1355:                /* allocate full vector for O(n) joining after call */
                   1356:                pfd_host = malloc(sizeof(*pfd_host)*(nfds+1));
                   1357:                if (!pfd_host)
                   1358:                        goto out;
                   1359:                pfd_rump = malloc(sizeof(*pfd_rump)*(nfds+1));
                   1360:                if (!pfd_rump) {
                   1361:                        goto out;
                   1362:                }
                   1363:
1.59      pooka    1364:                /*
                   1365:                 * then, open two pipes, one for notifications
                   1366:                 * to each kernel.
                   1367:                 */
                   1368:                if ((rv = rump_sys_pipe(rpipe)) == -1) {
                   1369:                        sverrno = errno;
                   1370:                }
                   1371:                if (rv == 0 && (rv = pipe(hpipe)) == -1) {
                   1372:                        sverrno = errno;
                   1373:                }
                   1374:
                   1375:                /* split vectors (or signal errors) */
1.1       pooka    1376:                for (i = 0; i < nfds; i++) {
1.59      pooka    1377:                        int fd;
                   1378:
                   1379:                        fds[i].revents = 0;
1.3       pooka    1380:                        if (fds[i].fd == -1) {
                   1381:                                pfd_host[i].fd = -1;
                   1382:                                pfd_rump[i].fd = -1;
                   1383:                        } else if (fd_isrump(fds[i].fd)) {
1.2       pooka    1384:                                pfd_host[i].fd = -1;
1.59      pooka    1385:                                fd = fd_host2rump(fds[i].fd);
                   1386:                                if (fd == rpipe[0] || fd == rpipe[1]) {
                   1387:                                        fds[i].revents = POLLNVAL;
                   1388:                                        if (rv != -1)
                   1389:                                                rv++;
                   1390:                                }
                   1391:                                pfd_rump[i].fd = fd;
1.2       pooka    1392:                                pfd_rump[i].events = fds[i].events;
                   1393:                        } else {
                   1394:                                pfd_rump[i].fd = -1;
1.59      pooka    1395:                                fd = fds[i].fd;
                   1396:                                if (fd == hpipe[0] || fd == hpipe[1]) {
                   1397:                                        fds[i].revents = POLLNVAL;
                   1398:                                        if (rv != -1)
                   1399:                                                rv++;
                   1400:                                }
                   1401:                                pfd_host[i].fd = fd;
1.1       pooka    1402:                                pfd_host[i].events = fds[i].events;
                   1403:                        }
1.39      pooka    1404:                        pfd_rump[i].revents = pfd_host[i].revents = 0;
1.1       pooka    1405:                }
1.59      pooka    1406:                if (rv) {
1.1       pooka    1407:                        goto out;
1.59      pooka    1408:                }
1.1       pooka    1409:
                   1410:                pfd_host[nfds].fd = hpipe[0];
                   1411:                pfd_host[nfds].events = POLLIN;
                   1412:                pfd_rump[nfds].fd = rpipe[0];
                   1413:                pfd_rump[nfds].events = POLLIN;
                   1414:
                   1415:                /*
                   1416:                 * then, create a thread to do host part and meanwhile
                   1417:                 * do rump kernel part right here
                   1418:                 */
                   1419:
                   1420:                parg.pfds = pfd_host;
                   1421:                parg.nfds = nfds+1;
1.3       pooka    1422:                parg.ts = ts;
                   1423:                parg.sigmask = sigmask;
1.1       pooka    1424:                parg.pipefd = rpipe[1];
                   1425:                pthread_create(&pt, NULL, hostpoll, &parg);
                   1426:
1.35      pooka    1427:                op_pollts = GETSYSCALL(rump, POLLTS);
1.3       pooka    1428:                lrv = op_pollts(pfd_rump, nfds+1, ts, NULL);
1.1       pooka    1429:                sverrno = errno;
                   1430:                write(hpipe[1], &rv, sizeof(rv));
                   1431:                pthread_join(pt, (void *)&trv);
                   1432:
                   1433:                /* check who "won" and merge results */
                   1434:                if (lrv != 0 && pfd_host[nfds].revents & POLLIN) {
                   1435:                        rv = trv;
                   1436:
                   1437:                        for (i = 0; i < nfds; i++) {
                   1438:                                if (pfd_rump[i].fd != -1)
                   1439:                                        fds[i].revents = pfd_rump[i].revents;
                   1440:                        }
                   1441:                        sverrno = parg.errnum;
                   1442:                } else if (trv != 0 && pfd_rump[nfds].revents & POLLIN) {
                   1443:                        rv = trv;
                   1444:
                   1445:                        for (i = 0; i < nfds; i++) {
                   1446:                                if (pfd_host[i].fd != -1)
                   1447:                                        fds[i].revents = pfd_host[i].revents;
                   1448:                        }
                   1449:                } else {
                   1450:                        rv = 0;
                   1451:                }
                   1452:
                   1453:  out:
1.35      pooka    1454:                host_close = GETSYSCALL(host, CLOSE);
1.1       pooka    1455:                if (rpipe[0] != -1)
                   1456:                        rump_sys_close(rpipe[0]);
                   1457:                if (rpipe[1] != -1)
                   1458:                        rump_sys_close(rpipe[1]);
                   1459:                if (hpipe[0] != -1)
1.9       pooka    1460:                        host_close(hpipe[0]);
1.1       pooka    1461:                if (hpipe[1] != -1)
1.9       pooka    1462:                        host_close(hpipe[1]);
1.1       pooka    1463:                free(pfd_host);
                   1464:                free(pfd_rump);
                   1465:                errno = sverrno;
                   1466:        } else {
                   1467:                if (hostcall) {
1.35      pooka    1468:                        op_pollts = GETSYSCALL(host, POLLTS);
1.1       pooka    1469:                } else {
1.35      pooka    1470:                        op_pollts = GETSYSCALL(rump, POLLTS);
1.2       pooka    1471:                        adjustpoll(fds, nfds, fd_host2rump);
1.1       pooka    1472:                }
                   1473:
1.3       pooka    1474:                rv = op_pollts(fds, nfds, ts, sigmask);
1.1       pooka    1475:                if (rumpcall)
1.2       pooka    1476:                        adjustpoll(fds, nfds, fd_rump2host);
1.1       pooka    1477:        }
                   1478:
                   1479:        return rv;
                   1480: }
                   1481:
                   1482: int
1.24      pooka    1483: poll(struct pollfd *fds, nfds_t nfds, int timeout)
1.1       pooka    1484: {
1.3       pooka    1485:        struct timespec ts;
                   1486:        struct timespec *tsp = NULL;
                   1487:
                   1488:        if (timeout != INFTIM) {
                   1489:                ts.tv_sec = timeout / 1000;
1.11      pooka    1490:                ts.tv_nsec = (timeout % 1000) * 1000*1000;
1.3       pooka    1491:
                   1492:                tsp = &ts;
                   1493:        }
1.1       pooka    1494:
1.29      pooka    1495:        return REALPOLLTS(fds, nfds, tsp, NULL);
1.1       pooka    1496: }
1.10      pooka    1497:
                   1498: int
1.34      pooka    1499: REALKEVENT(int kq, const struct kevent *changelist, size_t nchanges,
                   1500:        struct kevent *eventlist, size_t nevents,
                   1501:        const struct timespec *timeout)
1.10      pooka    1502: {
1.34      pooka    1503:        int (*op_kevent)(int, const struct kevent *, size_t,
                   1504:                struct kevent *, size_t, const struct timespec *);
                   1505:        const struct kevent *ev;
                   1506:        size_t i;
1.10      pooka    1507:
1.34      pooka    1508:        /*
                   1509:         * Check that we don't attempt to kevent rump kernel fd's.
                   1510:         * That needs similar treatment to select/poll, but is slightly
                   1511:         * trickier since we need to manage to different kq descriptors.
                   1512:         * (TODO, in case you're wondering).
                   1513:         */
                   1514:        for (i = 0; i < nchanges; i++) {
                   1515:                ev = &changelist[i];
                   1516:                if (ev->filter == EVFILT_READ || ev->filter == EVFILT_WRITE ||
                   1517:                    ev->filter == EVFILT_VNODE) {
1.66      pooka    1518:                        if (fd_isrump((int)ev->ident)) {
                   1519:                                errno = ENOTSUP;
                   1520:                                return -1;
                   1521:                        }
1.34      pooka    1522:                }
1.27      pooka    1523:        }
1.10      pooka    1524:
1.35      pooka    1525:        op_kevent = GETSYSCALL(host, KEVENT);
1.34      pooka    1526:        return op_kevent(kq, changelist, nchanges, eventlist, nevents, timeout);
1.10      pooka    1527: }
1.17      pooka    1528:
                   1529: /*
1.62      pooka    1530:  * mmapping from a rump kernel is not supported, so disallow it.
                   1531:  */
                   1532: void *
                   1533: mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
                   1534: {
                   1535:
                   1536:        if (flags & MAP_FILE && fd_isrump(fd)) {
                   1537:                errno = ENOSYS;
                   1538:                return MAP_FAILED;
                   1539:        }
                   1540:        return host_mmap(addr, len, prot, flags, fd, offset);
                   1541: }
                   1542:
                   1543: /*
1.17      pooka    1544:  * Rest are std type calls.
                   1545:  */
                   1546:
                   1547: FDCALL(int, bind, DUALCALL_BIND,                                       \
                   1548:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   1549:        (int, const struct sockaddr *, socklen_t),                      \
                   1550:        (fd, name, namelen))
                   1551:
                   1552: FDCALL(int, connect, DUALCALL_CONNECT,                                 \
                   1553:        (int fd, const struct sockaddr *name, socklen_t namelen),       \
                   1554:        (int, const struct sockaddr *, socklen_t),                      \
                   1555:        (fd, name, namelen))
                   1556:
                   1557: FDCALL(int, getpeername, DUALCALL_GETPEERNAME,                         \
                   1558:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   1559:        (int, struct sockaddr *, socklen_t *),                          \
                   1560:        (fd, name, namelen))
                   1561:
                   1562: FDCALL(int, getsockname, DUALCALL_GETSOCKNAME,                                 \
                   1563:        (int fd, struct sockaddr *name, socklen_t *namelen),            \
                   1564:        (int, struct sockaddr *, socklen_t *),                          \
                   1565:        (fd, name, namelen))
                   1566:
                   1567: FDCALL(int, listen, DUALCALL_LISTEN,                                   \
                   1568:        (int fd, int backlog),                                          \
                   1569:        (int, int),                                                     \
                   1570:        (fd, backlog))
                   1571:
                   1572: FDCALL(ssize_t, recvfrom, DUALCALL_RECVFROM,                           \
                   1573:        (int fd, void *buf, size_t len, int flags,                      \
                   1574:            struct sockaddr *from, socklen_t *fromlen),                 \
                   1575:        (int, void *, size_t, int, struct sockaddr *, socklen_t *),     \
                   1576:        (fd, buf, len, flags, from, fromlen))
                   1577:
                   1578: FDCALL(ssize_t, sendto, DUALCALL_SENDTO,                               \
                   1579:        (int fd, const void *buf, size_t len, int flags,                \
                   1580:            const struct sockaddr *to, socklen_t tolen),                \
                   1581:        (int, const void *, size_t, int,                                \
                   1582:            const struct sockaddr *, socklen_t),                        \
                   1583:        (fd, buf, len, flags, to, tolen))
                   1584:
                   1585: FDCALL(ssize_t, recvmsg, DUALCALL_RECVMSG,                             \
                   1586:        (int fd, struct msghdr *msg, int flags),                        \
                   1587:        (int, struct msghdr *, int),                                    \
                   1588:        (fd, msg, flags))
                   1589:
                   1590: FDCALL(ssize_t, sendmsg, DUALCALL_SENDMSG,                             \
                   1591:        (int fd, const struct msghdr *msg, int flags),                  \
                   1592:        (int, const struct msghdr *, int),                              \
                   1593:        (fd, msg, flags))
                   1594:
                   1595: FDCALL(int, getsockopt, DUALCALL_GETSOCKOPT,                           \
                   1596:        (int fd, int level, int optn, void *optval, socklen_t *optlen), \
                   1597:        (int, int, int, void *, socklen_t *),                           \
                   1598:        (fd, level, optn, optval, optlen))
                   1599:
                   1600: FDCALL(int, setsockopt, DUALCALL_SETSOCKOPT,                           \
                   1601:        (int fd, int level, int optn,                                   \
                   1602:            const void *optval, socklen_t optlen),                      \
                   1603:        (int, int, int, const void *, socklen_t),                       \
                   1604:        (fd, level, optn, optval, optlen))
                   1605:
                   1606: FDCALL(int, shutdown, DUALCALL_SHUTDOWN,                               \
                   1607:        (int fd, int how),                                              \
                   1608:        (int, int),                                                     \
                   1609:        (fd, how))
                   1610:
1.21      christos 1611: #if _FORTIFY_SOURCE > 0
                   1612: #define STUB(fun) __ssp_weak_name(fun)
                   1613: ssize_t _sys_readlink(const char * __restrict, char * __restrict, size_t);
                   1614: ssize_t
                   1615: STUB(readlink)(const char * __restrict path, char * __restrict buf,
                   1616:     size_t bufsiz)
                   1617: {
                   1618:        return _sys_readlink(path, buf, bufsiz);
                   1619: }
                   1620:
                   1621: char *_sys_getcwd(char *, size_t);
                   1622: char *
                   1623: STUB(getcwd)(char *buf, size_t size)
                   1624: {
                   1625:        return _sys_getcwd(buf, size);
                   1626: }
                   1627: #else
                   1628: #define STUB(fun) fun
                   1629: #endif
                   1630:
1.31      pooka    1631: FDCALL(ssize_t, REALREAD, DUALCALL_READ,                               \
1.17      pooka    1632:        (int fd, void *buf, size_t buflen),                             \
                   1633:        (int, void *, size_t),                                          \
                   1634:        (fd, buf, buflen))
                   1635:
1.18      pooka    1636: FDCALL(ssize_t, readv, DUALCALL_READV,                                         \
1.17      pooka    1637:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   1638:        (int, const struct iovec *, int),                               \
                   1639:        (fd, iov, iovcnt))
                   1640:
1.60      pooka    1641: FDCALL(ssize_t, REALPREAD, DUALCALL_PREAD,                             \
                   1642:        (int fd, void *buf, size_t nbytes, off_t offset),               \
                   1643:        (int, void *, size_t, off_t),                                   \
                   1644:        (fd, buf, nbytes, offset))
                   1645:
                   1646: FDCALL(ssize_t, preadv, DUALCALL_PREADV,                               \
                   1647:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   1648:        (int, const struct iovec *, int, off_t),                        \
                   1649:        (fd, iov, iovcnt, offset))
                   1650:
1.17      pooka    1651: FDCALL(ssize_t, writev, DUALCALL_WRITEV,                               \
                   1652:        (int fd, const struct iovec *iov, int iovcnt),                  \
                   1653:        (int, const struct iovec *, int),                               \
                   1654:        (fd, iov, iovcnt))
1.45      pooka    1655:
1.60      pooka    1656: FDCALL(ssize_t, REALPWRITE, DUALCALL_PWRITE,                           \
                   1657:        (int fd, const void *buf, size_t nbytes, off_t offset),         \
                   1658:        (int, const void *, size_t, off_t),                             \
                   1659:        (fd, buf, nbytes, offset))
                   1660:
                   1661: FDCALL(ssize_t, pwritev, DUALCALL_PWRITEV,                             \
                   1662:        (int fd, const struct iovec *iov, int iovcnt, off_t offset),    \
                   1663:        (int, const struct iovec *, int, off_t),                        \
                   1664:        (fd, iov, iovcnt, offset))
                   1665:
1.45      pooka    1666: FDCALL(int, REALFSTAT, DUALCALL_FSTAT,                                 \
                   1667:        (int fd, struct stat *sb),                                      \
                   1668:        (int, struct stat *),                                           \
                   1669:        (fd, sb))
                   1670:
                   1671: FDCALL(int, fstatvfs1, DUALCALL_FSTATVFS1,                             \
                   1672:        (int fd, struct statvfs *buf, int flags),                       \
                   1673:        (int, struct statvfs *, int),                                   \
                   1674:        (fd, buf, flags))
                   1675:
1.61      pooka    1676: FDCALL(off_t, lseek, DUALCALL_LSEEK,                                   \
1.45      pooka    1677:        (int fd, off_t offset, int whence),                             \
                   1678:        (int, off_t, int),                                              \
                   1679:        (fd, offset, whence))
1.61      pooka    1680: __strong_alias(_lseek,lseek);
1.45      pooka    1681:
                   1682: FDCALL(int, REALGETDENTS, DUALCALL_GETDENTS,                           \
                   1683:        (int fd, char *buf, size_t nbytes),                             \
                   1684:        (int, char *, size_t),                                          \
                   1685:        (fd, buf, nbytes))
                   1686:
                   1687: FDCALL(int, fchown, DUALCALL_FCHOWN,                                   \
                   1688:        (int fd, uid_t owner, gid_t group),                             \
                   1689:        (int, uid_t, gid_t),                                            \
                   1690:        (fd, owner, group))
                   1691:
                   1692: FDCALL(int, fchmod, DUALCALL_FCHMOD,                                   \
                   1693:        (int fd, mode_t mode),                                          \
                   1694:        (int, mode_t),                                                  \
                   1695:        (fd, mode))
                   1696:
                   1697: FDCALL(int, ftruncate, DUALCALL_FTRUNCATE,                             \
                   1698:        (int fd, off_t length),                                         \
                   1699:        (int, off_t),                                                   \
                   1700:        (fd, length))
                   1701:
                   1702: FDCALL(int, fsync, DUALCALL_FSYNC,                                     \
                   1703:        (int fd),                                                       \
                   1704:        (int),                                                          \
                   1705:        (fd))
                   1706:
                   1707: FDCALL(int, fsync_range, DUALCALL_FSYNC_RANGE,                         \
                   1708:        (int fd, int how, off_t start, off_t length),                   \
                   1709:        (int, int, off_t, off_t),                                       \
                   1710:        (fd, how, start, length))
                   1711:
                   1712: FDCALL(int, futimes, DUALCALL_FUTIMES,                                 \
                   1713:        (int fd, const struct timeval *tv),                             \
                   1714:        (int, const struct timeval *),                                  \
                   1715:        (fd, tv))
                   1716:
1.60      pooka    1717: FDCALL(int, fchflags, DUALCALL_FCHFLAGS,                               \
                   1718:        (int fd, u_long flags),                                         \
                   1719:        (int, u_long),                                                  \
                   1720:        (fd, flags))
                   1721:
1.45      pooka    1722: /*
                   1723:  * path-based selectors
                   1724:  */
                   1725:
                   1726: PATHCALL(int, REALSTAT, DUALCALL_STAT,                                 \
                   1727:        (const char *path, struct stat *sb),                            \
                   1728:        (const char *, struct stat *),                                  \
                   1729:        (path, sb))
                   1730:
                   1731: PATHCALL(int, REALLSTAT, DUALCALL_LSTAT,                               \
                   1732:        (const char *path, struct stat *sb),                            \
                   1733:        (const char *, struct stat *),                                  \
                   1734:        (path, sb))
                   1735:
                   1736: PATHCALL(int, chown, DUALCALL_CHOWN,                                   \
                   1737:        (const char *path, uid_t owner, gid_t group),                   \
                   1738:        (const char *, uid_t, gid_t),                                   \
                   1739:        (path, owner, group))
                   1740:
                   1741: PATHCALL(int, lchown, DUALCALL_LCHOWN,                                 \
                   1742:        (const char *path, uid_t owner, gid_t group),                   \
                   1743:        (const char *, uid_t, gid_t),                                   \
                   1744:        (path, owner, group))
                   1745:
                   1746: PATHCALL(int, chmod, DUALCALL_CHMOD,                                   \
                   1747:        (const char *path, mode_t mode),                                \
                   1748:        (const char *, mode_t),                                         \
                   1749:        (path, mode))
                   1750:
                   1751: PATHCALL(int, lchmod, DUALCALL_LCHMOD,                                 \
                   1752:        (const char *path, mode_t mode),                                \
                   1753:        (const char *, mode_t),                                         \
                   1754:        (path, mode))
                   1755:
                   1756: PATHCALL(int, statvfs1, DUALCALL_STATVFS1,                             \
                   1757:        (const char *path, struct statvfs *buf, int flags),             \
                   1758:        (const char *, struct statvfs *, int),                          \
                   1759:        (path, buf, flags))
                   1760:
                   1761: PATHCALL(int, unlink, DUALCALL_UNLINK,                                 \
                   1762:        (const char *path),                                             \
                   1763:        (const char *),                                                 \
                   1764:        (path))
                   1765:
                   1766: PATHCALL(int, symlink, DUALCALL_SYMLINK,                               \
1.58      pooka    1767:        (const char *target, const char *path),                         \
1.45      pooka    1768:        (const char *, const char *),                                   \
1.58      pooka    1769:        (target, path))
1.45      pooka    1770:
1.46      pooka    1771: PATHCALL(ssize_t, readlink, DUALCALL_READLINK,                         \
1.45      pooka    1772:        (const char *path, char *buf, size_t bufsiz),                   \
                   1773:        (const char *, char *, size_t),                                 \
                   1774:        (path, buf, bufsiz))
                   1775:
                   1776: PATHCALL(int, mkdir, DUALCALL_MKDIR,                                   \
                   1777:        (const char *path, mode_t mode),                                \
                   1778:        (const char *, mode_t),                                         \
                   1779:        (path, mode))
                   1780:
                   1781: PATHCALL(int, rmdir, DUALCALL_RMDIR,                                   \
                   1782:        (const char *path),                                             \
                   1783:        (const char *),                                                 \
                   1784:        (path))
                   1785:
                   1786: PATHCALL(int, utimes, DUALCALL_UTIMES,                                 \
                   1787:        (const char *path, const struct timeval *tv),                   \
                   1788:        (const char *, const struct timeval *),                         \
                   1789:        (path, tv))
                   1790:
                   1791: PATHCALL(int, lutimes, DUALCALL_LUTIMES,                               \
                   1792:        (const char *path, const struct timeval *tv),                   \
                   1793:        (const char *, const struct timeval *),                         \
                   1794:        (path, tv))
                   1795:
1.60      pooka    1796: PATHCALL(int, chflags, DUALCALL_CHFLAGS,                               \
                   1797:        (const char *path, u_long flags),                               \
                   1798:        (const char *, u_long),                                         \
                   1799:        (path, flags))
                   1800:
                   1801: PATHCALL(int, lchflags, DUALCALL_LCHFLAGS,                             \
                   1802:        (const char *path, u_long flags),                               \
                   1803:        (const char *, u_long),                                         \
                   1804:        (path, flags))
                   1805:
1.45      pooka    1806: PATHCALL(int, truncate, DUALCALL_TRUNCATE,                             \
                   1807:        (const char *path, off_t length),                               \
                   1808:        (const char *, off_t),                                          \
                   1809:        (path, length))
1.48      pooka    1810:
1.65      pooka    1811: PATHCALL(int, access, DUALCALL_ACCESS,                                 \
                   1812:        (const char *path, int mode),                                   \
                   1813:        (const char *, int),                                            \
                   1814:        (path, mode))
                   1815:
1.68      pooka    1816: PATHCALL(int, REALMKNOD, DUALCALL_MKNOD,                               \
                   1817:        (const char *path, mode_t mode, dev_t dev),                     \
                   1818:        (const char *, mode_t, dev_t),                                  \
                   1819:        (path, mode, dev))
                   1820:
1.48      pooka    1821: /*
                   1822:  * Note: with mount the decisive parameter is the mount
                   1823:  * destination directory.  This is because we don't really know
                   1824:  * about the "source" directory in a generic call (and besides,
                   1825:  * it might not even exist, cf. nfs).
                   1826:  */
                   1827: PATHCALL(int, REALMOUNT, DUALCALL_MOUNT,                               \
                   1828:        (const char *type, const char *path, int flags,                 \
                   1829:            void *data, size_t dlen),                                   \
                   1830:        (const char *, const char *, int, void *, size_t),              \
                   1831:        (type, path, flags, data, dlen))
                   1832:
                   1833: PATHCALL(int, unmount, DUALCALL_UNMOUNT,                               \
                   1834:        (const char *path, int flags),                                  \
                   1835:        (const char *, int),                                            \
                   1836:        (path, flags))

CVSweb <webmaster@jp.NetBSD.org>