diff options
author | Anders Persson <Anders.Persson@Sun.COM> | 2010-08-10 15:52:26 -0700 |
---|---|---|
committer | Anders Persson <Anders.Persson@Sun.COM> | 2010-08-10 15:52:26 -0700 |
commit | e82bc0ba9649a7146fdab88089eaa4b8502b2da4 (patch) | |
tree | c7f43497fb0230ae5f9dd4d49ad75b60f183c8e2 /usr/src | |
parent | a4ca1d52cdf9b55a14d0c62ff62b74cd904110ff (diff) | |
download | illumos-joyent-e82bc0ba9649a7146fdab88089eaa4b8502b2da4.tar.gz |
6972175 assertion failed: tcp->tcp_fin_sent, file: ../../common/inet/tcp/tcp_input.c, line: 4306
6971322 sof_inject_data_out() cannot inject data from close callback
6971886 missing NULL cookie checks in some kssl filter callbacks
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/uts/common/fs/sockfs/sockcommon_sops.c | 6 | ||||
-rw-r--r-- | usr/src/uts/common/fs/sockfs/sockfilter.c | 16 | ||||
-rw-r--r-- | usr/src/uts/common/inet/kssl/ksslfilter.c | 18 | ||||
-rw-r--r-- | usr/src/uts/common/inet/tcp/tcp_input.c | 11 | ||||
-rw-r--r-- | usr/src/uts/common/inet/tcp/tcp_socket.c | 24 | ||||
-rw-r--r-- | usr/src/uts/common/sys/socketvar.h | 2 |
6 files changed, 36 insertions, 41 deletions
diff --git a/usr/src/uts/common/fs/sockfs/sockcommon_sops.c b/usr/src/uts/common/fs/sockfs/sockcommon_sops.c index 7092cbbf65..294ec4b82c 100644 --- a/usr/src/uts/common/fs/sockfs/sockcommon_sops.c +++ b/usr/src/uts/common/fs/sockfs/sockcommon_sops.c @@ -1467,6 +1467,9 @@ so_close(struct sonode *so, int flag, struct cred *cr) so_rcv_flush(so); mutex_exit(&so->so_lock); + if (so->so_filter_active > 0) + sof_sonode_closing(so); + if (so->so_state & SS_ACCEPTCONN) { /* * We grab and release the accept lock to ensure that any @@ -1481,9 +1484,6 @@ so_close(struct sonode *so, int flag, struct cred *cr) so_acceptq_flush(so, B_TRUE); } - if (so->so_filter_active > 0) - sof_sonode_closing(so); - error = (*so->so_downcalls->sd_close)(so->so_proto_handle, flag, cr); switch (error) { default: diff --git a/usr/src/uts/common/fs/sockfs/sockfilter.c b/usr/src/uts/common/fs/sockfs/sockfilter.c index 3de36a768e..971523945e 100644 --- a/usr/src/uts/common/fs/sockfs/sockfilter.c +++ b/usr/src/uts/common/fs/sockfs/sockfilter.c @@ -59,7 +59,7 @@ * Modules are created by sof_register() and placed in sof_module_list, * which is protected by sof_module_lock. Each module has a reference count * that is incremented when a filter entry is using the module. A module - * can be destroyed by sof_register() only when it's ref count is zero. + * can be destroyed by sof_unregister() only when its ref count is zero. * * Socket filter instance (sof_instance_t): * @@ -637,8 +637,14 @@ sof_sonode_closing(struct sonode *so) */ sof_sonode_notify_filters(so, SOF_EV_CLOSING, (uintptr_t)B_TRUE); - /* wait for filters that are sending out data */ + /* + * Stop any future attempts to inject data, and wait for any + * pending operations to complete. This has to be done to ensure + * that no data is sent down to the protocol once a close + * downcall has been made. + */ mutex_enter(&so->so_lock); + so->so_state |= SS_FIL_STOP; while (so->so_filter_tx > 0) cv_wait(&so->so_closing_cv, &so->so_lock); mutex_exit(&so->so_lock); @@ -1702,12 +1708,8 @@ sof_inject_data_out(sof_handle_t handle, mblk_t *mp, struct nmsghdr *msg, struct sonode *so = inst->sofi_sonode; int error; - /* - * Data cannot be sent down to the protocol once the socket has - * started the process of closing. - */ mutex_enter(&so->so_lock); - if (so->so_state & SS_CLOSING) { + if (so->so_state & SS_FIL_STOP) { mutex_exit(&so->so_lock); freemsg(mp); return (EPIPE); diff --git a/usr/src/uts/common/inet/kssl/ksslfilter.c b/usr/src/uts/common/inet/kssl/ksslfilter.c index 208fa3e0aa..54766561fb 100644 --- a/usr/src/uts/common/inet/kssl/ksslfilter.c +++ b/usr/src/uts/common/inet/kssl/ksslfilter.c @@ -288,16 +288,15 @@ kssl_data_out_cb(sof_handle_t handle, void *cookie, mblk_t *mp, struct nmsghdr *msg, cred_t *cr, sof_rval_t *rv) { ksslf_t *kssl = (ksslf_t *)cookie; - kssl_ctx_t kssl_ctx = kssl->ksslf_ctx; mblk_t *recmp; _NOTE(ARGUNUSED(handle, msg, cr)); *rv = SOF_RVAL_CONTINUE; - if (kssl_ctx == NULL) + if (kssl == NULL || kssl->ksslf_ctx == NULL) return (mp); - if ((recmp = kssl_build_record(kssl_ctx, mp)) == NULL) { + if ((recmp = kssl_build_record(kssl->ksslf_ctx, mp)) == NULL) { freemsg(mp); *rv = SOF_RVAL_EINVAL; return (NULL); @@ -313,15 +312,14 @@ sof_rval_t kssl_shutdown_cb(sof_handle_t handle, void *cookie, int *howp, cred_t *cr) { ksslf_t *kssl = (ksslf_t *)cookie; - kssl_ctx_t kssl_ctx = kssl->ksslf_ctx; mblk_t *outmp; boolean_t flowctrld; struct nmsghdr msg; _NOTE(ARGUNUSED(cr)); - if (kssl_ctx == NULL) - return (SOF_RVAL_EINVAL); + if (kssl == NULL || kssl->ksslf_ctx == NULL) + return (SOF_RVAL_CONTINUE); /* * We only want to send close_notify when doing SHUT_WR/SHUT_RDWR @@ -331,7 +329,7 @@ kssl_shutdown_cb(sof_handle_t handle, void *cookie, int *howp, cred_t *cr) return (SOF_RVAL_CONTINUE); /* Go on if we fail to build the record. */ - if ((outmp = kssl_build_record(kssl_ctx, NULL)) == NULL) + if ((outmp = kssl_build_record(kssl->ksslf_ctx, NULL)) == NULL) return (SOF_RVAL_CONTINUE); bzero(&msg, sizeof (msg)); @@ -466,15 +464,17 @@ kssl_data_in_proc_cb(sof_handle_t handle, void *cookie, mblk_t *mp, cred_t *cr, size_t *lenp) { ksslf_t *kssl = (ksslf_t *)cookie; - kssl_ctx_t kssl_ctx = kssl->ksslf_ctx; kssl_cmd_t kssl_cmd; mblk_t *out; _NOTE(ARGUNUSED(cr)); + if (kssl == NULL || kssl->ksslf_ctx) + return (mp); + *lenp = 0; - kssl_cmd = kssl_handle_mblk(kssl_ctx, &mp, &out); + kssl_cmd = kssl_handle_mblk(kssl->ksslf_ctx, &mp, &out); switch (kssl_cmd) { case KSSL_CMD_NONE: diff --git a/usr/src/uts/common/inet/tcp/tcp_input.c b/usr/src/uts/common/inet/tcp/tcp_input.c index a57bb333df..831ebc7ba5 100644 --- a/usr/src/uts/common/inet/tcp/tcp_input.c +++ b/usr/src/uts/common/inet/tcp/tcp_input.c @@ -3618,9 +3618,20 @@ process_ack: CONN_INC_REF(connp); if (!tcp_newconn_notify(tcp, ira)) { + /* + * The state-change probe for SYN_RCVD -> + * ESTABLISHED has not fired yet. We reset + * the state to SYN_RCVD so that future + * state-change probes report correct state + * transistions. + */ + tcp->tcp_state = TCPS_SYN_RCVD; freemsg(mp); /* notification did not go up, so drop ref */ CONN_DEC_REF(connp); + /* ... and close the eager */ + ASSERT(TCP_IS_DETACHED(tcp)); + (void) tcp_close_detached(tcp); return; } /* diff --git a/usr/src/uts/common/inet/tcp/tcp_socket.c b/usr/src/uts/common/inet/tcp/tcp_socket.c index e284908b3e..a888284c54 100644 --- a/usr/src/uts/common/inet/tcp/tcp_socket.c +++ b/usr/src/uts/common/inet/tcp/tcp_socket.c @@ -1055,12 +1055,11 @@ tcp_fallback(sock_lower_handle_t proto_handle, queue_t *q, * Notifies a non-STREAMS based listener about a new connection. This * function is executed on the *eager*'s squeue once the 3 way handshake * has completed. Note that the behavior differs from STREAMS, where the - * T_CONN_IND is sent up by tcp_send_conn_ind while on the *listener*'s + * T_CONN_IND is sent up by tcp_send_conn_ind() while on the *listener*'s * squeue. * - * Returns B_TRUE if the notification succeeded, in which case `tcp' will - * be moved over to the ESTABLISHED list (q) of the listener. Othwerise, - * B_FALSE is returned and `tcp' is killed. + * Returns B_TRUE if the notification succeeded and an upper handle was + * obtained. `tcp' should be closed on failure. */ boolean_t tcp_newconn_notify(tcp_t *tcp, ip_recv_attr_t *ira) @@ -1072,7 +1071,6 @@ tcp_newconn_notify(tcp_t *tcp, ip_recv_attr_t *ira) ipaddr_t *addr_cache; sock_upper_handle_t upper; struct sock_proto_props sopp; - mblk_t *mp; mutex_enter(&listener->tcp_eager_lock); /* @@ -1150,22 +1148,6 @@ tcp_newconn_notify(tcp_t *tcp, ip_recv_attr_t *ira) (lconnp->conn_upper_handle, (sock_lower_handle_t)econnp, &sock_tcp_downcalls, ira->ira_cred, ira->ira_cpid, &econnp->conn_upcalls)) == NULL) { - /* - * Normally this should not happen, but the listener might - * have done a fallback to TPI followed by a close(), in - * which case tcp_closemp for this conn might have been - * used by tcp_eager_cleanup(). - */ - mutex_enter(&listener->tcp_eager_lock); - if (tcp->tcp_closemp_used) { - mutex_exit(&listener->tcp_eager_lock); - return (B_FALSE); - } - tcp->tcp_closemp_used = B_TRUE; - TCP_DEBUG_GETPCSTACK(tcp->tcmp_stk, 15); - mp = &tcp->tcp_closemp; - mutex_exit(&listener->tcp_eager_lock); - tcp_eager_kill(econnp, mp, NULL, NULL); return (B_FALSE); } econnp->conn_upper_handle = upper; diff --git a/usr/src/uts/common/sys/socketvar.h b/usr/src/uts/common/sys/socketvar.h index 75b1626bcb..8221c620a8 100644 --- a/usr/src/uts/common/sys/socketvar.h +++ b/usr/src/uts/common/sys/socketvar.h @@ -300,7 +300,7 @@ struct sonode { #define SS_FILOP_OK 0x00040000 /* socket can attach filters */ #define SS_FIL_RCV_FLOWCTRL 0x00080000 /* filter asserted rcv flow ctrl */ #define SS_FIL_SND_FLOWCTRL 0x00100000 /* filter asserted snd flow ctrl */ -/* unused 0x00200000 */ /* was SS_DIRECT */ +#define SS_FIL_STOP 0x00200000 /* no more filter actions */ #define SS_SODIRECT 0x00400000 /* transport supports sodirect */ |