aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Ortiz <samuel@sortiz.org>2006-09-27 23:05:38 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-28 21:02:46 -0400
commitda349f1c2e0a0bf8958cdaf14e8f33acdf3182a5 (patch)
treec959dd1fe9a4104f94febd0ac6928d9f286f12f8
parent1a9e9ef684ec2bd27fcdb373a82957a0c050daf6 (diff)
[IrDA]: af_irda.c cleanups
We lock the socket when both releasing and getting a disconnected notification. In the latter case, we also ste the socket as orphan. This fixes a potential kernel bug that can be triggered when we get the disconnection notification before closing the socket. Signed-off-by: Samuel Ortiz <samuel@sortiz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/irda/af_irda.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 17699eeb64d7..7b7cd5bd2a06 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -132,13 +132,14 @@ static void irda_disconnect_indication(void *instance, void *sap,
132 132
133 /* Prevent race conditions with irda_release() and irda_shutdown() */ 133 /* Prevent race conditions with irda_release() and irda_shutdown() */
134 if (!sock_flag(sk, SOCK_DEAD) && sk->sk_state != TCP_CLOSE) { 134 if (!sock_flag(sk, SOCK_DEAD) && sk->sk_state != TCP_CLOSE) {
135 lock_sock(sk);
135 sk->sk_state = TCP_CLOSE; 136 sk->sk_state = TCP_CLOSE;
136 sk->sk_err = ECONNRESET; 137 sk->sk_err = ECONNRESET;
137 sk->sk_shutdown |= SEND_SHUTDOWN; 138 sk->sk_shutdown |= SEND_SHUTDOWN;
138 139
139 sk->sk_state_change(sk); 140 sk->sk_state_change(sk);
140 /* Uh-oh... Should use sock_orphan ? */ 141 sock_orphan(sk);
141 sock_set_flag(sk, SOCK_DEAD); 142 release_sock(sk);
142 143
143 /* Close our TSAP. 144 /* Close our TSAP.
144 * If we leave it open, IrLMP put it back into the list of 145 * If we leave it open, IrLMP put it back into the list of
@@ -1212,6 +1213,7 @@ static int irda_release(struct socket *sock)
1212 if (sk == NULL) 1213 if (sk == NULL)
1213 return 0; 1214 return 0;
1214 1215
1216 lock_sock(sk);
1215 sk->sk_state = TCP_CLOSE; 1217 sk->sk_state = TCP_CLOSE;
1216 sk->sk_shutdown |= SEND_SHUTDOWN; 1218 sk->sk_shutdown |= SEND_SHUTDOWN;
1217 sk->sk_state_change(sk); 1219 sk->sk_state_change(sk);
@@ -1221,6 +1223,7 @@ static int irda_release(struct socket *sock)
1221 1223
1222 sock_orphan(sk); 1224 sock_orphan(sk);
1223 sock->sk = NULL; 1225 sock->sk = NULL;
1226 release_sock(sk);
1224 1227
1225 /* Purge queues (see sock_init_data()) */ 1228 /* Purge queues (see sock_init_data()) */
1226 skb_queue_purge(&sk->sk_receive_queue); 1229 skb_queue_purge(&sk->sk_receive_queue);
@@ -1353,6 +1356,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
1353 IRDA_DEBUG(4, "%s()\n", __FUNCTION__); 1356 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
1354 1357
1355 IRDA_ASSERT(self != NULL, return -1;); 1358 IRDA_ASSERT(self != NULL, return -1;);
1359 IRDA_ASSERT(!sock_error(sk), return -1;);
1356 1360
1357 skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 1361 skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
1358 flags & MSG_DONTWAIT, &err); 1362 flags & MSG_DONTWAIT, &err);
@@ -1405,6 +1409,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
1405 IRDA_DEBUG(3, "%s()\n", __FUNCTION__); 1409 IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
1406 1410
1407 IRDA_ASSERT(self != NULL, return -1;); 1411 IRDA_ASSERT(self != NULL, return -1;);
1412 IRDA_ASSERT(!sock_error(sk), return -1;);
1408 1413
1409 if (sock->flags & __SO_ACCEPTCON) 1414 if (sock->flags & __SO_ACCEPTCON)
1410 return(-EINVAL); 1415 return(-EINVAL);