uipc_syscalls_43.c revision 1.47.14.6 1 /* $NetBSD: uipc_syscalls_43.c,v 1.47.14.6 2018/09/22 04:56:28 pgoyette Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
32 */
33
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_43.c,v 1.47.14.6 2018/09/22 04:56:28 pgoyette Exp $");
36
37 #if defined(_KERNEL_OPT)
38 #include "opt_compat_netbsd.h"
39 #endif
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/filedesc.h>
44 #include <sys/kernel.h>
45 #include <sys/proc.h>
46 #include <sys/file.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/stat.h>
50 #include <sys/ioctl.h>
51 #include <sys/fcntl.h>
52 #include <sys/syslog.h>
53 #include <sys/unistd.h>
54 #include <sys/resourcevar.h>
55 #include <sys/mbuf.h> /* for MLEN */
56 #include <sys/protosw.h>
57
58 #include <sys/mount.h>
59 #include <sys/syscall.h>
60 #include <sys/syscallvar.h>
61 #include <sys/syscallargs.h>
62
63 #include <net/if.h>
64 #include <net/bpf.h>
65 #include <net/route.h>
66 #include <netinet/in.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/ip.h>
69 #include <net/if_gre.h>
70 #include <net/if_atm.h>
71 #include <net/if_tap.h>
72 #include <net80211/ieee80211_ioctl.h>
73 #include <netinet6/in6_var.h>
74 #include <netinet6/nd6.h>
75 #include <compat/sys/socket.h>
76 #include <compat/sys/sockio.h>
77
78 #include <compat/common/compat_util.h>
79 #include <compat/common/compat_mod.h>
80
81 #include <uvm/uvm_extern.h>
82
83 /*
84 * Following 4.3 syscalls were not versioned, even through they should
85 * have been:
86 * connect(2), bind(2), sendto(2)
87 */
88
89 static struct syscall_package uipc_syscalls_43_syscalls[] = {
90 { SYS_compat_43_oaccept, 0, (sy_call_t *)compat_43_sys_accept },
91 { SYS_compat_43_ogetpeername, 0,
92 (sy_call_t *)compat_43_sys_getpeername },
93 { SYS_compat_43_ogetsockname, 0,
94 (sy_call_t *)compat_43_sys_getsockname },
95 { SYS_compat_43_orecv, 0, (sy_call_t *)compat_43_sys_recv },
96 { SYS_compat_43_orecvfrom, 0, (sy_call_t *)compat_43_sys_recvfrom },
97 { SYS_compat_43_orecvmsg, 0, (sy_call_t *)compat_43_sys_recvmsg },
98 { SYS_compat_43_osend, 0, (sy_call_t *)compat_43_sys_send },
99 { SYS_compat_43_osendmsg, 0, (sy_call_t *)compat_43_sys_sendmsg },
100 { 0, 0, NULL }
101 };
102
103 static int compat_43_sa_put(void *);
104
105 int
106 compat_43_sys_accept(struct lwp *l, const struct compat_43_sys_accept_args *uap, register_t *retval)
107 {
108 /* {
109 syscallarg(int) s;
110 syscallarg(void *) name;
111 syscallarg(int *) anamelen;
112 } */
113 int error;
114
115 if ((error = sys_accept(l, (const struct sys_accept_args *)uap, retval)) != 0)
116 return error;
117
118 if (SCARG(uap, name)
119 && (error = compat_43_sa_put(SCARG(uap, name))))
120 return (error);
121
122 return 0;
123 }
124
125 int
126 compat_43_sys_getpeername(struct lwp *l, const struct compat_43_sys_getpeername_args *uap, register_t *retval)
127 {
128 /* {
129 syscallarg(int) fdes;
130 syscallarg(void *) asa;
131 syscallarg(int *) alen;
132 } */
133
134 int error;
135
136 if ((error = sys_getpeername(l, (const struct sys_getpeername_args *)uap, retval)) != 0)
137 return error;
138
139 if ((error = compat_43_sa_put(SCARG(uap, asa))))
140 return (error);
141
142 return 0;
143 }
144
145 int
146 compat_43_sys_getsockname(struct lwp *l, const struct compat_43_sys_getsockname_args *uap, register_t *retval)
147 {
148 /* {
149 syscallarg(int) fdes;
150 syscallarg(void *) asa;
151 syscallarg(int *) alen;
152 } */
153 int error;
154
155 if ((error = sys_getsockname(l, (const struct sys_getsockname_args *)uap, retval)) != 0)
156 return error;
157
158 if ((error = compat_43_sa_put(SCARG(uap, asa))))
159 return (error);
160
161 return 0;
162 }
163
164 int
165 compat_43_sys_recv(struct lwp *l, const struct compat_43_sys_recv_args *uap, register_t *retval)
166 {
167 /* {
168 syscallarg(int) s;
169 syscallarg(void *) buf;
170 syscallarg(int) len;
171 syscallarg(int) flags;
172 } */
173 struct sys_recvfrom_args bra;
174
175 SCARG(&bra, s) = SCARG(uap, s);
176 SCARG(&bra, buf) = SCARG(uap, buf);
177 SCARG(&bra, len) = (size_t) SCARG(uap, len);
178 SCARG(&bra, flags) = SCARG(uap, flags);
179 SCARG(&bra, from) = NULL;
180 SCARG(&bra, fromlenaddr) = NULL;
181
182 return (sys_recvfrom(l, &bra, retval));
183 }
184
185 int
186 compat_43_sys_recvfrom(struct lwp *l, const struct compat_43_sys_recvfrom_args *uap, register_t *retval)
187 {
188 /* {
189 syscallarg(int) s;
190 syscallarg(void *) buf;
191 syscallarg(size_t) len;
192 syscallarg(int) flags;
193 syscallarg(void *) from;
194 syscallarg(int *) fromlenaddr;
195 } */
196 int error;
197
198 if ((error = sys_recvfrom(l, (const struct sys_recvfrom_args *)uap, retval)))
199 return (error);
200
201 if (SCARG(uap, from) && (error = compat_43_sa_put(SCARG(uap, from))))
202 return (error);
203
204 return (0);
205 }
206
207 /*
208 * Old recvmsg. Arrange necessary structures, calls generic code and
209 * adjusts results accordingly.
210 */
211 int
212 compat_43_sys_recvmsg(struct lwp *l, const struct compat_43_sys_recvmsg_args *uap, register_t *retval)
213 {
214 /* {
215 syscallarg(int) s;
216 syscallarg(struct omsghdr *) msg;
217 syscallarg(int) flags;
218 } */
219 struct omsghdr omsg;
220 struct msghdr msg;
221 struct mbuf *from, *control;
222 int error;
223
224 error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr));
225 if (error)
226 return (error);
227
228 if (omsg.msg_accrights == NULL)
229 omsg.msg_accrightslen = 0;
230 /* it was this way in 4.4BSD */
231 if (omsg.msg_accrightslen > MLEN)
232 return EINVAL;
233
234 msg.msg_name = omsg.msg_name;
235 msg.msg_namelen = omsg.msg_namelen;
236 msg.msg_iovlen = omsg.msg_iovlen;
237 msg.msg_iov = omsg.msg_iov;
238 msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE;
239
240 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
241 omsg.msg_accrights != NULL ? &control : NULL, retval);
242 if (error != 0)
243 return error;
244
245 /*
246 * If there is any control information and it's SCM_RIGHTS,
247 * pass it back to the program.
248 * XXX: maybe there can be more than one chunk of control data?
249 */
250 if (omsg.msg_accrights && control != NULL) {
251 struct cmsghdr *cmsg = mtod(control, struct cmsghdr *);
252
253 if (cmsg->cmsg_level == SOL_SOCKET
254 && cmsg->cmsg_type == SCM_RIGHTS
255 && cmsg->cmsg_len < omsg.msg_accrightslen
256 && copyout(CMSG_DATA(cmsg), omsg.msg_accrights,
257 cmsg->cmsg_len) == 0) {
258 omsg.msg_accrightslen = cmsg->cmsg_len;
259 free_control_mbuf(l, control, control->m_next);
260 } else {
261 omsg.msg_accrightslen = 0;
262 free_control_mbuf(l, control, control);
263 }
264 } else
265 omsg.msg_accrightslen = 0;
266
267 if (from != NULL)
268 /* convert from sockaddr sa_family to osockaddr one here */
269 mtod(from, struct osockaddr *)->sa_family =
270 mtod(from, struct sockaddr *)->sa_family;
271
272 error = copyout_sockname((struct sockaddr *)omsg.msg_name, &omsg.msg_namelen, 0, from);
273 if (from != NULL)
274 m_free(from);
275
276 if (error != 0)
277 error = copyout(&omsg, SCARG(uap, msg), sizeof(omsg));
278
279 return error;
280 }
281
282 int
283 compat_43_sys_send(struct lwp *l, const struct compat_43_sys_send_args *uap, register_t *retval)
284 {
285 /* {
286 syscallarg(int) s;
287 syscallarg(void *) buf;
288 syscallarg(int) len;
289 syscallarg(int) flags;
290 } */
291 struct sys_sendto_args bsa;
292
293 SCARG(&bsa, s) = SCARG(uap, s);
294 SCARG(&bsa, buf) = SCARG(uap, buf);
295 SCARG(&bsa, len) = SCARG(uap, len);
296 SCARG(&bsa, flags) = SCARG(uap, flags);
297 SCARG(&bsa, to) = NULL;
298 SCARG(&bsa, tolen) = 0;
299
300 return (sys_sendto(l, &bsa, retval));
301 }
302
303 int
304 compat43_set_accrights(struct msghdr *msg, void *accrights, int accrightslen)
305 {
306 struct cmsghdr *cmsg;
307 int error;
308 struct mbuf *ctl;
309 u_int clen;
310
311 if (accrights == NULL || accrightslen == 0) {
312 msg->msg_control = NULL;
313 msg->msg_controllen = 0;
314 return 0;
315 }
316
317 clen = CMSG_SPACE(accrightslen);
318 /* it was (almost) this way in 4.4BSD */
319 if (accrightslen < 0 || clen > MLEN)
320 return EINVAL;
321
322 ctl = m_get(M_WAIT, MT_CONTROL);
323 ctl->m_len = clen;
324 cmsg = mtod(ctl, struct cmsghdr *);
325 cmsg->cmsg_len = CMSG_SPACE(accrightslen);
326 cmsg->cmsg_level = SOL_SOCKET;
327 cmsg->cmsg_type = SCM_RIGHTS;
328
329 error = copyin(accrights, CMSG_DATA(cmsg), accrightslen);
330 if (error) {
331 m_free(ctl);
332 return error;
333 }
334
335 msg->msg_control = ctl;
336 msg->msg_controllen = clen;
337 msg->msg_flags |= MSG_CONTROLMBUF;
338 return 0;
339 }
340
341 /*
342 * Old sendmsg. Arrange necessary structures, call generic code and
343 * adjust the results accordingly for old code.
344 */
345 int
346 compat_43_sys_sendmsg(struct lwp *l, const struct compat_43_sys_sendmsg_args *uap, register_t *retval)
347 {
348 /* {
349 syscallarg(int) s;
350 syscallarg(void *) msg;
351 syscallarg(int) flags;
352 } */
353 struct omsghdr omsg;
354 struct msghdr msg;
355 int error;
356 struct mbuf *nam;
357 struct osockaddr *osa;
358 struct sockaddr *sa;
359
360 error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr));
361 if (error != 0)
362 return (error);
363
364 msg.msg_iovlen = omsg.msg_iovlen;
365 msg.msg_iov = omsg.msg_iov;
366
367 error = sockargs(&nam, omsg.msg_name, omsg.msg_namelen,
368 UIO_USERSPACE, MT_SONAME);
369 if (error != 0)
370 return (error);
371
372 sa = mtod(nam, struct sockaddr *);
373 osa = mtod(nam, struct osockaddr *);
374 sa->sa_family = osa->sa_family;
375 sa->sa_len = omsg.msg_namelen;
376
377 msg.msg_flags = MSG_IOVUSRSPACE | MSG_NAMEMBUF;
378
379 msg.msg_name = nam;
380 msg.msg_namelen = omsg.msg_namelen;
381 error = compat43_set_accrights(&msg, omsg.msg_accrights,
382 omsg.msg_accrightslen);
383 if (error != 0)
384 goto bad;
385
386 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags),
387 retval);
388
389 bad:
390 if (nam != NULL)
391 m_free(nam);
392
393 return (error);
394 }
395
396 static int
397 compat_43_sa_put(void *from)
398 {
399 struct osockaddr *osa = (struct osockaddr *) from;
400 struct sockaddr sa;
401 struct osockaddr *kosa;
402 int error, len;
403
404 /*
405 * Only read/write the sockaddr family and length, the rest is
406 * not changed.
407 */
408 len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
409
410 error = copyin((void *) osa, (void *) &sa, len);
411 if (error)
412 return (error);
413
414 /* Note: we convert from sockaddr sa_family to osockaddr one here */
415 kosa = (struct osockaddr *) &sa;
416 kosa->sa_family = sa.sa_family;
417 error = copyout(kosa, osa, len);
418 if (error)
419 return (error);
420
421 return (0);
422 }
423
424 int
425 uipc_syscalls_43_init(void)
426 {
427
428 return syscall_establish(NULL, uipc_syscalls_43_syscalls);
429 }
430
431 int
432 uipc_syscalls_43_fini(void)
433 {
434
435 return syscall_disestablish(NULL, uipc_syscalls_43_syscalls);
436 }
437