Skip to content

Commit c7aa122

Browse files
author
Samuel Ortiz
committed
NFC: Take a reference on the LLCP local pointer when creating a socket
LLCP sockets point to their local LLCP service, so they need to take a reference on it. Signed-off-by: Samuel Ortiz <[email protected]>
1 parent f8f5701 commit c7aa122

File tree

3 files changed

+40
-24
lines changed

3 files changed

+40
-24
lines changed

net/nfc/llcp/llcp.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
5959
release_sock(sk);
6060

6161
sock_orphan(sk);
62-
63-
s->local = NULL;
6462
}
6563

6664
parent_sk = &parent->sk;
@@ -83,8 +81,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
8381
release_sock(accept_sk);
8482

8583
sock_orphan(accept_sk);
86-
87-
lsk->local = NULL;
8884
}
8985
}
9086

@@ -96,13 +92,39 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local)
9692
release_sock(parent_sk);
9793

9894
sock_orphan(parent_sk);
99-
100-
parent->local = NULL;
10195
}
10296

10397
mutex_unlock(&local->socket_lock);
10498
}
10599

100+
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
101+
{
102+
kref_get(&local->ref);
103+
104+
return local;
105+
}
106+
107+
static void local_release(struct kref *ref)
108+
{
109+
struct nfc_llcp_local *local;
110+
111+
local = container_of(ref, struct nfc_llcp_local, ref);
112+
113+
list_del(&local->list);
114+
nfc_llcp_socket_release(local);
115+
del_timer_sync(&local->link_timer);
116+
skb_queue_purge(&local->tx_queue);
117+
destroy_workqueue(local->tx_wq);
118+
destroy_workqueue(local->rx_wq);
119+
kfree_skb(local->rx_pending);
120+
kfree(local);
121+
}
122+
123+
int nfc_llcp_local_put(struct nfc_llcp_local *local)
124+
{
125+
return kref_put(&local->ref, local_release);
126+
}
127+
106128
static void nfc_llcp_clear_sdp(struct nfc_llcp_local *local)
107129
{
108130
mutex_lock(&local->sdp_lock);
@@ -612,7 +634,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local,
612634

613635
new_sock = nfc_llcp_sock(new_sk);
614636
new_sock->dev = local->dev;
615-
new_sock->local = local;
637+
new_sock->local = nfc_llcp_local_get(local);
616638
new_sock->nfc_protocol = sock->nfc_protocol;
617639
new_sock->ssap = bound_sap;
618640
new_sock->dsap = ssap;
@@ -943,6 +965,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
943965

944966
local->dev = ndev;
945967
INIT_LIST_HEAD(&local->list);
968+
kref_init(&local->ref);
946969
mutex_init(&local->sdp_lock);
947970
mutex_init(&local->socket_lock);
948971
init_timer(&local->link_timer);
@@ -1015,14 +1038,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
10151038
return;
10161039
}
10171040

1018-
list_del(&local->list);
1019-
nfc_llcp_socket_release(local);
1020-
del_timer_sync(&local->link_timer);
1021-
skb_queue_purge(&local->tx_queue);
1022-
destroy_workqueue(local->tx_wq);
1023-
destroy_workqueue(local->rx_wq);
1024-
kfree_skb(local->rx_pending);
1025-
kfree(local);
1041+
nfc_llcp_local_put(local);
10261042
}
10271043

10281044
int __init nfc_llcp_init(void)

net/nfc/llcp/llcp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct nfc_llcp_local {
4444
struct list_head list;
4545
struct nfc_dev *dev;
4646

47+
struct kref ref;
48+
4749
struct mutex sdp_lock;
4850
struct mutex socket_lock;
4951

@@ -165,6 +167,8 @@ struct nfc_llcp_sock {
165167

166168

167169
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
170+
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
171+
int nfc_llcp_local_put(struct nfc_llcp_local *local);
168172
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
169173
struct nfc_llcp_sock *sock);
170174
u8 nfc_llcp_get_local_ssap(struct nfc_llcp_local *local);

net/nfc/llcp/sock.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
111111
}
112112

113113
llcp_sock->dev = dev;
114-
llcp_sock->local = local;
114+
llcp_sock->local = nfc_llcp_local_get(local);
115115
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
116116
llcp_sock->service_name_len = min_t(unsigned int,
117117
llcp_addr.service_name_len,
@@ -487,7 +487,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
487487
}
488488

489489
llcp_sock->dev = dev;
490-
llcp_sock->local = local;
490+
llcp_sock->local = nfc_llcp_local_get(local);
491491
llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
492492
if (llcp_sock->ssap == LLCP_SAP_MAX) {
493493
ret = -ENOMEM;
@@ -701,22 +701,18 @@ struct sock *nfc_llcp_sock_alloc(struct socket *sock, int type, gfp_t gfp)
701701

702702
void nfc_llcp_sock_free(struct nfc_llcp_sock *sock)
703703
{
704-
struct nfc_llcp_local *local = sock->local;
705-
706704
kfree(sock->service_name);
707705

708706
skb_queue_purge(&sock->tx_queue);
709707
skb_queue_purge(&sock->tx_pending_queue);
710708
skb_queue_purge(&sock->tx_backlog_queue);
711709

712710
list_del_init(&sock->accept_queue);
713-
714-
if (local != NULL && sock == local->sockets[sock->ssap])
715-
local->sockets[sock->ssap] = NULL;
716-
else
717-
list_del_init(&sock->list);
711+
list_del_init(&sock->list);
718712

719713
sock->parent = NULL;
714+
715+
nfc_llcp_local_put(sock->local);
720716
}
721717

722718
static int llcp_sock_create(struct net *net, struct socket *sock,

0 commit comments

Comments
 (0)