Skip to content

Commit

Permalink
NFC: Fix LLCP sockets releasing path
Browse files Browse the repository at this point in the history
The socket local pointer needs to be set to NULL when the adapter is
removed or the MAC goes down.
If the socket release code is called after such an event, the socket
reference count still needs to be decreased in order for the socket to
eventually be freed.

Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Samuel Ortiz authored and John W. Linville committed Mar 6, 2012
1 parent 47807d3 commit 40c75f8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 12 deletions.
15 changes: 11 additions & 4 deletions net/nfc/llcp/llcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)

/* Release all child sockets */
list_for_each_entry_safe(s, n, &parent->list, list) {
list_del(&s->list);
list_del_init(&s->list);
sk = &s->sk;

lock_sock(sk);
Expand All @@ -56,9 +56,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
nfc_put_device(s->dev);

sk->sk_state = LLCP_CLOSED;
sock_set_flag(sk, SOCK_DEAD);

release_sock(sk);

sock_orphan(sk);

s->local = NULL;
}

parent_sk = &parent->sk;
Expand All @@ -77,21 +80,25 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
nfc_llcp_accept_unlink(accept_sk);

accept_sk->sk_state = LLCP_CLOSED;
sock_set_flag(accept_sk, SOCK_DEAD);

release_sock(accept_sk);

sock_orphan(accept_sk);

lsk->local = NULL;
}
}

if (parent_sk->sk_state == LLCP_CONNECTED)
nfc_put_device(parent->dev);

parent_sk->sk_state = LLCP_CLOSED;
sock_set_flag(parent_sk, SOCK_DEAD);

release_sock(parent_sk);

sock_orphan(parent_sk);

parent->local = NULL;
}

mutex_unlock(&local->socket_lock);
Expand Down
23 changes: 15 additions & 8 deletions net/nfc/llcp/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,22 +315,25 @@ static int llcp_sock_release(struct socket *sock)
struct sock *sk = sock->sk;
struct nfc_llcp_local *local;
struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
int err = 0;

if (!sk)
return 0;

pr_debug("%p\n", sk);

local = llcp_sock->local;
if (local == NULL)
return -ENODEV;
if (local == NULL) {
err = -ENODEV;
goto out;
}

mutex_lock(&local->socket_lock);

if (llcp_sock == local->sockets[llcp_sock->ssap])
local->sockets[llcp_sock->ssap] = NULL;
else
list_del(&llcp_sock->list);
list_del_init(&llcp_sock->list);

mutex_unlock(&local->socket_lock);

Expand All @@ -354,9 +357,7 @@ static int llcp_sock_release(struct socket *sock)

release_sock(accept_sk);

sock_set_flag(sk, SOCK_DEAD);
sock_orphan(accept_sk);
sock_put(accept_sk);
}
}

Expand All @@ -367,14 +368,13 @@ static int llcp_sock_release(struct socket *sock)
sk->sk_state == LLCP_LISTEN)
nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);

sock_set_flag(sk, SOCK_DEAD);

release_sock(sk);

out:
sock_orphan(sk);
sock_put(sk);

return 0;
return err;
}

static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
Expand Down Expand Up @@ -645,6 +645,8 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)

void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
{
struct nfc_llcp_local *local = sock->local;

kfree(sock->service_name);

skb_queue_purge(&sock->tx_queue);
Expand All @@ -653,6 +655,11 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)

list_del_init(&sock->accept_queue);

if (local != NULL && sock == local->sockets[sock->ssap])
local->sockets[sock->ssap] = NULL;
else
list_del_init(&sock->list);

sock->parent = NULL;
}

Expand Down

0 comments on commit 40c75f8

Please sign in to comment.