summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorAnders Persson <Anders.Persson@Sun.COM>2010-08-10 15:52:26 -0700
committerAnders Persson <Anders.Persson@Sun.COM>2010-08-10 15:52:26 -0700
commite82bc0ba9649a7146fdab88089eaa4b8502b2da4 (patch)
treec7f43497fb0230ae5f9dd4d49ad75b60f183c8e2 /usr/src
parenta4ca1d52cdf9b55a14d0c62ff62b74cd904110ff (diff)
downloadillumos-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.c6
-rw-r--r--usr/src/uts/common/fs/sockfs/sockfilter.c16
-rw-r--r--usr/src/uts/common/inet/kssl/ksslfilter.c18
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_input.c11
-rw-r--r--usr/src/uts/common/inet/tcp/tcp_socket.c24
-rw-r--r--usr/src/uts/common/sys/socketvar.h2
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 */