1 /* $NetBSD: uipc_syscalls_43.c,v 1.49 2018/05/03 21:43:33 christos 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.49 2018/05/03 21:43:33 christos Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/filedesc.h> 40 #include <sys/kernel.h> 41 #include <sys/proc.h> 42 #include <sys/file.h> 43 #include <sys/socket.h> 44 #include <sys/socketvar.h> 45 #include <sys/stat.h> 46 #include <sys/ioctl.h> 47 #include <sys/fcntl.h> 48 #include <sys/syslog.h> 49 #include <sys/unistd.h> 50 #include <sys/resourcevar.h> 51 #include <sys/mbuf.h> /* for MLEN */ 52 #include <sys/protosw.h> 53 54 #include <sys/mount.h> 55 #include <sys/syscallargs.h> 56 57 #include <net/if.h> 58 #include <net/bpf.h> 59 #include <net/route.h> 60 #include <netinet/in.h> 61 #include <netinet/in_systm.h> 62 #include <netinet/ip.h> 63 #include <net/if_gre.h> 64 #include <net/if_atm.h> 65 #include <net/if_tap.h> 66 #include <net80211/ieee80211_ioctl.h> 67 #include <netinet6/in6_var.h> 68 #include <netinet6/nd6.h> 69 #include <compat/sys/socket.h> 70 #include <compat/sys/sockio.h> 71 72 #include <compat/common/compat_util.h> 73 74 #include <uvm/uvm_extern.h> 75 76 /* 77 * Following 4.3 syscalls were not versioned, even through they should 78 * have been: 79 * connect(2), bind(2), sendto(2) 80 */ 81 82 static int compat_43_sa_put(void *); 83 84 int 85 compat_43_sys_accept(struct lwp *l, const struct compat_43_sys_accept_args *uap, register_t *retval) 86 { 87 /* { 88 syscallarg(int) s; 89 syscallarg(void *) name; 90 syscallarg(int *) anamelen; 91 } */ 92 int error; 93 94 if ((error = sys_accept(l, (const struct sys_accept_args *)uap, retval)) != 0) 95 return error; 96 97 if (SCARG(uap, name) 98 && (error = compat_43_sa_put(SCARG(uap, name)))) 99 return (error); 100 101 return 0; 102 } 103 104 int 105 compat_43_sys_getpeername(struct lwp *l, const struct compat_43_sys_getpeername_args *uap, register_t *retval) 106 { 107 /* { 108 syscallarg(int) fdes; 109 syscallarg(void *) asa; 110 syscallarg(int *) alen; 111 } */ 112 113 int error; 114 115 if ((error = sys_getpeername(l, (const struct sys_getpeername_args *)uap, retval)) != 0) 116 return error; 117 118 if ((error = compat_43_sa_put(SCARG(uap, asa)))) 119 return (error); 120 121 return 0; 122 } 123 124 int 125 compat_43_sys_getsockname(struct lwp *l, const struct compat_43_sys_getsockname_args *uap, register_t *retval) 126 { 127 /* { 128 syscallarg(int) fdes; 129 syscallarg(void *) asa; 130 syscallarg(int *) alen; 131 } */ 132 int error; 133 134 if ((error = sys_getsockname(l, (const struct sys_getsockname_args *)uap, retval)) != 0) 135 return error; 136 137 if ((error = compat_43_sa_put(SCARG(uap, asa)))) 138 return (error); 139 140 return 0; 141 } 142 143 int 144 compat_43_sys_recv(struct lwp *l, const struct compat_43_sys_recv_args *uap, register_t *retval) 145 { 146 /* { 147 syscallarg(int) s; 148 syscallarg(void *) buf; 149 syscallarg(int) len; 150 syscallarg(int) flags; 151 } */ 152 struct sys_recvfrom_args bra; 153 154 SCARG(&bra, s) = SCARG(uap, s); 155 SCARG(&bra, buf) = SCARG(uap, buf); 156 SCARG(&bra, len) = (size_t) SCARG(uap, len); 157 SCARG(&bra, flags) = SCARG(uap, flags); 158 SCARG(&bra, from) = NULL; 159 SCARG(&bra, fromlenaddr) = NULL; 160 161 return (sys_recvfrom(l, &bra, retval)); 162 } 163 164 int 165 compat_43_sys_recvfrom(struct lwp *l, const struct compat_43_sys_recvfrom_args *uap, register_t *retval) 166 { 167 /* { 168 syscallarg(int) s; 169 syscallarg(void *) buf; 170 syscallarg(size_t) len; 171 syscallarg(int) flags; 172 syscallarg(void *) from; 173 syscallarg(int *) fromlenaddr; 174 } */ 175 int error; 176 177 if ((error = sys_recvfrom(l, (const struct sys_recvfrom_args *)uap, retval))) 178 return (error); 179 180 if (SCARG(uap, from) && (error = compat_43_sa_put(SCARG(uap, from)))) 181 return (error); 182 183 return (0); 184 } 185 186 /* 187 * Old recvmsg. Arrange necessary structures, calls generic code and 188 * adjusts results accordingly. 189 */ 190 int 191 compat_43_sys_recvmsg(struct lwp *l, const struct compat_43_sys_recvmsg_args *uap, register_t *retval) 192 { 193 /* { 194 syscallarg(int) s; 195 syscallarg(struct omsghdr *) msg; 196 syscallarg(int) flags; 197 } */ 198 struct omsghdr omsg; 199 struct msghdr msg; 200 struct mbuf *from, *control; 201 int error; 202 203 error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr)); 204 if (error) 205 return (error); 206 207 if (omsg.msg_accrights == NULL) 208 omsg.msg_accrightslen = 0; 209 /* it was this way in 4.4BSD */ 210 if (omsg.msg_accrightslen > MLEN) 211 return EINVAL; 212 213 msg.msg_name = omsg.msg_name; 214 msg.msg_namelen = omsg.msg_namelen; 215 msg.msg_iovlen = omsg.msg_iovlen; 216 msg.msg_iov = omsg.msg_iov; 217 msg.msg_flags = (SCARG(uap, flags) & MSG_USERFLAGS) | MSG_IOVUSRSPACE; 218 219 error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, 220 omsg.msg_accrights != NULL ? &control : NULL, retval); 221 if (error != 0) 222 return error; 223 224 /* 225 * If there is any control information and it's SCM_RIGHTS, 226 * pass it back to the program. 227 * XXX: maybe there can be more than one chunk of control data? 228 */ 229 if (omsg.msg_accrights && control != NULL) { 230 struct cmsghdr *cmsg = mtod(control, struct cmsghdr *); 231 232 if (cmsg->cmsg_level == SOL_SOCKET 233 && cmsg->cmsg_type == SCM_RIGHTS 234 && cmsg->cmsg_len < omsg.msg_accrightslen 235 && copyout(CMSG_DATA(cmsg), omsg.msg_accrights, 236 cmsg->cmsg_len) == 0) { 237 omsg.msg_accrightslen = cmsg->cmsg_len; 238 free_control_mbuf(l, control, control->m_next); 239 } else { 240 omsg.msg_accrightslen = 0; 241 free_control_mbuf(l, control, control); 242 } 243 } else 244 omsg.msg_accrightslen = 0; 245 246 if (from != NULL) 247 /* convert from sockaddr sa_family to osockaddr one here */ 248 mtod(from, struct osockaddr *)->sa_family = 249 mtod(from, struct sockaddr *)->sa_family; 250 251 error = copyout_sockname((struct sockaddr *)omsg.msg_name, &omsg.msg_namelen, 0, from); 252 if (from != NULL) 253 m_free(from); 254 255 if (error != 0) 256 error = copyout(&omsg, SCARG(uap, msg), sizeof(omsg)); 257 258 return error; 259 } 260 261 int 262 compat_43_sys_send(struct lwp *l, const struct compat_43_sys_send_args *uap, register_t *retval) 263 { 264 /* { 265 syscallarg(int) s; 266 syscallarg(void *) buf; 267 syscallarg(int) len; 268 syscallarg(int) flags; 269 } */ 270 struct sys_sendto_args bsa; 271 272 SCARG(&bsa, s) = SCARG(uap, s); 273 SCARG(&bsa, buf) = SCARG(uap, buf); 274 SCARG(&bsa, len) = SCARG(uap, len); 275 SCARG(&bsa, flags) = SCARG(uap, flags); 276 SCARG(&bsa, to) = NULL; 277 SCARG(&bsa, tolen) = 0; 278 279 return (sys_sendto(l, &bsa, retval)); 280 } 281 282 int 283 compat43_set_accrights(struct msghdr *msg, void *accrights, int accrightslen) 284 { 285 struct cmsghdr *cmsg; 286 int error; 287 struct mbuf *ctl; 288 u_int clen; 289 290 if (accrights == NULL || accrightslen == 0) { 291 msg->msg_control = NULL; 292 msg->msg_controllen = 0; 293 return 0; 294 } 295 296 clen = CMSG_SPACE(accrightslen); 297 /* it was (almost) this way in 4.4BSD */ 298 if (accrightslen < 0 || clen > MLEN) 299 return EINVAL; 300 301 ctl = m_get(M_WAIT, MT_CONTROL); 302 ctl->m_len = clen; 303 cmsg = mtod(ctl, struct cmsghdr *); 304 cmsg->cmsg_len = CMSG_SPACE(accrightslen); 305 cmsg->cmsg_level = SOL_SOCKET; 306 cmsg->cmsg_type = SCM_RIGHTS; 307 308 error = copyin(accrights, CMSG_DATA(cmsg), accrightslen); 309 if (error) { 310 m_free(ctl); 311 return error; 312 } 313 314 msg->msg_control = ctl; 315 msg->msg_controllen = clen; 316 msg->msg_flags |= MSG_CONTROLMBUF; 317 return 0; 318 } 319 320 /* 321 * Old sendmsg. Arrange necessary structures, call generic code and 322 * adjust the results accordingly for old code. 323 */ 324 int 325 compat_43_sys_sendmsg(struct lwp *l, const struct compat_43_sys_sendmsg_args *uap, register_t *retval) 326 { 327 /* { 328 syscallarg(int) s; 329 syscallarg(void *) msg; 330 syscallarg(int) flags; 331 } */ 332 struct omsghdr omsg; 333 struct msghdr msg; 334 int error; 335 struct mbuf *nam; 336 struct osockaddr *osa; 337 struct sockaddr *sa; 338 339 error = copyin(SCARG(uap, msg), &omsg, sizeof (struct omsghdr)); 340 if (error != 0) 341 return (error); 342 343 msg.msg_iovlen = omsg.msg_iovlen; 344 msg.msg_iov = omsg.msg_iov; 345 346 error = sockargs(&nam, omsg.msg_name, omsg.msg_namelen, 347 UIO_USERSPACE, MT_SONAME); 348 if (error != 0) 349 return (error); 350 351 sa = mtod(nam, struct sockaddr *); 352 osa = mtod(nam, struct osockaddr *); 353 sa->sa_family = osa->sa_family; 354 sa->sa_len = omsg.msg_namelen; 355 356 msg.msg_flags = MSG_IOVUSRSPACE | MSG_NAMEMBUF; 357 358 msg.msg_name = nam; 359 msg.msg_namelen = omsg.msg_namelen; 360 error = compat43_set_accrights(&msg, omsg.msg_accrights, 361 omsg.msg_accrightslen); 362 if (error != 0) 363 goto bad; 364 365 return do_sys_sendmsg(l, SCARG(uap, s), &msg, SCARG(uap, flags), 366 retval); 367 368 bad: 369 if (nam != NULL) 370 m_free(nam); 371 372 return (error); 373 } 374 375 static int 376 compat_43_sa_put(void *from) 377 { 378 struct osockaddr *osa = (struct osockaddr *) from; 379 struct sockaddr sa; 380 struct osockaddr *kosa; 381 int error, len; 382 383 /* 384 * Only read/write the sockaddr family and length, the rest is 385 * not changed. 386 */ 387 len = sizeof(sa.sa_len) + sizeof(sa.sa_family); 388 389 error = copyin((void *) osa, (void *) &sa, len); 390 if (error) 391 return (error); 392 393 /* Note: we convert from sockaddr sa_family to osockaddr one here */ 394 kosa = (struct osockaddr *) &sa; 395 kosa->sa_family = sa.sa_family; 396 error = copyout(kosa, osa, len); 397 if (error) 398 return (error); 399 400 return (0); 401 } 402