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