Print this page
12976 system panics with error in IP module
Reviewed by: Andy Fiddaman <andy@omniosce.org>
Reviewed by: Paul Winder <p.winder@me.com>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2019 Joyent, Inc.
  25  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
  26  * Copyright (c) 2013, 2017 by Delphix. All rights reserved.
  27  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.

  28  */
  29 /* Copyright (c) 1990 Mentat Inc. */
  30 
  31 #include <sys/types.h>
  32 #include <sys/stream.h>
  33 #include <sys/strsun.h>
  34 #include <sys/strsubr.h>
  35 #include <sys/stropts.h>
  36 #include <sys/strlog.h>
  37 #define _SUN_TPI_VERSION 2
  38 #include <sys/tihdr.h>
  39 #include <sys/timod.h>
  40 #include <sys/ddi.h>
  41 #include <sys/sunddi.h>
  42 #include <sys/suntpi.h>
  43 #include <sys/xti_inet.h>
  44 #include <sys/cmn_err.h>
  45 #include <sys/debug.h>
  46 #include <sys/sdt.h>
  47 #include <sys/vtrace.h>


1002                         tcp->tcp_timer_tid = TCP_TIMER(tcp, tcp_timer,
1003                             delta ? delta : 1);
1004                 }
1005         } else {
1006                 tcp_closei_local(tcp);
1007                 CONN_DEC_REF(connp);
1008         }
1009 finish:
1010         tcp->tcp_detached = B_TRUE;
1011         connp->conn_rq = NULL;
1012         connp->conn_wq = NULL;
1013 
1014         /* Signal closing thread that it can complete close */
1015         mutex_enter(&tcp->tcp_closelock);
1016         tcp->tcp_closed = 1;
1017         cv_signal(&tcp->tcp_closecv);
1018         mutex_exit(&tcp->tcp_closelock);
1019 
1020         /* If we have an upper handle (socket), release it */
1021         if (IPCL_IS_NONSTR(connp)) {
1022                 ASSERT(connp->conn_upper_handle != NULL);
1023                 (*connp->conn_upcalls->su_closed)(connp->conn_upper_handle);











1024                 connp->conn_upper_handle = NULL;
1025                 connp->conn_upcalls = NULL;


1026         }
1027 }
1028 
1029 void
1030 tcp_close_common(conn_t *connp, int flags)
1031 {
1032         tcp_t           *tcp = connp->conn_tcp;
1033         mblk_t          *mp = &tcp->tcp_closemp;
1034         boolean_t       conn_ioctl_cleanup_reqd = B_FALSE;
1035         mblk_t          *bp;
1036 
1037         ASSERT(connp->conn_ref >= 2);
1038 
1039         /*
1040          * Mark the conn as closing. ipsq_pending_mp_add will not
1041          * add any mp to the pending mp list, after this conn has
1042          * started closing.
1043          */
1044         mutex_enter(&connp->conn_lock);
1045         connp->conn_state_flags |= CONN_CLOSING;


1404         ASSERT(tcp->tcp_rthdrlen == 0);
1405 
1406         /*
1407          * Following is really a blowing away a union.
1408          * It happens to have exactly two members of identical size
1409          * the following code is enough.
1410          */
1411         tcp_close_mpp(&tcp->tcp_conn.tcp_eager_conn_ind);
1412 
1413         /* Allow the CC algorithm to clean up after itself. */
1414         if (tcp->tcp_cc_algo != NULL && tcp->tcp_cc_algo->cb_destroy != NULL)
1415                 tcp->tcp_cc_algo->cb_destroy(&tcp->tcp_ccv);
1416 
1417         /*
1418          * If this is a non-STREAM socket still holding on to an upper
1419          * handle, release it. As a result of fallback we might also see
1420          * STREAMS based conns with upper handles, in which case there is
1421          * nothing to do other than clearing the field.
1422          */
1423         if (connp->conn_upper_handle != NULL) {













1424                 if (IPCL_IS_NONSTR(connp)) {
1425                         (*connp->conn_upcalls->su_closed)(
1426                             connp->conn_upper_handle);


1427                         tcp->tcp_detached = B_TRUE;
1428                 }
1429                 connp->conn_upper_handle = NULL;
1430                 connp->conn_upcalls = NULL;
1431         }
1432 }
1433 
1434 /*
1435  * tcp_get_conn/tcp_free_conn
1436  *
1437  * tcp_get_conn is used to get a clean tcp connection structure.
1438  * It tries to reuse the connections put on the freelist by the
1439  * time_wait_collector failing which it goes to kmem_cache. This
1440  * way has two benefits compared to just allocating from and
1441  * freeing to kmem_cache.
1442  * 1) The time_wait_collector can free (which includes the cleanup)
1443  * outside the squeue. So when the interrupt comes, we have a clean
1444  * connection sitting in the freelist. Obviously, this buys us
1445  * performance.
1446  *
1447  * 2) Defence against DOS attack. Allocating a tcp/conn in tcp_input_listener
1448  * has multiple disadvantages - tying up the squeue during alloc.
1449  * But allocating the conn/tcp in IP land is also not the best since
1450  * we can't check the 'q' and 'q0' which are protected by squeue and




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.

  24  * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright (c) 2013, 2017 by Delphix. All rights reserved.
  26  * Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved.
  27  * Copyright 2020 Joyent, Inc.
  28  */
  29 /* Copyright (c) 1990 Mentat Inc. */
  30 
  31 #include <sys/types.h>
  32 #include <sys/stream.h>
  33 #include <sys/strsun.h>
  34 #include <sys/strsubr.h>
  35 #include <sys/stropts.h>
  36 #include <sys/strlog.h>
  37 #define _SUN_TPI_VERSION 2
  38 #include <sys/tihdr.h>
  39 #include <sys/timod.h>
  40 #include <sys/ddi.h>
  41 #include <sys/sunddi.h>
  42 #include <sys/suntpi.h>
  43 #include <sys/xti_inet.h>
  44 #include <sys/cmn_err.h>
  45 #include <sys/debug.h>
  46 #include <sys/sdt.h>
  47 #include <sys/vtrace.h>


