1/* 2 * Copyright (c) 1982, 1986, 1989, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 34 */ 35 36#include <sys/cdefs.h>
|
37__FBSDID("$FreeBSD: head/sys/kern/uipc_usrreq.c 126103 2004-02-22 01:11:53Z cperciva $");
|
37__FBSDID("$FreeBSD: head/sys/kern/uipc_usrreq.c 126425 2004-03-01 03:14:23Z rwatson $"); |
38 39#include "opt_mac.h" 40 41#include <sys/param.h> 42#include <sys/domain.h> 43#include <sys/fcntl.h> 44#include <sys/malloc.h> /* XXX must be before <sys/file.h> */ 45#include <sys/file.h> 46#include <sys/filedesc.h> 47#include <sys/jail.h> 48#include <sys/kernel.h> 49#include <sys/lock.h> 50#include <sys/mac.h> 51#include <sys/mbuf.h> 52#include <sys/mutex.h> 53#include <sys/namei.h> 54#include <sys/proc.h> 55#include <sys/protosw.h> 56#include <sys/resourcevar.h> 57#include <sys/socket.h> 58#include <sys/socketvar.h> 59#include <sys/signalvar.h> 60#include <sys/stat.h> 61#include <sys/sx.h> 62#include <sys/sysctl.h> 63#include <sys/systm.h> 64#include <sys/un.h> 65#include <sys/unpcb.h> 66#include <sys/vnode.h> 67 68#include <vm/uma.h> 69 70static uma_zone_t unp_zone; 71static unp_gen_t unp_gencnt; 72static u_int unp_count; 73 74static struct unp_head unp_shead, unp_dhead; 75 76/* 77 * Unix communications domain. 78 * 79 * TODO: 80 * SEQPACKET, RDM 81 * rethink name space problems 82 * need a proper out-of-band 83 * lock pushdown 84 */ 85static struct sockaddr sun_noname = { sizeof(sun_noname), AF_LOCAL }; 86static ino_t unp_ino; /* prototype for fake inode numbers */ 87 88static int unp_attach(struct socket *); 89static void unp_detach(struct unpcb *); 90static int unp_bind(struct unpcb *,struct sockaddr *, struct thread *); 91static int unp_connect(struct socket *,struct sockaddr *, struct thread *); 92static void unp_disconnect(struct unpcb *); 93static void unp_shutdown(struct unpcb *); 94static void unp_drop(struct unpcb *, int); 95static void unp_gc(void); 96static void unp_scan(struct mbuf *, void (*)(struct file *)); 97static void unp_mark(struct file *); 98static void unp_discard(struct file *); 99static void unp_freerights(struct file **, int); 100static int unp_internalize(struct mbuf **, struct thread *); 101static int unp_listen(struct unpcb *, struct thread *); 102 103static int 104uipc_abort(struct socket *so) 105{ 106 struct unpcb *unp = sotounpcb(so); 107 108 if (unp == 0) 109 return (EINVAL); 110 unp_drop(unp, ECONNABORTED); 111 unp_detach(unp); 112 sotryfree(so); 113 return (0); 114} 115 116static int 117uipc_accept(struct socket *so, struct sockaddr **nam) 118{ 119 struct unpcb *unp = sotounpcb(so); 120 121 if (unp == 0) 122 return (EINVAL); 123 124 /* 125 * Pass back name of connected socket, 126 * if it was bound and we are still connected 127 * (our peer may have closed already!). 128 */ 129 if (unp->unp_conn && unp->unp_conn->unp_addr) {
|
130 *nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr,
131 1);
|
130 *nam = sodupsockaddr( 131 (struct sockaddr *)unp->unp_conn->unp_addr, M_WAITOK); |
132 } else {
|
133 *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
|
133 *nam = sodupsockaddr((struct sockaddr *)&sun_noname, 134 M_WAITOK); |
135 } 136 return (0); 137} 138 139static int 140uipc_attach(struct socket *so, int proto, struct thread *td) 141{ 142 struct unpcb *unp = sotounpcb(so); 143 144 if (unp != 0) 145 return (EISCONN); 146 return (unp_attach(so)); 147} 148 149static int 150uipc_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 151{ 152 struct unpcb *unp = sotounpcb(so); 153 154 if (unp == 0) 155 return (EINVAL); 156 157 return (unp_bind(unp, nam, td)); 158} 159 160static int 161uipc_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 162{ 163 struct unpcb *unp = sotounpcb(so); 164 165 if (unp == 0) 166 return (EINVAL); 167 return (unp_connect(so, nam, curthread)); 168} 169 170static int 171uipc_connect2(struct socket *so1, struct socket *so2) 172{ 173 struct unpcb *unp = sotounpcb(so1); 174 175 if (unp == 0) 176 return (EINVAL); 177 178 return (unp_connect2(so1, so2)); 179} 180 181/* control is EOPNOTSUPP */ 182 183static int 184uipc_detach(struct socket *so) 185{ 186 struct unpcb *unp = sotounpcb(so); 187 188 if (unp == 0) 189 return (EINVAL); 190 191 unp_detach(unp); 192 return (0); 193} 194 195static int 196uipc_disconnect(struct socket *so) 197{ 198 struct unpcb *unp = sotounpcb(so); 199 200 if (unp == 0) 201 return (EINVAL); 202 unp_disconnect(unp); 203 return (0); 204} 205 206static int 207uipc_listen(struct socket *so, struct thread *td) 208{ 209 struct unpcb *unp = sotounpcb(so); 210 211 if (unp == 0 || unp->unp_vnode == 0) 212 return (EINVAL); 213 return (unp_listen(unp, td)); 214} 215 216static int 217uipc_peeraddr(struct socket *so, struct sockaddr **nam) 218{ 219 struct unpcb *unp = sotounpcb(so); 220 221 if (unp == 0) 222 return (EINVAL); 223 if (unp->unp_conn && unp->unp_conn->unp_addr)
|
223 *nam = dup_sockaddr((struct sockaddr *)unp->unp_conn->unp_addr,
224 1);
|
224 *nam = sodupsockaddr( 225 (struct sockaddr *)unp->unp_conn->unp_addr, M_WAITOK); |
226 else { 227 /* 228 * XXX: It seems that this test always fails even when 229 * connection is established. So, this else clause is 230 * added as workaround to return PF_LOCAL sockaddr. 231 */
|
231 *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
|
232 *nam = sodupsockaddr((struct sockaddr *)&sun_noname, 233 M_WAITOK); |
234 } 235 return (0); 236} 237 238static int 239uipc_rcvd(struct socket *so, int flags) 240{ 241 struct unpcb *unp = sotounpcb(so); 242 struct socket *so2; 243 u_long newhiwat; 244 245 if (unp == 0) 246 return (EINVAL); 247 switch (so->so_type) { 248 case SOCK_DGRAM: 249 panic("uipc_rcvd DGRAM?"); 250 /*NOTREACHED*/ 251 252 case SOCK_STREAM: 253 if (unp->unp_conn == 0) 254 break; 255 so2 = unp->unp_conn->unp_socket; 256 /* 257 * Adjust backpressure on sender 258 * and wakeup any waiting to write. 259 */ 260 so2->so_snd.sb_mbmax += unp->unp_mbcnt - so->so_rcv.sb_mbcnt; 261 unp->unp_mbcnt = so->so_rcv.sb_mbcnt; 262 newhiwat = so2->so_snd.sb_hiwat + unp->unp_cc - 263 so->so_rcv.sb_cc; 264 (void)chgsbsize(so2->so_cred->cr_uidinfo, &so2->so_snd.sb_hiwat, 265 newhiwat, RLIM_INFINITY); 266 unp->unp_cc = so->so_rcv.sb_cc; 267 sowwakeup(so2); 268 break; 269 270 default: 271 panic("uipc_rcvd unknown socktype"); 272 } 273 return (0); 274} 275 276/* pru_rcvoob is EOPNOTSUPP */ 277 278static int 279uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 280 struct mbuf *control, struct thread *td) 281{ 282 int error = 0; 283 struct unpcb *unp = sotounpcb(so); 284 struct socket *so2; 285 u_long newhiwat; 286 287 if (unp == 0) { 288 error = EINVAL; 289 goto release; 290 } 291 if (flags & PRUS_OOB) { 292 error = EOPNOTSUPP; 293 goto release; 294 } 295 296 if (control && (error = unp_internalize(&control, td))) 297 goto release; 298 299 switch (so->so_type) { 300 case SOCK_DGRAM: 301 { 302 struct sockaddr *from; 303 304 if (nam) { 305 if (unp->unp_conn) { 306 error = EISCONN; 307 break; 308 } 309 error = unp_connect(so, nam, td); 310 if (error) 311 break; 312 } else { 313 if (unp->unp_conn == 0) { 314 error = ENOTCONN; 315 break; 316 } 317 } 318 so2 = unp->unp_conn->unp_socket; 319 if (unp->unp_addr) 320 from = (struct sockaddr *)unp->unp_addr; 321 else 322 from = &sun_noname; 323 if (sbappendaddr(&so2->so_rcv, from, m, control)) { 324 sorwakeup(so2); 325 m = 0; 326 control = 0; 327 } else { 328 error = ENOBUFS; 329 } 330 if (nam) 331 unp_disconnect(unp); 332 break; 333 } 334 335 case SOCK_STREAM: 336 /* Connect if not connected yet. */ 337 /* 338 * Note: A better implementation would complain 339 * if not equal to the peer's address. 340 */ 341 if ((so->so_state & SS_ISCONNECTED) == 0) { 342 if (nam) { 343 error = unp_connect(so, nam, td); 344 if (error) 345 break; /* XXX */ 346 } else { 347 error = ENOTCONN; 348 break; 349 } 350 } 351 352 if (so->so_state & SS_CANTSENDMORE) { 353 error = EPIPE; 354 break; 355 } 356 if (unp->unp_conn == 0) 357 panic("uipc_send connected but no connection?"); 358 so2 = unp->unp_conn->unp_socket; 359 /* 360 * Send to paired receive port, and then reduce 361 * send buffer hiwater marks to maintain backpressure. 362 * Wake up readers. 363 */ 364 if (control) { 365 if (sbappendcontrol(&so2->so_rcv, m, control)) 366 control = 0; 367 } else { 368 sbappend(&so2->so_rcv, m); 369 } 370 so->so_snd.sb_mbmax -= 371 so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt; 372 unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt; 373 newhiwat = so->so_snd.sb_hiwat - 374 (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc); 375 (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, 376 newhiwat, RLIM_INFINITY); 377 unp->unp_conn->unp_cc = so2->so_rcv.sb_cc; 378 sorwakeup(so2); 379 m = 0; 380 break; 381 382 default: 383 panic("uipc_send unknown socktype"); 384 } 385 386 /* 387 * SEND_EOF is equivalent to a SEND followed by 388 * a SHUTDOWN. 389 */ 390 if (flags & PRUS_EOF) { 391 socantsendmore(so); 392 unp_shutdown(unp); 393 } 394 395 if (control && error != 0) 396 unp_dispose(control); 397 398release: 399 if (control) 400 m_freem(control); 401 if (m) 402 m_freem(m); 403 return (error); 404} 405 406static int 407uipc_sense(struct socket *so, struct stat *sb) 408{ 409 struct unpcb *unp = sotounpcb(so); 410 struct socket *so2; 411 412 if (unp == 0) 413 return (EINVAL); 414 sb->st_blksize = so->so_snd.sb_hiwat; 415 if (so->so_type == SOCK_STREAM && unp->unp_conn != 0) { 416 so2 = unp->unp_conn->unp_socket; 417 sb->st_blksize += so2->so_rcv.sb_cc; 418 } 419 sb->st_dev = NOUDEV; 420 if (unp->unp_ino == 0) 421 unp->unp_ino = (++unp_ino == 0) ? ++unp_ino : unp_ino; 422 sb->st_ino = unp->unp_ino; 423 return (0); 424} 425 426static int 427uipc_shutdown(struct socket *so) 428{ 429 struct unpcb *unp = sotounpcb(so); 430 431 if (unp == 0) 432 return (EINVAL); 433 socantsendmore(so); 434 unp_shutdown(unp); 435 return (0); 436} 437 438static int 439uipc_sockaddr(struct socket *so, struct sockaddr **nam) 440{ 441 struct unpcb *unp = sotounpcb(so); 442 443 if (unp == 0) 444 return (EINVAL); 445 if (unp->unp_addr)
|
444 *nam = dup_sockaddr((struct sockaddr *)unp->unp_addr, 1);
|
446 *nam = sodupsockaddr((struct sockaddr *)unp->unp_addr, 447 M_WAITOK); |
448 else
|
446 *nam = dup_sockaddr((struct sockaddr *)&sun_noname, 1);
|
449 *nam = sodupsockaddr((struct sockaddr *)&sun_noname, 450 M_WAITOK); |
451 return (0); 452} 453 454struct pr_usrreqs uipc_usrreqs = { 455 uipc_abort, uipc_accept, uipc_attach, uipc_bind, uipc_connect, 456 uipc_connect2, pru_control_notsupp, uipc_detach, uipc_disconnect, 457 uipc_listen, uipc_peeraddr, uipc_rcvd, pru_rcvoob_notsupp, 458 uipc_send, uipc_sense, uipc_shutdown, uipc_sockaddr, 459 sosend, soreceive, sopoll, pru_sosetlabel_null 460}; 461 462int 463uipc_ctloutput(so, sopt) 464 struct socket *so; 465 struct sockopt *sopt; 466{ 467 struct unpcb *unp = sotounpcb(so); 468 int error; 469 470 switch (sopt->sopt_dir) { 471 case SOPT_GET: 472 switch (sopt->sopt_name) { 473 case LOCAL_PEERCRED: 474 if (unp->unp_flags & UNP_HAVEPC) 475 error = sooptcopyout(sopt, &unp->unp_peercred, 476 sizeof(unp->unp_peercred)); 477 else { 478 if (so->so_type == SOCK_STREAM) 479 error = ENOTCONN; 480 else 481 error = EINVAL; 482 } 483 break; 484 default: 485 error = EOPNOTSUPP; 486 break; 487 } 488 break; 489 case SOPT_SET: 490 default: 491 error = EOPNOTSUPP; 492 break; 493 } 494 return (error); 495} 496 497/* 498 * Both send and receive buffers are allocated PIPSIZ bytes of buffering 499 * for stream sockets, although the total for sender and receiver is 500 * actually only PIPSIZ. 501 * Datagram sockets really use the sendspace as the maximum datagram size, 502 * and don't really want to reserve the sendspace. Their recvspace should 503 * be large enough for at least one max-size datagram plus address. 504 */ 505#ifndef PIPSIZ 506#define PIPSIZ 8192 507#endif 508static u_long unpst_sendspace = PIPSIZ; 509static u_long unpst_recvspace = PIPSIZ; 510static u_long unpdg_sendspace = 2*1024; /* really max datagram size */ 511static u_long unpdg_recvspace = 4*1024; 512 513static int unp_rights; /* file descriptors in flight */ 514 515SYSCTL_DECL(_net_local_stream); 516SYSCTL_INT(_net_local_stream, OID_AUTO, sendspace, CTLFLAG_RW, 517 &unpst_sendspace, 0, ""); 518SYSCTL_INT(_net_local_stream, OID_AUTO, recvspace, CTLFLAG_RW, 519 &unpst_recvspace, 0, ""); 520SYSCTL_DECL(_net_local_dgram); 521SYSCTL_INT(_net_local_dgram, OID_AUTO, maxdgram, CTLFLAG_RW, 522 &unpdg_sendspace, 0, ""); 523SYSCTL_INT(_net_local_dgram, OID_AUTO, recvspace, CTLFLAG_RW, 524 &unpdg_recvspace, 0, ""); 525SYSCTL_DECL(_net_local); 526SYSCTL_INT(_net_local, OID_AUTO, inflight, CTLFLAG_RD, &unp_rights, 0, ""); 527 528static int 529unp_attach(so) 530 struct socket *so; 531{ 532 register struct unpcb *unp; 533 int error; 534 535 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 536 switch (so->so_type) { 537 538 case SOCK_STREAM: 539 error = soreserve(so, unpst_sendspace, unpst_recvspace); 540 break; 541 542 case SOCK_DGRAM: 543 error = soreserve(so, unpdg_sendspace, unpdg_recvspace); 544 break; 545 546 default: 547 panic("unp_attach"); 548 } 549 if (error) 550 return (error); 551 } 552 unp = uma_zalloc(unp_zone, M_WAITOK); 553 if (unp == NULL) 554 return (ENOBUFS); 555 bzero(unp, sizeof *unp); 556 unp->unp_gencnt = ++unp_gencnt; 557 unp_count++; 558 LIST_INIT(&unp->unp_refs); 559 unp->unp_socket = so; 560 LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead 561 : &unp_shead, unp, unp_link); 562 so->so_pcb = unp; 563 return (0); 564} 565 566static void 567unp_detach(unp) 568 register struct unpcb *unp; 569{ 570 LIST_REMOVE(unp, unp_link); 571 unp->unp_gencnt = ++unp_gencnt; 572 --unp_count; 573 if (unp->unp_vnode) { 574 unp->unp_vnode->v_socket = 0; 575 vrele(unp->unp_vnode); 576 unp->unp_vnode = 0; 577 } 578 if (unp->unp_conn) 579 unp_disconnect(unp); 580 while (!LIST_EMPTY(&unp->unp_refs)) 581 unp_drop(LIST_FIRST(&unp->unp_refs), ECONNRESET); 582 soisdisconnected(unp->unp_socket); 583 unp->unp_socket->so_pcb = 0; 584 if (unp_rights) { 585 /* 586 * Normally the receive buffer is flushed later, 587 * in sofree, but if our receive buffer holds references 588 * to descriptors that are now garbage, we will dispose 589 * of those descriptor references after the garbage collector 590 * gets them (resulting in a "panic: closef: count < 0"). 591 */ 592 sorflush(unp->unp_socket); 593 unp_gc(); 594 } 595 if (unp->unp_addr) 596 FREE(unp->unp_addr, M_SONAME); 597 uma_zfree(unp_zone, unp); 598} 599 600static int 601unp_bind(unp, nam, td) 602 struct unpcb *unp; 603 struct sockaddr *nam; 604 struct thread *td; 605{ 606 struct sockaddr_un *soun = (struct sockaddr_un *)nam; 607 struct vnode *vp; 608 struct mount *mp; 609 struct vattr vattr; 610 int error, namelen; 611 struct nameidata nd; 612 char *buf; 613 614 if (unp->unp_vnode != NULL) 615 return (EINVAL); 616 617 namelen = soun->sun_len - offsetof(struct sockaddr_un, sun_path); 618 if (namelen <= 0) 619 return (EINVAL); 620 621 buf = malloc(namelen + 1, M_TEMP, M_WAITOK); 622 strlcpy(buf, soun->sun_path, namelen + 1); 623 624restart: 625 NDINIT(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME, UIO_SYSSPACE, 626 buf, td); 627/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */ 628 error = namei(&nd); 629 if (error) { 630 free(buf, M_TEMP); 631 return (error); 632 } 633 vp = nd.ni_vp; 634 if (vp != NULL || vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 635 NDFREE(&nd, NDF_ONLY_PNBUF); 636 if (nd.ni_dvp == vp) 637 vrele(nd.ni_dvp); 638 else 639 vput(nd.ni_dvp); 640 if (vp != NULL) { 641 vrele(vp); 642 free(buf, M_TEMP); 643 return (EADDRINUSE); 644 } 645 error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH); 646 if (error) { 647 free(buf, M_TEMP); 648 return (error); 649 } 650 goto restart; 651 } 652 VATTR_NULL(&vattr); 653 vattr.va_type = VSOCK; 654 vattr.va_mode = (ACCESSPERMS & ~td->td_proc->p_fd->fd_cmask); 655#ifdef MAC 656 error = mac_check_vnode_create(td->td_ucred, nd.ni_dvp, &nd.ni_cnd, 657 &vattr); 658#endif 659 if (error == 0) { 660 VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE); 661 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 662 } 663 NDFREE(&nd, NDF_ONLY_PNBUF); 664 vput(nd.ni_dvp); 665 if (error) { 666 free(buf, M_TEMP); 667 return (error); 668 } 669 vp = nd.ni_vp; 670 vp->v_socket = unp->unp_socket; 671 unp->unp_vnode = vp;
|
668 unp->unp_addr = (struct sockaddr_un *)dup_sockaddr(nam, 1);
|
672 unp->unp_addr = (struct sockaddr_un *)sodupsockaddr(nam, M_WAITOK); |
673 VOP_UNLOCK(vp, 0, td); 674 vn_finished_write(mp); 675 free(buf, M_TEMP); 676 return (0); 677} 678 679static int 680unp_connect(so, nam, td) 681 struct socket *so; 682 struct sockaddr *nam; 683 struct thread *td; 684{ 685 register struct sockaddr_un *soun = (struct sockaddr_un *)nam; 686 register struct vnode *vp; 687 register struct socket *so2, *so3; 688 struct unpcb *unp, *unp2, *unp3; 689 int error, len; 690 struct nameidata nd; 691 char buf[SOCK_MAXADDRLEN]; 692 693 len = nam->sa_len - offsetof(struct sockaddr_un, sun_path); 694 if (len <= 0) 695 return (EINVAL); 696 strlcpy(buf, soun->sun_path, len + 1); 697 698 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, buf, td); 699 error = namei(&nd); 700 if (error) 701 return (error); 702 vp = nd.ni_vp; 703 NDFREE(&nd, NDF_ONLY_PNBUF); 704 if (vp->v_type != VSOCK) { 705 error = ENOTSOCK; 706 goto bad; 707 } 708 error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td); 709 if (error) 710 goto bad; 711 so2 = vp->v_socket; 712 if (so2 == 0) { 713 error = ECONNREFUSED; 714 goto bad; 715 } 716 if (so->so_type != so2->so_type) { 717 error = EPROTOTYPE; 718 goto bad; 719 } 720 if (so->so_proto->pr_flags & PR_CONNREQUIRED) { 721 if ((so2->so_options & SO_ACCEPTCONN) == 0 || 722 (so3 = sonewconn(so2, 0)) == 0) { 723 error = ECONNREFUSED; 724 goto bad; 725 } 726 unp = sotounpcb(so); 727 unp2 = sotounpcb(so2); 728 unp3 = sotounpcb(so3); 729 if (unp2->unp_addr) 730 unp3->unp_addr = (struct sockaddr_un *)
|
727 dup_sockaddr((struct sockaddr *)
728 unp2->unp_addr, 1);
|
731 sodupsockaddr((struct sockaddr *)unp2->unp_addr, 732 M_WAITOK); |
733 734 /* 735 * unp_peercred management: 736 * 737 * The connecter's (client's) credentials are copied 738 * from its process structure at the time of connect() 739 * (which is now). 740 */ 741 cru2x(td->td_ucred, &unp3->unp_peercred); 742 unp3->unp_flags |= UNP_HAVEPC; 743 /* 744 * The receiver's (server's) credentials are copied 745 * from the unp_peercred member of socket on which the 746 * former called listen(); unp_listen() cached that 747 * process's credentials at that time so we can use 748 * them now. 749 */ 750 KASSERT(unp2->unp_flags & UNP_HAVEPCCACHED, 751 ("unp_connect: listener without cached peercred")); 752 memcpy(&unp->unp_peercred, &unp2->unp_peercred, 753 sizeof(unp->unp_peercred)); 754 unp->unp_flags |= UNP_HAVEPC; 755#ifdef MAC 756 mac_set_socket_peer_from_socket(so, so3); 757 mac_set_socket_peer_from_socket(so3, so); 758#endif 759 760 so2 = so3; 761 } 762 error = unp_connect2(so, so2); 763bad: 764 vput(vp); 765 return (error); 766} 767 768int 769unp_connect2(so, so2) 770 register struct socket *so; 771 register struct socket *so2; 772{ 773 register struct unpcb *unp = sotounpcb(so); 774 register struct unpcb *unp2; 775 776 if (so2->so_type != so->so_type) 777 return (EPROTOTYPE); 778 unp2 = sotounpcb(so2); 779 unp->unp_conn = unp2; 780 switch (so->so_type) { 781 782 case SOCK_DGRAM: 783 LIST_INSERT_HEAD(&unp2->unp_refs, unp, unp_reflink); 784 soisconnected(so); 785 break; 786 787 case SOCK_STREAM: 788 unp2->unp_conn = unp; 789 soisconnected(so); 790 soisconnected(so2); 791 break; 792 793 default: 794 panic("unp_connect2"); 795 } 796 return (0); 797} 798 799static void 800unp_disconnect(unp) 801 struct unpcb *unp; 802{ 803 register struct unpcb *unp2 = unp->unp_conn; 804 805 if (unp2 == 0) 806 return; 807 unp->unp_conn = 0; 808 switch (unp->unp_socket->so_type) { 809 810 case SOCK_DGRAM: 811 LIST_REMOVE(unp, unp_reflink); 812 unp->unp_socket->so_state &= ~SS_ISCONNECTED; 813 break; 814 815 case SOCK_STREAM: 816 soisdisconnected(unp->unp_socket); 817 unp2->unp_conn = 0; 818 soisdisconnected(unp2->unp_socket); 819 break; 820 } 821} 822 823#ifdef notdef 824void 825unp_abort(unp) 826 struct unpcb *unp; 827{ 828 829 unp_detach(unp); 830} 831#endif 832 833static int 834unp_pcblist(SYSCTL_HANDLER_ARGS) 835{ 836 int error, i, n; 837 struct unpcb *unp, **unp_list; 838 unp_gen_t gencnt; 839 struct xunpgen *xug; 840 struct unp_head *head; 841 struct xunpcb *xu; 842 843 head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead); 844 845 /* 846 * The process of preparing the PCB list is too time-consuming and 847 * resource-intensive to repeat twice on every request. 848 */ 849 if (req->oldptr == 0) { 850 n = unp_count; 851 req->oldidx = 2 * (sizeof *xug) 852 + (n + n/8) * sizeof(struct xunpcb); 853 return (0); 854 } 855 856 if (req->newptr != 0) 857 return (EPERM); 858 859 /* 860 * OK, now we're committed to doing something. 861 */ 862 xug = malloc(sizeof(*xug), M_TEMP, M_WAITOK); 863 gencnt = unp_gencnt; 864 n = unp_count; 865 866 xug->xug_len = sizeof *xug; 867 xug->xug_count = n; 868 xug->xug_gen = gencnt; 869 xug->xug_sogen = so_gencnt; 870 error = SYSCTL_OUT(req, xug, sizeof *xug); 871 if (error) { 872 free(xug, M_TEMP); 873 return (error); 874 } 875 876 unp_list = malloc(n * sizeof *unp_list, M_TEMP, M_WAITOK); 877 878 for (unp = LIST_FIRST(head), i = 0; unp && i < n; 879 unp = LIST_NEXT(unp, unp_link)) { 880 if (unp->unp_gencnt <= gencnt) { 881 if (cr_cansee(req->td->td_ucred, 882 unp->unp_socket->so_cred)) 883 continue; 884 unp_list[i++] = unp; 885 } 886 } 887 n = i; /* in case we lost some during malloc */ 888 889 error = 0; 890 xu = malloc(sizeof(*xu), M_TEMP, M_WAITOK); 891 for (i = 0; i < n; i++) { 892 unp = unp_list[i]; 893 if (unp->unp_gencnt <= gencnt) { 894 xu->xu_len = sizeof *xu; 895 xu->xu_unpp = unp; 896 /* 897 * XXX - need more locking here to protect against 898 * connect/disconnect races for SMP. 899 */ 900 if (unp->unp_addr) 901 bcopy(unp->unp_addr, &xu->xu_addr, 902 unp->unp_addr->sun_len); 903 if (unp->unp_conn && unp->unp_conn->unp_addr) 904 bcopy(unp->unp_conn->unp_addr, 905 &xu->xu_caddr, 906 unp->unp_conn->unp_addr->sun_len); 907 bcopy(unp, &xu->xu_unp, sizeof *unp); 908 sotoxsocket(unp->unp_socket, &xu->xu_socket); 909 error = SYSCTL_OUT(req, xu, sizeof *xu); 910 } 911 } 912 free(xu, M_TEMP); 913 if (!error) { 914 /* 915 * Give the user an updated idea of our state. 916 * If the generation differs from what we told 917 * her before, she knows that something happened 918 * while we were processing this request, and it 919 * might be necessary to retry. 920 */ 921 xug->xug_gen = unp_gencnt; 922 xug->xug_sogen = so_gencnt; 923 xug->xug_count = unp_count; 924 error = SYSCTL_OUT(req, xug, sizeof *xug); 925 } 926 free(unp_list, M_TEMP); 927 free(xug, M_TEMP); 928 return (error); 929} 930 931SYSCTL_PROC(_net_local_dgram, OID_AUTO, pcblist, CTLFLAG_RD, 932 (caddr_t)(long)SOCK_DGRAM, 0, unp_pcblist, "S,xunpcb", 933 "List of active local datagram sockets"); 934SYSCTL_PROC(_net_local_stream, OID_AUTO, pcblist, CTLFLAG_RD, 935 (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb", 936 "List of active local stream sockets"); 937 938static void 939unp_shutdown(unp) 940 struct unpcb *unp; 941{ 942 struct socket *so; 943 944 if (unp->unp_socket->so_type == SOCK_STREAM && unp->unp_conn && 945 (so = unp->unp_conn->unp_socket)) 946 socantrcvmore(so); 947} 948 949static void 950unp_drop(unp, errno) 951 struct unpcb *unp; 952 int errno; 953{ 954 struct socket *so = unp->unp_socket; 955 956 so->so_error = errno; 957 unp_disconnect(unp); 958} 959 960#ifdef notdef 961void 962unp_drain() 963{ 964 965} 966#endif 967 968static void 969unp_freerights(rp, fdcount) 970 struct file **rp; 971 int fdcount; 972{ 973 int i; 974 struct file *fp; 975 976 for (i = 0; i < fdcount; i++) { 977 fp = *rp; 978 /* 979 * zero the pointer before calling 980 * unp_discard since it may end up 981 * in unp_gc().. 982 */ 983 *rp++ = 0; 984 unp_discard(fp); 985 } 986} 987 988int 989unp_externalize(control, controlp) 990 struct mbuf *control, **controlp; 991{ 992 struct thread *td = curthread; /* XXX */ 993 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 994 int i; 995 int *fdp; 996 struct file **rp; 997 struct file *fp; 998 void *data; 999 socklen_t clen = control->m_len, datalen; 1000 int error, newfds; 1001 int f; 1002 u_int newlen; 1003 1004 error = 0; 1005 if (controlp != NULL) /* controlp == NULL => free control messages */ 1006 *controlp = NULL; 1007 1008 while (cm != NULL) { 1009 if (sizeof(*cm) > clen || cm->cmsg_len > clen) { 1010 error = EINVAL; 1011 break; 1012 } 1013 1014 data = CMSG_DATA(cm); 1015 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1016 1017 if (cm->cmsg_level == SOL_SOCKET 1018 && cm->cmsg_type == SCM_RIGHTS) { 1019 newfds = datalen / sizeof(struct file *); 1020 rp = data; 1021 1022 /* If we're not outputting the descriptors free them. */ 1023 if (error || controlp == NULL) { 1024 unp_freerights(rp, newfds); 1025 goto next; 1026 } 1027 FILEDESC_LOCK(td->td_proc->p_fd); 1028 /* if the new FD's will not fit free them. */ 1029 if (!fdavail(td, newfds)) { 1030 FILEDESC_UNLOCK(td->td_proc->p_fd); 1031 error = EMSGSIZE; 1032 unp_freerights(rp, newfds); 1033 goto next; 1034 } 1035 /* 1036 * now change each pointer to an fd in the global 1037 * table to an integer that is the index to the 1038 * local fd table entry that we set up to point 1039 * to the global one we are transferring. 1040 */ 1041 newlen = newfds * sizeof(int); 1042 *controlp = sbcreatecontrol(NULL, newlen, 1043 SCM_RIGHTS, SOL_SOCKET); 1044 if (*controlp == NULL) { 1045 FILEDESC_UNLOCK(td->td_proc->p_fd); 1046 error = E2BIG; 1047 unp_freerights(rp, newfds); 1048 goto next; 1049 } 1050 1051 fdp = (int *) 1052 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1053 for (i = 0; i < newfds; i++) { 1054 if (fdalloc(td, 0, &f)) 1055 panic("unp_externalize fdalloc failed"); 1056 fp = *rp++; 1057 td->td_proc->p_fd->fd_ofiles[f] = fp; 1058 FILE_LOCK(fp); 1059 fp->f_msgcount--; 1060 FILE_UNLOCK(fp); 1061 unp_rights--; 1062 *fdp++ = f; 1063 } 1064 FILEDESC_UNLOCK(td->td_proc->p_fd); 1065 } else { /* We can just copy anything else across */ 1066 if (error || controlp == NULL) 1067 goto next; 1068 *controlp = sbcreatecontrol(NULL, datalen, 1069 cm->cmsg_type, cm->cmsg_level); 1070 if (*controlp == NULL) { 1071 error = ENOBUFS; 1072 goto next; 1073 } 1074 bcopy(data, 1075 CMSG_DATA(mtod(*controlp, struct cmsghdr *)), 1076 datalen); 1077 } 1078 1079 controlp = &(*controlp)->m_next; 1080 1081next: 1082 if (CMSG_SPACE(datalen) < clen) { 1083 clen -= CMSG_SPACE(datalen); 1084 cm = (struct cmsghdr *) 1085 ((caddr_t)cm + CMSG_SPACE(datalen)); 1086 } else { 1087 clen = 0; 1088 cm = NULL; 1089 } 1090 } 1091 1092 m_freem(control); 1093 1094 return (error); 1095} 1096 1097void 1098unp_init(void) 1099{ 1100 unp_zone = uma_zcreate("unpcb", sizeof(struct unpcb), NULL, NULL, 1101 NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); 1102 if (unp_zone == 0) 1103 panic("unp_init"); 1104 uma_zone_set_max(unp_zone, nmbclusters); 1105 LIST_INIT(&unp_dhead); 1106 LIST_INIT(&unp_shead); 1107} 1108 1109static int 1110unp_internalize(controlp, td) 1111 struct mbuf **controlp; 1112 struct thread *td; 1113{ 1114 struct mbuf *control = *controlp; 1115 struct proc *p = td->td_proc; 1116 struct filedesc *fdescp = p->p_fd; 1117 struct cmsghdr *cm = mtod(control, struct cmsghdr *); 1118 struct cmsgcred *cmcred; 1119 struct file **rp; 1120 struct file *fp; 1121 struct timeval *tv; 1122 int i, fd, *fdp; 1123 void *data; 1124 socklen_t clen = control->m_len, datalen; 1125 int error, oldfds; 1126 u_int newlen; 1127 1128 error = 0; 1129 *controlp = NULL; 1130 1131 while (cm != NULL) { 1132 if (sizeof(*cm) > clen || cm->cmsg_level != SOL_SOCKET 1133 || cm->cmsg_len > clen) { 1134 error = EINVAL; 1135 goto out; 1136 } 1137 1138 data = CMSG_DATA(cm); 1139 datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; 1140 1141 switch (cm->cmsg_type) { 1142 /* 1143 * Fill in credential information. 1144 */ 1145 case SCM_CREDS: 1146 *controlp = sbcreatecontrol(NULL, sizeof(*cmcred), 1147 SCM_CREDS, SOL_SOCKET); 1148 if (*controlp == NULL) { 1149 error = ENOBUFS; 1150 goto out; 1151 } 1152 1153 cmcred = (struct cmsgcred *) 1154 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1155 cmcred->cmcred_pid = p->p_pid; 1156 cmcred->cmcred_uid = td->td_ucred->cr_ruid; 1157 cmcred->cmcred_gid = td->td_ucred->cr_rgid; 1158 cmcred->cmcred_euid = td->td_ucred->cr_uid; 1159 cmcred->cmcred_ngroups = MIN(td->td_ucred->cr_ngroups, 1160 CMGROUP_MAX); 1161 for (i = 0; i < cmcred->cmcred_ngroups; i++) 1162 cmcred->cmcred_groups[i] = 1163 td->td_ucred->cr_groups[i]; 1164 break; 1165 1166 case SCM_RIGHTS: 1167 oldfds = datalen / sizeof (int); 1168 /* 1169 * check that all the FDs passed in refer to legal files 1170 * If not, reject the entire operation. 1171 */ 1172 fdp = data; 1173 FILEDESC_LOCK(fdescp); 1174 for (i = 0; i < oldfds; i++) { 1175 fd = *fdp++; 1176 if ((unsigned)fd >= fdescp->fd_nfiles || 1177 fdescp->fd_ofiles[fd] == NULL) { 1178 FILEDESC_UNLOCK(fdescp); 1179 error = EBADF; 1180 goto out; 1181 } 1182 fp = fdescp->fd_ofiles[fd]; 1183 if (!(fp->f_ops->fo_flags & DFLAG_PASSABLE)) { 1184 FILEDESC_UNLOCK(fdescp); 1185 error = EOPNOTSUPP; 1186 goto out; 1187 } 1188 1189 } 1190 /* 1191 * Now replace the integer FDs with pointers to 1192 * the associated global file table entry.. 1193 */ 1194 newlen = oldfds * sizeof(struct file *); 1195 *controlp = sbcreatecontrol(NULL, newlen, 1196 SCM_RIGHTS, SOL_SOCKET); 1197 if (*controlp == NULL) { 1198 FILEDESC_UNLOCK(fdescp); 1199 error = E2BIG; 1200 goto out; 1201 } 1202 1203 fdp = data; 1204 rp = (struct file **) 1205 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1206 for (i = 0; i < oldfds; i++) { 1207 fp = fdescp->fd_ofiles[*fdp++]; 1208 *rp++ = fp; 1209 FILE_LOCK(fp); 1210 fp->f_count++; 1211 fp->f_msgcount++; 1212 FILE_UNLOCK(fp); 1213 unp_rights++; 1214 } 1215 FILEDESC_UNLOCK(fdescp); 1216 break; 1217 1218 case SCM_TIMESTAMP: 1219 *controlp = sbcreatecontrol(NULL, sizeof(*tv), 1220 SCM_TIMESTAMP, SOL_SOCKET); 1221 if (*controlp == NULL) { 1222 error = ENOBUFS; 1223 goto out; 1224 } 1225 tv = (struct timeval *) 1226 CMSG_DATA(mtod(*controlp, struct cmsghdr *)); 1227 microtime(tv); 1228 break; 1229 1230 default: 1231 error = EINVAL; 1232 goto out; 1233 } 1234 1235 controlp = &(*controlp)->m_next; 1236 1237 if (CMSG_SPACE(datalen) < clen) { 1238 clen -= CMSG_SPACE(datalen); 1239 cm = (struct cmsghdr *) 1240 ((caddr_t)cm + CMSG_SPACE(datalen)); 1241 } else { 1242 clen = 0; 1243 cm = NULL; 1244 } 1245 } 1246 1247out: 1248 m_freem(control); 1249 1250 return (error); 1251} 1252 1253static int unp_defer, unp_gcing; 1254 1255static void 1256unp_gc() 1257{ 1258 register struct file *fp, *nextfp; 1259 register struct socket *so; 1260 struct file **extra_ref, **fpp; 1261 int nunref, i; 1262 1263 if (unp_gcing) 1264 return; 1265 unp_gcing = 1; 1266 unp_defer = 0; 1267 /* 1268 * before going through all this, set all FDs to 1269 * be NOT defered and NOT externally accessible 1270 */ 1271 sx_slock(&filelist_lock); 1272 LIST_FOREACH(fp, &filehead, f_list) 1273 fp->f_gcflag &= ~(FMARK|FDEFER); 1274 do { 1275 LIST_FOREACH(fp, &filehead, f_list) { 1276 FILE_LOCK(fp); 1277 /* 1278 * If the file is not open, skip it 1279 */ 1280 if (fp->f_count == 0) { 1281 FILE_UNLOCK(fp); 1282 continue; 1283 } 1284 /* 1285 * If we already marked it as 'defer' in a 1286 * previous pass, then try process it this time 1287 * and un-mark it 1288 */ 1289 if (fp->f_gcflag & FDEFER) { 1290 fp->f_gcflag &= ~FDEFER; 1291 unp_defer--; 1292 } else { 1293 /* 1294 * if it's not defered, then check if it's 1295 * already marked.. if so skip it 1296 */ 1297 if (fp->f_gcflag & FMARK) { 1298 FILE_UNLOCK(fp); 1299 continue; 1300 } 1301 /* 1302 * If all references are from messages 1303 * in transit, then skip it. it's not 1304 * externally accessible. 1305 */ 1306 if (fp->f_count == fp->f_msgcount) { 1307 FILE_UNLOCK(fp); 1308 continue; 1309 } 1310 /* 1311 * If it got this far then it must be 1312 * externally accessible. 1313 */ 1314 fp->f_gcflag |= FMARK; 1315 } 1316 /* 1317 * either it was defered, or it is externally 1318 * accessible and not already marked so. 1319 * Now check if it is possibly one of OUR sockets. 1320 */ 1321 if (fp->f_type != DTYPE_SOCKET || 1322 (so = fp->f_data) == NULL) { 1323 FILE_UNLOCK(fp); 1324 continue; 1325 } 1326 FILE_UNLOCK(fp); 1327 if (so->so_proto->pr_domain != &localdomain || 1328 (so->so_proto->pr_flags&PR_RIGHTS) == 0) 1329 continue; 1330#ifdef notdef 1331 if (so->so_rcv.sb_flags & SB_LOCK) { 1332 /* 1333 * This is problematical; it's not clear 1334 * we need to wait for the sockbuf to be 1335 * unlocked (on a uniprocessor, at least), 1336 * and it's also not clear what to do 1337 * if sbwait returns an error due to receipt 1338 * of a signal. If sbwait does return 1339 * an error, we'll go into an infinite 1340 * loop. Delete all of this for now. 1341 */ 1342 (void) sbwait(&so->so_rcv); 1343 goto restart; 1344 } 1345#endif 1346 /* 1347 * So, Ok, it's one of our sockets and it IS externally 1348 * accessible (or was defered). Now we look 1349 * to see if we hold any file descriptors in its 1350 * message buffers. Follow those links and mark them 1351 * as accessible too. 1352 */ 1353 unp_scan(so->so_rcv.sb_mb, unp_mark); 1354 } 1355 } while (unp_defer); 1356 sx_sunlock(&filelist_lock); 1357 /* 1358 * We grab an extra reference to each of the file table entries 1359 * that are not otherwise accessible and then free the rights 1360 * that are stored in messages on them. 1361 * 1362 * The bug in the orginal code is a little tricky, so I'll describe 1363 * what's wrong with it here. 1364 * 1365 * It is incorrect to simply unp_discard each entry for f_msgcount 1366 * times -- consider the case of sockets A and B that contain 1367 * references to each other. On a last close of some other socket, 1368 * we trigger a gc since the number of outstanding rights (unp_rights) 1369 * is non-zero. If during the sweep phase the gc code un_discards, 1370 * we end up doing a (full) closef on the descriptor. A closef on A 1371 * results in the following chain. Closef calls soo_close, which 1372 * calls soclose. Soclose calls first (through the switch 1373 * uipc_usrreq) unp_detach, which re-invokes unp_gc. Unp_gc simply 1374 * returns because the previous instance had set unp_gcing, and 1375 * we return all the way back to soclose, which marks the socket 1376 * with SS_NOFDREF, and then calls sofree. Sofree calls sorflush 1377 * to free up the rights that are queued in messages on the socket A, 1378 * i.e., the reference on B. The sorflush calls via the dom_dispose 1379 * switch unp_dispose, which unp_scans with unp_discard. This second 1380 * instance of unp_discard just calls closef on B. 1381 * 1382 * Well, a similar chain occurs on B, resulting in a sorflush on B, 1383 * which results in another closef on A. Unfortunately, A is already 1384 * being closed, and the descriptor has already been marked with 1385 * SS_NOFDREF, and soclose panics at this point. 1386 * 1387 * Here, we first take an extra reference to each inaccessible 1388 * descriptor. Then, we call sorflush ourself, since we know 1389 * it is a Unix domain socket anyhow. After we destroy all the 1390 * rights carried in messages, we do a last closef to get rid 1391 * of our extra reference. This is the last close, and the 1392 * unp_detach etc will shut down the socket. 1393 * 1394 * 91/09/19, bsy@cs.cmu.edu 1395 */ 1396 extra_ref = malloc(nfiles * sizeof(struct file *), M_TEMP, M_WAITOK); 1397 sx_slock(&filelist_lock); 1398 for (nunref = 0, fp = LIST_FIRST(&filehead), fpp = extra_ref; fp != 0; 1399 fp = nextfp) { 1400 nextfp = LIST_NEXT(fp, f_list); 1401 FILE_LOCK(fp); 1402 /* 1403 * If it's not open, skip it 1404 */ 1405 if (fp->f_count == 0) { 1406 FILE_UNLOCK(fp); 1407 continue; 1408 } 1409 /* 1410 * If all refs are from msgs, and it's not marked accessible 1411 * then it must be referenced from some unreachable cycle 1412 * of (shut-down) FDs, so include it in our 1413 * list of FDs to remove 1414 */ 1415 if (fp->f_count == fp->f_msgcount && !(fp->f_gcflag & FMARK)) { 1416 *fpp++ = fp; 1417 nunref++; 1418 fp->f_count++; 1419 } 1420 FILE_UNLOCK(fp); 1421 } 1422 sx_sunlock(&filelist_lock); 1423 /* 1424 * for each FD on our hit list, do the following two things 1425 */ 1426 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) { 1427 struct file *tfp = *fpp; 1428 FILE_LOCK(tfp); 1429 if (tfp->f_type == DTYPE_SOCKET && 1430 tfp->f_data != NULL) { 1431 FILE_UNLOCK(tfp); 1432 sorflush(tfp->f_data); 1433 } else { 1434 FILE_UNLOCK(tfp); 1435 } 1436 } 1437 for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp) 1438 closef(*fpp, (struct thread *) NULL); 1439 free(extra_ref, M_TEMP); 1440 unp_gcing = 0; 1441} 1442 1443void 1444unp_dispose(m) 1445 struct mbuf *m; 1446{ 1447 1448 if (m) 1449 unp_scan(m, unp_discard); 1450} 1451 1452static int 1453unp_listen(unp, td) 1454 struct unpcb *unp; 1455 struct thread *td; 1456{ 1457 1458 cru2x(td->td_ucred, &unp->unp_peercred); 1459 unp->unp_flags |= UNP_HAVEPCCACHED; 1460 return (0); 1461} 1462 1463static void 1464unp_scan(m0, op) 1465 register struct mbuf *m0; 1466 void (*op)(struct file *); 1467{ 1468 struct mbuf *m; 1469 struct file **rp; 1470 struct cmsghdr *cm; 1471 void *data; 1472 int i; 1473 socklen_t clen, datalen; 1474 int qfds; 1475 1476 while (m0) { 1477 for (m = m0; m; m = m->m_next) { 1478 if (m->m_type != MT_CONTROL) 1479 continue; 1480 1481 cm = mtod(m, struct cmsghdr *); 1482 clen = m->m_len; 1483 1484 while (cm != NULL) { 1485 if (sizeof(*cm) > clen || cm->cmsg_len > clen) 1486 break; 1487 1488 data = CMSG_DATA(cm); 1489 datalen = (caddr_t)cm + cm->cmsg_len 1490 - (caddr_t)data; 1491 1492 if (cm->cmsg_level == SOL_SOCKET && 1493 cm->cmsg_type == SCM_RIGHTS) { 1494 qfds = datalen / sizeof (struct file *); 1495 rp = data; 1496 for (i = 0; i < qfds; i++) 1497 (*op)(*rp++); 1498 } 1499 1500 if (CMSG_SPACE(datalen) < clen) { 1501 clen -= CMSG_SPACE(datalen); 1502 cm = (struct cmsghdr *) 1503 ((caddr_t)cm + CMSG_SPACE(datalen)); 1504 } else { 1505 clen = 0; 1506 cm = NULL; 1507 } 1508 } 1509 } 1510 m0 = m0->m_act; 1511 } 1512} 1513 1514static void 1515unp_mark(fp) 1516 struct file *fp; 1517{ 1518 if (fp->f_gcflag & FMARK) 1519 return; 1520 unp_defer++; 1521 fp->f_gcflag |= (FMARK|FDEFER); 1522} 1523 1524static void 1525unp_discard(fp) 1526 struct file *fp; 1527{ 1528 FILE_LOCK(fp); 1529 fp->f_msgcount--; 1530 unp_rights--; 1531 FILE_UNLOCK(fp); 1532 (void) closef(fp, (struct thread *)NULL); 1533}
|