diff options
| author | Samuel Ortiz <samuel@sortiz.org> | 2006-09-27 23:05:38 -0400 |
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-28 21:02:46 -0400 |
| commit | da349f1c2e0a0bf8958cdaf14e8f33acdf3182a5 (patch) | |
| tree | c959dd1fe9a4104f94febd0ac6928d9f286f12f8 | |
| parent | 1a9e9ef684ec2bd27fcdb373a82957a0c050daf6 (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.c | 9 |
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); |
