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