aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2012-03-04 19:03:51 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-06 15:16:24 -0500
commit40c75f81d6852bb4fd08491074889187f77b8d1f (patch)
tree456956512172a11d67a811e15277d5e0a56387c0 /net
parent47807d3dbb62e93850cbcb797db1a9ee1806f986 (diff)
NFC: Fix LLCP sockets releasing path
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>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/llcp/llcp.c15
-rw-r--r--net/nfc/llcp/sock.c23
2 files changed, 26 insertions, 12 deletions
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 3ce646e35f6b..8af896dc759e 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -47,7 +47,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
47 47
48 /* Release all child sockets */ 48 /* Release all child sockets */
49 list_for_each_entry_safe(s, n, &parent->list, list) { 49 list_for_each_entry_safe(s, n, &parent->list, list) {
50 list_del(&s->list); 50 list_del_init(&s->list);
51 sk = &s->sk; 51 sk = &s->sk;
52 52
53 lock_sock(sk); 53 lock_sock(sk);
@@ -56,9 +56,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
56 nfc_put_device(s->dev); 56 nfc_put_device(s->dev);
57 57
58 sk->sk_state = LLCP_CLOSED; 58 sk->sk_state = LLCP_CLOSED;
59 sock_set_flag(sk, SOCK_DEAD);
60 59
61 release_sock(sk); 60 release_sock(sk);
61
62 sock_orphan(sk);
63
64 s->local = NULL;
62 } 65 }
63 66
64 parent_sk = &parent->sk; 67 parent_sk = &parent->sk;
@@ -77,11 +80,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
77 nfc_llcp_accept_unlink(accept_sk); 80 nfc_llcp_accept_unlink(accept_sk);
78 81
79 accept_sk->sk_state = LLCP_CLOSED; 82 accept_sk->sk_state = LLCP_CLOSED;
80 sock_set_flag(accept_sk, SOCK_DEAD);
81 83
82 release_sock(accept_sk); 84 release_sock(accept_sk);
83 85
84 sock_orphan(accept_sk); 86 sock_orphan(accept_sk);
87
88 lsk->local = NULL;
85 } 89 }
86 } 90 }
87 91
@@ -89,9 +93,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
89 nfc_put_device(parent->dev); 93 nfc_put_device(parent->dev);
90 94
91 parent_sk->sk_state = LLCP_CLOSED; 95 parent_sk->sk_state = LLCP_CLOSED;
92 sock_set_flag(parent_sk, SOCK_DEAD);
93 96
94 release_sock(parent_sk); 97 release_sock(parent_sk);
98
99 sock_orphan(parent_sk);
100
101 parent->local = NULL;
95 } 102 }
96 103
97 mutex_unlock(&local->socket_lock); 104 mutex_unlock(&local->socket_lock);
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index d3861773fab0..35825e20163a 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -315,6 +315,7 @@ static int llcp_sock_release(struct socket *sock)
315 struct sock *sk = sock->sk; 315 struct sock *sk = sock->sk;
316 struct nfc_llcp_local *local; 316 struct nfc_llcp_local *local;
317 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk); 317 struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
318 int err = 0;
318 319
319 if (!sk) 320 if (!sk)
320 return 0; 321 return 0;
@@ -322,15 +323,17 @@ static int llcp_sock_release(struct socket *sock)
322 pr_debug("%p\n", sk); 323 pr_debug("%p\n", sk);
323 324
324 local = llcp_sock->local; 325 local = llcp_sock->local;
325 if (local == NULL) 326 if (local == NULL) {
326 return -ENODEV; 327 err = -ENODEV;
328 goto out;
329 }
327 330
328 mutex_lock(&local->socket_lock); 331 mutex_lock(&local->socket_lock);
329 332
330 if (llcp_sock == local->sockets[llcp_sock->ssap]) 333 if (llcp_sock == local->sockets[llcp_sock->ssap])
331 local->sockets[llcp_sock->ssap] = NULL; 334 local->sockets[llcp_sock->ssap] = NULL;
332 else 335 else
333 list_del(&llcp_sock->list); 336 list_del_init(&llcp_sock->list);
334 337
335 mutex_unlock(&local->socket_lock); 338 mutex_unlock(&local->socket_lock);
336 339
@@ -354,9 +357,7 @@ static int llcp_sock_release(struct socket *sock)
354 357
355 release_sock(accept_sk); 358 release_sock(accept_sk);
356 359
357 sock_set_flag(sk, SOCK_DEAD);
358 sock_orphan(accept_sk); 360 sock_orphan(accept_sk);
359 sock_put(accept_sk);
360 } 361 }
361 } 362 }
362 363
@@ -367,14 +368,13 @@ static int llcp_sock_release(struct socket *sock)
367 sk->sk_state == LLCP_LISTEN) 368 sk->sk_state == LLCP_LISTEN)
368 nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap); 369 nfc_llcp_put_ssap(llcp_sock->local, llcp_sock->ssap);
369 370
370 sock_set_flag(sk, SOCK_DEAD);
371
372 release_sock(sk); 371 release_sock(sk);
373 372
373out:
374 sock_orphan(sk); 374 sock_orphan(sk);
375 sock_put(sk); 375 sock_put(sk);
376 376
377 return 0; 377 return err;
378} 378}
379 379
380static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, 380static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
@@ -645,6 +645,8 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
645 645
646void nfc_llcp_sock_free(struct nfc_llcp_sock *sock) 646void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
647{ 647{
648 struct nfc_llcp_local *local = sock->local;
649
648 kfree(sock->service_name); 650 kfree(sock->service_name);
649 651
650 skb_queue_purge(&sock->tx_queue); 652 skb_queue_purge(&sock->tx_queue);
@@ -653,6 +655,11 @@ void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
653 655
654 list_del_init(&sock->accept_queue); 656 list_del_init(&sock->accept_queue);
655 657
658 if (local != NULL && sock == local->sockets[sock->ssap])
659 local->sockets[sock->ssap] = NULL;
660 else
661 list_del_init(&sock->list);
662
656 sock->parent = NULL; 663 sock->parent = NULL;
657} 664}
658 665