1 /* $NetBSD: uipc_syscalls_43.c,v 1.18 2002/03/16 20:43:49 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94 36 */ 37 38 #include <sys/cdefs.h> 39 __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_43.c,v 1.18 2002/03/16 20:43:49 christos Exp $"); 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/malloc.h> 53 #include <sys/syslog.h> 54 #include <sys/unistd.h> 55 #include <sys/resourcevar.h> 56 #include <sys/mbuf.h> /* for MLEN */ 57 58 #include <sys/mount.h> 59 #include <sys/syscallargs.h> 60 61 #include <compat/common/compat_util.h> 62 63 #include <uvm/uvm_extern.h> 64 65 /* 66 * Following 4.3 syscalls were not versioned, even through they should 67 * have been: 68 * connect(2), bind(2), sendto(2) 69 */ 70 71 static int compat_43_sa_put(caddr_t); 72 73 int 74 compat_43_sys_accept(p, v, retval) 75 struct proc *p; 76 void *v; 77 register_t *retval; 78 { 79 struct compat_43_sys_accept_args /* { 80 syscallarg(int) s; 81 syscallarg(caddr_t) name; 82 syscallarg(int *) anamelen; 83 } */ *uap = v; 84 int error; 85 86 if ((error = sys_accept(p, v, retval)) != 0) 87 return error; 88 89 if (SCARG(uap, name) 90 && (error = compat_43_sa_put(SCARG(uap, name)))) 91 return (error); 92 93 return 0; 94 } 95 96 int 97 compat_43_sys_getpeername(p, v, retval) 98 struct proc *p; 99 void *v; 100 register_t *retval; 101 { 102 struct compat_43_sys_getpeername_args /* { 103 syscallarg(int) fdes; 104 syscallarg(caddr_t) asa; 105 syscallarg(int *) alen; 106 } */ *uap = v; 107 108 int error; 109 110 if ((error = sys_getpeername(p, v, retval)) != 0) 111 return error; 112 113 if ((error = compat_43_sa_put(SCARG(uap, asa)))) 114 return (error); 115 116 return 0; 117 } 118 119 int 120 compat_43_sys_getsockname(p, v, retval) 121 struct proc *p; 122 void *v; 123 register_t *retval; 124 { 125 struct compat_43_sys_getsockname_args /* { 126 syscallarg(int) fdes; 127 syscallarg(caddr_t) asa; 128 syscallarg(int *) alen; 129 } */ *uap = v; 130 int error; 131 132 if ((error = sys_getsockname(p, v, retval)) != 0) 133 return error; 134 135 if ((error = compat_43_sa_put(SCARG(uap, asa)))) 136 return (error); 137 138 return 0; 139 } 140 141 int 142 compat_43_sys_recv(p, v, retval) 143 struct proc *p; 144 void *v; 145 register_t *retval; 146 { 147 struct compat_43_sys_recv_args /* { 148 syscallarg(int) s; 149 syscallarg(caddr_t) buf; 150 syscallarg(int) len; 151 syscallarg(int) flags; 152 } */ *uap = v; 153 struct sys_recvfrom_args bra; 154 155 SCARG(&bra, s) = SCARG(uap, s); 156 SCARG(&bra, buf) = SCARG(uap, buf); 157 SCARG(&bra, len) = (size_t) SCARG(uap, len); 158 SCARG(&bra, flags) = SCARG(uap, flags); 159 SCARG(&bra, from) = NULL; 160 SCARG(&bra, fromlenaddr) = NULL; 161 162 return (sys_recvfrom(p, &bra, retval)); 163 } 164 165 int 166 compat_43_sys_recvfrom(p, v, retval) 167 struct proc *p; 168 void *v; 169 register_t *retval; 170 { 171 struct compat_43_sys_recvfrom_args /* { 172 syscallarg(int) s; 173 syscallarg(caddr_t) buf; 174 syscallarg(size_t) len; 175 syscallarg(int) flags; 176 syscallarg(caddr_t) from; 177 syscallarg(int *) fromlenaddr; 178 } */ *uap = v; 179 int error; 180 181 if ((error = sys_recvfrom(p, v, retval))) 182 return (error); 183 184 if (SCARG(uap, from) && (error = compat_43_sa_put(SCARG(uap, from)))) 185 return (error); 186 187 return (0); 188 } 189 190 /* 191 * Old recvmsg. Arrange necessary structures, calls generic code and 192 * adjusts results accordingly. 193 */ 194 int 195 compat_43_sys_recvmsg(p, v, retval) 196 struct proc *p; 197 void *v; 198 register_t *retval; 199 { 200 struct compat_43_sys_recvmsg_args /* { 201 syscallarg(int) s; 202 syscallarg(struct omsghdr *) msg; 203 syscallarg(int) flags; 204 } */ *uap = v; 205 struct omsghdr omsg; 206 struct msghdr msg; 207 struct iovec aiov[UIO_SMALLIOV], *iov; 208 int error; 209 210 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&omsg, 211 sizeof (struct omsghdr)); 212 if (error) 213 return (error); 214 if ((u_int)omsg.msg_iovlen > UIO_SMALLIOV) { 215 if ((u_int)omsg.msg_iovlen > IOV_MAX) 216 return (EMSGSIZE); 217 iov = malloc(sizeof(struct iovec) * omsg.msg_iovlen, 218 M_IOV, M_WAITOK); 219 } else 220 iov = aiov; 221 222 error = copyin((caddr_t)omsg.msg_iov, (caddr_t)iov, 223 (unsigned)(omsg.msg_iovlen * sizeof (struct iovec))); 224 if (error) 225 goto done; 226 227 msg.msg_name = omsg.msg_name; 228 msg.msg_namelen = omsg.msg_namelen; 229 msg.msg_iovlen = omsg.msg_iovlen; 230 msg.msg_iov = iov; 231 msg.msg_flags = SCARG(uap, flags); 232 233 /* 234 * If caller passes accrights, arrange things for generic code to 235 * DTRT. 236 */ 237 if (omsg.msg_accrights && omsg.msg_accrightslen) { 238 caddr_t sg = stackgap_init(p, 0); 239 struct cmsg *ucmsg; 240 241 /* it was this way in 4.4BSD */ 242 if ((u_int) omsg.msg_accrightslen > MLEN) 243 return (EINVAL); 244 245 ucmsg = stackgap_alloc(p, &sg, CMSG_SPACE(omsg.msg_accrightslen)); 246 if (ucmsg == NULL) 247 return (EMSGSIZE); 248 249 msg.msg_control = ucmsg; 250 msg.msg_controllen = CMSG_SPACE(omsg.msg_accrightslen); 251 } else { 252 msg.msg_control = NULL; 253 msg.msg_controllen = 0; 254 } 255 256 error = recvit(p, SCARG(uap, s), &msg, 257 (caddr_t)&SCARG(uap, msg)->msg_namelen, retval); 258 259 /* 260 * If there is any control information and it's SCM_RIGHTS, 261 * pass it back to the program. 262 */ 263 if (!error && omsg.msg_accrights && msg.msg_controllen > 0) { 264 struct cmsghdr *cmsg; 265 266 /* safe - msg.msg_controllen set by kernel */ 267 cmsg = (struct cmsghdr *) malloc(msg.msg_controllen, 268 M_TEMP, M_WAITOK); 269 270 error = copyin(msg.msg_control, cmsg, msg.msg_controllen); 271 if (error) { 272 free(cmsg, M_TEMP); 273 return (error); 274 } 275 276 if (cmsg->cmsg_level != SOL_SOCKET 277 || cmsg->cmsg_type != SCM_RIGHTS 278 || copyout(CMSG_DATA(cmsg), omsg.msg_accrights, 279 cmsg->cmsg_len)) { 280 omsg.msg_accrightslen = 0; 281 } 282 283 free(cmsg, M_TEMP); 284 285 if (!error) { 286 error = copyout(&cmsg->cmsg_len, 287 &SCARG(uap, msg)->msg_accrightslen, sizeof(int)); 288 } 289 } 290 291 if (!error && omsg.msg_name) { 292 int namelen; 293 294 if ((error = copyin(&SCARG(uap, msg)->msg_namelen, &namelen, sizeof(int)) == 0) 295 && namelen > 0) 296 error = compat_43_sa_put(omsg.msg_name); 297 } 298 299 done: 300 if (iov != aiov) 301 free(iov, M_IOV); 302 return (error); 303 } 304 305 int 306 compat_43_sys_send(p, v, retval) 307 struct proc *p; 308 void *v; 309 register_t *retval; 310 { 311 struct compat_43_sys_send_args /* { 312 syscallarg(int) s; 313 syscallarg(caddr_t) buf; 314 syscallarg(int) len; 315 syscallarg(int) flags; 316 } */ *uap = v; 317 struct sys_sendto_args bsa; 318 319 SCARG(&bsa, s) = SCARG(uap, s); 320 SCARG(&bsa, buf) = SCARG(uap, buf); 321 SCARG(&bsa, len) = SCARG(uap, len); 322 SCARG(&bsa, flags) = SCARG(uap, flags); 323 SCARG(&bsa, to) = NULL; 324 SCARG(&bsa, tolen) = 0; 325 326 return (sys_sendto(p, &bsa, retval)); 327 } 328 329 /* 330 * Old sendmsg. Arrange necessary structures, call generic code and 331 * adjust the results accordingly for old code. 332 */ 333 int 334 compat_43_sys_sendmsg(p, v, retval) 335 struct proc *p; 336 void *v; 337 register_t *retval; 338 { 339 struct compat_43_sys_sendmsg_args /* { 340 syscallarg(int) s; 341 syscallarg(caddr_t) msg; 342 syscallarg(int) flags; 343 } */ *uap = v; 344 struct omsghdr omsg; 345 struct msghdr msg; 346 struct iovec aiov[UIO_SMALLIOV], *iov; 347 int error; 348 caddr_t sg = stackgap_init(p, 0); 349 350 error = copyin(SCARG(uap, msg), (caddr_t)&omsg, 351 sizeof (struct omsghdr)); 352 if (error) 353 return (error); 354 if ((u_int)omsg.msg_iovlen > UIO_SMALLIOV) { 355 if ((u_int)omsg.msg_iovlen > IOV_MAX) 356 return (EMSGSIZE); 357 iov = malloc(sizeof(struct iovec) * omsg.msg_iovlen, 358 M_IOV, M_WAITOK); 359 } else 360 iov = aiov; 361 error = copyin((caddr_t)omsg.msg_iov, (caddr_t)iov, 362 (unsigned)(omsg.msg_iovlen * sizeof (struct iovec))); 363 if (error) 364 goto done; 365 366 if (omsg.msg_name) { 367 struct osockaddr *osa; 368 struct sockaddr *sa, *usa; 369 370 if ((u_int) omsg.msg_namelen > UCHAR_MAX) 371 return (EINVAL); 372 373 osa = malloc(omsg.msg_namelen, M_TEMP, M_WAITOK); 374 375 if ((error = copyin(omsg.msg_name, osa, omsg.msg_namelen))) { 376 free(osa, M_TEMP); 377 return (error); 378 } 379 380 sa = (struct sockaddr *) osa; 381 sa->sa_family = osa->sa_family; 382 sa->sa_len = omsg.msg_namelen; 383 384 usa = stackgap_alloc(p, &sg, omsg.msg_namelen); 385 if (!usa) { 386 free(osa, M_TEMP); 387 return (ENOMEM); 388 } 389 390 (void) copyout(sa, usa, omsg.msg_namelen); 391 free(osa, M_TEMP); 392 393 msg.msg_name = usa; 394 msg.msg_namelen = omsg.msg_namelen; 395 } else { 396 msg.msg_name = NULL; 397 msg.msg_namelen = 0; 398 } 399 msg.msg_iovlen = omsg.msg_iovlen; 400 msg.msg_iov = iov; 401 msg.msg_flags = 0; 402 403 if (omsg.msg_accrights && omsg.msg_accrightslen != 0) { 404 struct cmsghdr *cmsg, *ucmsg; 405 406 /* it was this way in 4.4BSD */ 407 if ((u_int) omsg.msg_accrightslen > MLEN) 408 return (EINVAL); 409 410 cmsg = malloc(CMSG_SPACE(omsg.msg_accrightslen), M_TEMP, 411 M_WAITOK); 412 cmsg->cmsg_len = CMSG_SPACE(omsg.msg_accrightslen); 413 cmsg->cmsg_level = SOL_SOCKET; 414 cmsg->cmsg_type = SCM_RIGHTS; 415 416 error = copyin(omsg.msg_accrights, CMSG_DATA(cmsg), 417 omsg.msg_accrightslen); 418 if (error) { 419 free(cmsg, M_TEMP); 420 return (error); 421 } 422 423 ucmsg = stackgap_alloc(p, &sg, CMSG_SPACE(omsg.msg_accrightslen)); 424 if (!ucmsg) { 425 free(cmsg, M_TEMP); 426 return (EMSGSIZE); 427 } 428 429 (void) copyout(cmsg, ucmsg, CMSG_SPACE(omsg.msg_accrightslen)); 430 free(cmsg, M_TEMP); 431 432 msg.msg_control = ucmsg; 433 msg.msg_controllen = CMSG_SPACE(omsg.msg_accrightslen); 434 } else { 435 msg.msg_control = NULL; 436 msg.msg_controllen = 0; 437 } 438 439 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval); 440 done: 441 if (iov != aiov) 442 FREE(iov, M_IOV); 443 return (error); 444 } 445 446 static int 447 compat_43_sa_put(from) 448 caddr_t from; 449 { 450 struct osockaddr *osa = (struct osockaddr *) from; 451 struct sockaddr sa; 452 struct osockaddr *kosa; 453 int error, len; 454 455 /* 456 * Only read/write the sockaddr family and length, the rest is 457 * not changed. 458 */ 459 len = sizeof(sa.sa_len) + sizeof(sa.sa_family); 460 461 error = copyin((caddr_t) osa, (caddr_t) &sa, len); 462 if (error) 463 return (error); 464 465 /* Note: we convert from sockaddr sa_family to osockaddr one here */ 466 kosa = (struct osockaddr *) &sa; 467 kosa->sa_family = sa.sa_family; 468 error = copyout(kosa, osa, len); 469 if (error) 470 return (error); 471 472 return (0); 473 } 474