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