From f2297e9296e52199b01691617a851111fa19a0b2 Mon Sep 17 00:00:00 2001 From: Dan McDonald Date: Mon, 24 Oct 2011 11:42:57 -0400 Subject: [PATCH] 1631 kernel panic in tcp_input_data Reviewed by: Garrett D'Amore Reviewed by: Richard Lowe Approved by: Richard Lowe --- usr/src/uts/common/inet/tcp/tcp_input.c | 134 +++++++++++++++++++++++++--- usr/src/uts/intel/ip/ip.global-objs.debug64 | 2 + usr/src/uts/intel/ip/ip.global-objs.obj64 | 2 + usr/src/uts/sparc/ip/ip.global-objs.debug64 | 2 + usr/src/uts/sparc/ip/ip.global-objs.obj64 | 2 + 5 files changed, 131 insertions(+), 11 deletions(-) diff --git a/usr/src/uts/common/inet/tcp/tcp_input.c b/usr/src/uts/common/inet/tcp/tcp_input.c index 831ebc7ba5..918412d03a 100644 --- a/usr/src/uts/common/inet/tcp/tcp_input.c +++ b/usr/src/uts/common/inet/tcp/tcp_input.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* This file contains all TCP input processing functions. */ @@ -2230,6 +2231,114 @@ tcp_ack_mp(tcp_t *tcp) } /* + * Dummy socket upcalls for if/when the conn_t gets detached from a + * direct-callback sonode via a user-driven close(). Easy to catch with + * DTrace FBT, and should be mostly harmless. + */ + +/* ARGSUSED */ +static sock_upper_handle_t +tcp_dummy_newconn(sock_upper_handle_t x, sock_lower_handle_t y, + sock_downcalls_t *z, cred_t *cr, pid_t pid, sock_upcalls_t **ignored) +{ + ASSERT(0); /* Panic in debug, otherwise ignore. */ + return (NULL); +} + +/* ARGSUSED */ +static void +tcp_dummy_connected(sock_upper_handle_t x, sock_connid_t y, cred_t *cr, + pid_t pid) +{ + ASSERT(x == NULL); + /* Normally we'd crhold(cr) and attach it to socket state. */ + /* LINTED */ +} + +/* ARGSUSED */ +static int +tcp_dummy_disconnected(sock_upper_handle_t x, sock_connid_t y, int blah) +{ + ASSERT(0); /* Panic in debug, otherwise ignore. */ + return (-1); +} + +/* ARGSUSED */ +static void +tcp_dummy_opctl(sock_upper_handle_t x, sock_opctl_action_t y, uintptr_t blah) +{ + ASSERT(x == NULL); + /* We really want this one to be a harmless NOP for now. */ + /* LINTED */ +} + +/* ARGSUSED */ +static ssize_t +tcp_dummy_recv(sock_upper_handle_t x, mblk_t *mp, size_t len, int flags, + int *error, boolean_t *push) +{ + ASSERT(x == NULL); + + /* + * Consume the message, set ESHUTDOWN, and return an error. + * Nobody's home! + */ + freemsg(mp); + *error = ESHUTDOWN; + return (-1); +} + +/* ARGSUSED */ +static void +tcp_dummy_set_proto_props(sock_upper_handle_t x, struct sock_proto_props *y) +{ + ASSERT(0); /* Panic in debug, otherwise ignore. */ +} + +/* ARGSUSED */ +static void +tcp_dummy_txq_full(sock_upper_handle_t x, boolean_t y) +{ + ASSERT(0); /* Panic in debug, otherwise ignore. */ +} + +/* ARGSUSED */ +static void +tcp_dummy_signal_oob(sock_upper_handle_t x, ssize_t len) +{ + ASSERT(x == NULL); + /* Otherwise, this would signal socket state about OOB data. */ +} + +/* ARGSUSED */ +static void +tcp_dummy_set_error(sock_upper_handle_t x, int err) +{ + ASSERT(0); /* Panic in debug, otherwise ignore. */ +} + +/* ARGSUSED */ +static void +tcp_dummy_onearg(sock_upper_handle_t x) +{ + ASSERT(0); /* Panic in debug, otherwise ignore. */ +} + +static sock_upcalls_t tcp_dummy_upcalls = { + tcp_dummy_newconn, + tcp_dummy_connected, + tcp_dummy_disconnected, + tcp_dummy_opctl, + tcp_dummy_recv, + tcp_dummy_set_proto_props, + tcp_dummy_txq_full, + tcp_dummy_signal_oob, + tcp_dummy_onearg, + tcp_dummy_set_error, + tcp_dummy_onearg +}; + +/* * Handle M_DATA messages from IP. Its called directly from IP via * squeue for received IP packets. * @@ -2271,6 +2380,7 @@ tcp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) squeue_t *sqp = (squeue_t *)arg2; tcp_t *tcp = connp->conn_tcp; tcp_stack_t *tcps = tcp->tcp_tcps; + sock_upcalls_t *sockupcalls; /* * RST from fused tcp loopback peer should trigger an unfuse. @@ -2396,6 +2506,11 @@ tcp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) } } + sockupcalls = connp->conn_upcalls; + /* A conn_t may have belonged to a now-closed socket. Be careful. */ + if (sockupcalls == NULL) + sockupcalls = &tcp_dummy_upcalls; + switch (tcp->tcp_state) { case TCPS_SYN_SENT: if (connp->conn_final_sqp == NULL && @@ -2607,8 +2722,7 @@ tcp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) } putnext(connp->conn_rq, mp1); } else { - (*connp->conn_upcalls-> - su_connected) + (*sockupcalls->su_connected) (connp->conn_upper_handle, tcp->tcp_connid, ira->ira_cred, @@ -2635,7 +2749,7 @@ tcp_input_data(void *arg, mblk_t *mp, void *arg2, ip_recv_attr_t *ira) } putnext(connp->conn_rq, mp1); } else { - (*connp->conn_upcalls->su_connected) + (*sockupcalls->su_connected) (connp->conn_upper_handle, tcp->tcp_connid, ira->ira_cred, ira->ira_cpid); @@ -3009,8 +3123,7 @@ try_again:; tcp->tcp_urp_last))) { if (IPCL_IS_NONSTR(connp)) { if (!TCP_IS_DETACHED(tcp)) { - (*connp->conn_upcalls-> - su_signal_oob) + (*sockupcalls->su_signal_oob) (connp->conn_upper_handle, urp); } @@ -3288,7 +3401,7 @@ ok:; */ if (IPCL_IS_NONSTR(connp)) { if (!TCP_IS_DETACHED(tcp)) { - (*connp->conn_upcalls->su_signal_oob) + (*sockupcalls->su_signal_oob) (connp->conn_upper_handle, urp); } } else { @@ -3447,7 +3560,7 @@ ok:; if (IPCL_IS_NONSTR(connp)) { int error; - (*connp->conn_upcalls->su_recv) + (*sockupcalls->su_recv) (connp->conn_upper_handle, mp, seg_len, MSG_OOB, &error, NULL); /* @@ -4626,8 +4739,7 @@ update_ack: boolean_t push = flags & (TH_PUSH|TH_FIN); int error; - if ((*connp->conn_upcalls->su_recv)( - connp->conn_upper_handle, + if ((*sockupcalls->su_recv)(connp->conn_upper_handle, mp, seg_len, 0, &error, &push) <= 0) { /* * We should never be in middle of a @@ -4869,8 +4981,8 @@ ack_check: if (IPCL_IS_NONSTR(connp)) { ASSERT(tcp->tcp_ordrel_mp == NULL); tcp->tcp_ordrel_done = B_TRUE; - (*connp->conn_upcalls->su_opctl) - (connp->conn_upper_handle, SOCK_OPCTL_SHUT_RECV, 0); + (*sockupcalls->su_opctl)(connp->conn_upper_handle, + SOCK_OPCTL_SHUT_RECV, 0); goto done; } diff --git a/usr/src/uts/intel/ip/ip.global-objs.debug64 b/usr/src/uts/intel/ip/ip.global-objs.debug64 index 7062aac6db..40d5bd498b 100644 --- a/usr/src/uts/intel/ip/ip.global-objs.debug64 +++ b/usr/src/uts/intel/ip/ip.global-objs.debug64 @@ -20,6 +20,7 @@ # # # Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2011 Nexenta Systems, Inc. All rights reserved # arp_m_tbl @@ -253,6 +254,7 @@ tcp_conn_cache tcp_conn_hash_size tcp_do_reclaim tcp_drop_ack_unsent_cnt +tcp_dummy_upcalls tcp_early_abort tcp_fallback_sock_winit tcp_free_list_max_cnt diff --git a/usr/src/uts/intel/ip/ip.global-objs.obj64 b/usr/src/uts/intel/ip/ip.global-objs.obj64 index 6c095dd832..5c56fe7efd 100644 --- a/usr/src/uts/intel/ip/ip.global-objs.obj64 +++ b/usr/src/uts/intel/ip/ip.global-objs.obj64 @@ -20,6 +20,7 @@ # # # Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2011 Nexenta Systems, Inc. All rights reserved # arp_m_tbl @@ -250,6 +251,7 @@ tcp_conn_cache tcp_conn_hash_size tcp_do_reclaim tcp_drop_ack_unsent_cnt +tcp_dummy_upcalls tcp_early_abort tcp_fallback_sock_winit tcp_free_list_max_cnt diff --git a/usr/src/uts/sparc/ip/ip.global-objs.debug64 b/usr/src/uts/sparc/ip/ip.global-objs.debug64 index 7062aac6db..40d5bd498b 100644 --- a/usr/src/uts/sparc/ip/ip.global-objs.debug64 +++ b/usr/src/uts/sparc/ip/ip.global-objs.debug64 @@ -20,6 +20,7 @@ # # # Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2011 Nexenta Systems, Inc. All rights reserved # arp_m_tbl @@ -253,6 +254,7 @@ tcp_conn_cache tcp_conn_hash_size tcp_do_reclaim tcp_drop_ack_unsent_cnt +tcp_dummy_upcalls tcp_early_abort tcp_fallback_sock_winit tcp_free_list_max_cnt diff --git a/usr/src/uts/sparc/ip/ip.global-objs.obj64 b/usr/src/uts/sparc/ip/ip.global-objs.obj64 index 6c095dd832..5c56fe7efd 100644 --- a/usr/src/uts/sparc/ip/ip.global-objs.obj64 +++ b/usr/src/uts/sparc/ip/ip.global-objs.obj64 @@ -20,6 +20,7 @@ # # # Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2011 Nexenta Systems, Inc. All rights reserved # arp_m_tbl @@ -250,6 +251,7 @@ tcp_conn_cache tcp_conn_hash_size tcp_do_reclaim tcp_drop_ack_unsent_cnt +tcp_dummy_upcalls tcp_early_abort tcp_fallback_sock_winit tcp_free_list_max_cnt -- 2.11.4.GIT