1002                         tcp->tcp_timer_tid = TCP_TIMER(tcp, tcp_timer,
1003                             delta ? delta : 1);
1004                 }
1005         } else {
1006                 tcp_closei_local(tcp);
1007                 CONN_DEC_REF(connp);
1008         }
1009 finish:
1010         tcp->tcp_detached = B_TRUE;
1011         connp->conn_rq = NULL;
1012         connp->conn_wq = NULL;
1013 
1014         /* Signal closing thread that it can complete close */
1015         mutex_enter(&tcp->tcp_closelock);
1016         tcp->tcp_closed = 1;
1017         cv_signal(&tcp->tcp_closecv);
1018         mutex_exit(&tcp->tcp_closelock);
1019 
1020         /* If we have an upper handle (socket), release it */
1021         if (IPCL_IS_NONSTR(connp)) {
1022                 sock_upcalls_t *upcalls = connp->conn_upcalls;
1023                 sock_upper_handle_t handle = connp->conn_upper_handle;
1024 
1025                 ASSERT(upcalls != NULL);
1026                 ASSERT(upcalls->su_closed != NULL);
1027                 ASSERT(handle != NULL);
1028                 /*
1029                  * Set these to NULL first because closed() will free upper
1030                  * structures.  Acquire conn_lock because an external caller
1031                  * like conn_get_socket_info() will upcall if these are
1032                  * non-NULL.
1033                  */
1034                 mutex_enter(&connp->conn_lock);
1035                 connp->conn_upper_handle = NULL;
1036                 connp->conn_upcalls = NULL;
1037                 mutex_exit(&connp->conn_lock);
1038                 upcalls->su_closed(handle);
1039         }
1040 }
1041 
1042 void
1043 tcp_close_common(conn_t *connp, int flags)
1044 {
1045         tcp_t           *tcp = connp->conn_tcp;
1046         mblk_t          *mp = &tcp->tcp_closemp;
1047         boolean_t       conn_ioctl_cleanup_reqd = B_FALSE;
1048         mblk_t          *bp;
1049 
1050         ASSERT(connp->conn_ref >= 2);
1051 
1052         /*
1053          * Mark the conn as closing. ipsq_pending_mp_add will not
1054          * add any mp to the pending mp list, after this conn has
1055          * started closing.
1056          */
1057         mutex_enter(&connp->conn_lock);
1058         connp->conn_state_flags |= CONN_CLOSING;


1417         ASSERT(tcp->tcp_rthdrlen == 0);
1418 
1419         /*
1420          * Following is really a blowing away a union.
1421          * It happens to have exactly two members of identical size
1422          * the following code is enough.
1423          */
1424         tcp_close_mpp(&tcp->tcp_conn.tcp_eager_conn_ind);
1425 
1426         /* Allow the CC algorithm to clean up after itself. */
1427         if (tcp->tcp_cc_algo != NULL && tcp->tcp_cc_algo->cb_destroy != NULL)
1428                 tcp->tcp_cc_algo->cb_destroy(&tcp->tcp_ccv);
1429 
1430         /*
1431          * If this is a non-STREAM socket still holding on to an upper
1432          * handle, release it. As a result of fallback we might also see
1433          * STREAMS based conns with upper handles, in which case there is
1434          * nothing to do other than clearing the field.
1435          */
1436         if (connp->conn_upper_handle != NULL) {
1437                 sock_upcalls_t *upcalls = connp->conn_upcalls;
1438                 sock_upper_handle_t handle = connp->conn_upper_handle;
1439 
1440                 /*
1441                  * Set these to NULL first because closed() will free upper
1442                  * structures.  Acquire conn_lock because an external caller
1443                  * like conn_get_socket_info() will upcall if these are
1444                  * non-NULL.
1445                  */
1446                 mutex_enter(&connp->conn_lock);
1447                 connp->conn_upper_handle = NULL;
1448                 connp->conn_upcalls = NULL;
1449                 mutex_exit(&connp->conn_lock);
1450                 if (IPCL_IS_NONSTR(connp)) {
1451                         ASSERT(upcalls != NULL);
1452                         ASSERT(upcalls->su_closed != NULL);
1453                         ASSERT(handle != NULL);
1454                         upcalls->su_closed(handle);
1455                         tcp->tcp_detached = B_TRUE;
1456                 }


1457         }
1458 }
1459 
1460 /*
1461  * tcp_get_conn/tcp_free_conn
1462  *
1463  * tcp_get_conn is used to get a clean tcp connection structure.
1464  * It tries to reuse the connections put on the freelist by the
1465  * time_wait_collector failing which it goes to kmem_cache. This
1466  * way has two benefits compared to just allocating from and
1467  * freeing to kmem_cache.
1468  * 1) The time_wait_collector can free (which includes the cleanup)
1469  * outside the squeue. So when the interrupt comes, we have a clean
1470  * connection sitting in the freelist. Obviously, this buys us
1471  * performance.
1472  *
1473  * 2) Defence against DOS attack. Allocating a tcp/conn in tcp_input_listener
1474  * has multiple disadvantages - tying up the squeue during alloc.
1475  * But allocating the conn/tcp in IP land is also not the best since
1476  * we can't check the 'q' and 'q0' which are protected by squeue and