[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>
This commit is contained in:
committed by
David S. Miller
parent
1a9e9ef684
commit
da349f1c2e
@@ -132,13 +132,14 @@ static void irda_disconnect_indication(void *instance, void *sap,
|
|||||||
|
|
||||||
/* Prevent race conditions with irda_release() and irda_shutdown() */
|
/* Prevent race conditions with irda_release() and irda_shutdown() */
|
||||||
if (!sock_flag(sk, SOCK_DEAD) && sk->sk_state != TCP_CLOSE) {
|
if (!sock_flag(sk, SOCK_DEAD) && sk->sk_state != TCP_CLOSE) {
|
||||||
|
lock_sock(sk);
|
||||||
sk->sk_state = TCP_CLOSE;
|
sk->sk_state = TCP_CLOSE;
|
||||||
sk->sk_err = ECONNRESET;
|
sk->sk_err = ECONNRESET;
|
||||||
sk->sk_shutdown |= SEND_SHUTDOWN;
|
sk->sk_shutdown |= SEND_SHUTDOWN;
|
||||||
|
|
||||||
sk->sk_state_change(sk);
|
sk->sk_state_change(sk);
|
||||||
/* Uh-oh... Should use sock_orphan ? */
|
sock_orphan(sk);
|
||||||
sock_set_flag(sk, SOCK_DEAD);
|
release_sock(sk);
|
||||||
|
|
||||||
/* Close our TSAP.
|
/* Close our TSAP.
|
||||||
* If we leave it open, IrLMP put it back into the list of
|
* If we leave it open, IrLMP put it back into the list of
|
||||||
@@ -1212,6 +1213,7 @@ static int irda_release(struct socket *sock)
|
|||||||
if (sk == NULL)
|
if (sk == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
lock_sock(sk);
|
||||||
sk->sk_state = TCP_CLOSE;
|
sk->sk_state = TCP_CLOSE;
|
||||||
sk->sk_shutdown |= SEND_SHUTDOWN;
|
sk->sk_shutdown |= SEND_SHUTDOWN;
|
||||||
sk->sk_state_change(sk);
|
sk->sk_state_change(sk);
|
||||||
@@ -1221,6 +1223,7 @@ static int irda_release(struct socket *sock)
|
|||||||
|
|
||||||
sock_orphan(sk);
|
sock_orphan(sk);
|
||||||
sock->sk = NULL;
|
sock->sk = NULL;
|
||||||
|
release_sock(sk);
|
||||||
|
|
||||||
/* Purge queues (see sock_init_data()) */
|
/* Purge queues (see sock_init_data()) */
|
||||||
skb_queue_purge(&sk->sk_receive_queue);
|
skb_queue_purge(&sk->sk_receive_queue);
|
||||||
@@ -1353,6 +1356,7 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
|
|||||||
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
|
IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
|
||||||
|
|
||||||
IRDA_ASSERT(self != NULL, return -1;);
|
IRDA_ASSERT(self != NULL, return -1;);
|
||||||
|
IRDA_ASSERT(!sock_error(sk), return -1;);
|
||||||
|
|
||||||
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
|
skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
|
||||||
flags & MSG_DONTWAIT, &err);
|
flags & MSG_DONTWAIT, &err);
|
||||||
@@ -1405,6 +1409,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
|
|||||||
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
|
IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
|
||||||
|
|
||||||
IRDA_ASSERT(self != NULL, return -1;);
|
IRDA_ASSERT(self != NULL, return -1;);
|
||||||
|
IRDA_ASSERT(!sock_error(sk), return -1;);
|
||||||
|
|
||||||
if (sock->flags & __SO_ACCEPTCON)
|
if (sock->flags & __SO_ACCEPTCON)
|
||||||
return(-EINVAL);
|
return(-EINVAL);
|
||||||
|
Reference in New Issue
Block a user