Print this page
14619 Race between udp_activate() and conn_get_socket_info()

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/ip/ipclassifier.c
          +++ new/usr/src/uts/common/inet/ip/ipclassifier.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
  24      - * Copyright 2020 Joyent, Inc.
       24 + * Copyright 2022 Joyent, Inc.
  25   25   */
  26   26  
  27   27  /*
  28   28   * IP PACKET CLASSIFIER
  29   29   *
  30   30   * The IP packet classifier provides mapping between IP packets and persistent
  31   31   * connection state for connection-oriented protocols. It also provides
  32   32   * interface for managing connection states.
  33   33   *
  34   34   * The connection state is kept in conn_t data structure and contains, among
↓ open down ↓ 2690 lines elided ↑ open up ↑
2725 2725          return (1);
2726 2726  }
2727 2727  #endif
2728 2728  
2729 2729  mib2_socketInfoEntry_t *
2730 2730  conn_get_socket_info(conn_t *connp, mib2_socketInfoEntry_t *sie)
2731 2731  {
2732 2732          vnode_t *vn = NULL;
2733 2733          vattr_t attr;
2734 2734          uint64_t flags = 0;
     2735 +        sock_upcalls_t *upcalls;
     2736 +        sock_upper_handle_t upper_handle;
2735 2737  
2736 2738          /*
2737 2739           * If the connection is closing, it is not safe to make an upcall or
2738 2740           * access the stream associated with the connection.
2739 2741           * The callers of this function have a reference on connp itself
2740 2742           * so, as long as it is not closing, it's safe to continue.
2741 2743           */
2742 2744          mutex_enter(&connp->conn_lock);
2743 2745  
2744 2746          if ((connp->conn_state_flags & CONN_CLOSING)) {
2745 2747                  mutex_exit(&connp->conn_lock);
2746 2748                  return (NULL);
2747 2749          }
2748 2750  
2749 2751          /*
2750 2752           * Continue to hold conn_lock because we don't want to race with an
2751 2753           * in-progress close, which will have set-to-NULL (and destroyed
2752 2754           * upper_handle, aka sonode (and vnode)) BEFORE setting CONN_CLOSING.
     2755 +         *
     2756 +         * There is still a race with an in-progress OPEN, however, where
     2757 +         * conn_upper_handle and conn_upcalls are being assigned (in multiple
     2758 +         * codepaths) WITHOUT conn_lock being held.  We address that race
     2759 +         * HERE, however, given that both are going from NULL to non-NULL,
     2760 +         * if we lose the race, we don't get any data for the in-progress-OPEN
     2761 +         * socket.
2753 2762           */
2754 2763  
2755      -        if (connp->conn_upper_handle != NULL) {
2756      -                vn = (*connp->conn_upcalls->su_get_vnode)
2757      -                    (connp->conn_upper_handle);
     2764 +        upcalls = connp->conn_upcalls;
     2765 +        upper_handle = connp->conn_upper_handle;
     2766 +        /* Check BOTH for non-NULL before attempting an upcall. */
     2767 +        if (upper_handle != NULL && upcalls != NULL) {
     2768 +                /* su_get_vnode() returns one with VN_HOLD() already done. */
     2769 +                vn = upcalls->su_get_vnode(upper_handle);
2758 2770          } else if (!IPCL_IS_NONSTR(connp) && connp->conn_rq != NULL) {
2759 2771                  vn = STREAM(connp->conn_rq)->sd_pvnode;
2760 2772                  if (vn != NULL)
2761 2773                          VN_HOLD(vn);
2762 2774                  flags |= MIB2_SOCKINFO_STREAM;
2763 2775          }
2764 2776  
2765 2777          mutex_exit(&connp->conn_lock);
2766 2778  
2767 2779          if (vn == NULL || VOP_GETATTR(vn, &attr, 0, CRED(), NULL) != 0) {
↓ open down ↓ 15 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX