Skip to content

Commit 6709d4b

Browse files
f0rm2l1ndavem330
authored andcommitted
net: nfc: Fix use-after-free caused by nfc_llcp_find_local
This commit fixes several use-after-free that caused by function nfc_llcp_find_local(). For example, one UAF can happen when below buggy time window occurs. // nfc_genl_llc_get_params | // nfc_unregister_device | dev = nfc_get_device(idx); | device_lock(...) if (!dev) | dev->shutting_down = true; return -ENODEV; | device_unlock(...); | device_lock(...); | // nfc_llcp_unregister_device | nfc_llcp_find_local() nfc_llcp_find_local(...); | | local_cleanup() if (!local) { | rc = -ENODEV; | // nfc_llcp_local_put goto exit; | kref_put(.., local_release) } | | // local_release | list_del(&local->list) // nfc_genl_send_params | kfree() local->dev->idx !!!UAF!!! | | and the crash trace for the one of the discussed UAF like: BUG: KASAN: slab-use-after-free in nfc_genl_llc_get_params+0x72f/0x780 net/nfc/netlink.c:1045 Read of size 8 at addr ffff888105b0e410 by task 20114 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x72/0xa0 lib/dump_stack.c:106 print_address_description mm/kasan/report.c:319 [inline] print_report+0xcc/0x620 mm/kasan/report.c:430 kasan_report+0xb2/0xe0 mm/kasan/report.c:536 nfc_genl_send_params net/nfc/netlink.c:999 [inline] nfc_genl_llc_get_params+0x72f/0x780 net/nfc/netlink.c:1045 genl_family_rcv_msg_doit.isra.0+0x1ee/0x2e0 net/netlink/genetlink.c:968 genl_family_rcv_msg net/netlink/genetlink.c:1048 [inline] genl_rcv_msg+0x503/0x7d0 net/netlink/genetlink.c:1065 netlink_rcv_skb+0x161/0x430 net/netlink/af_netlink.c:2548 genl_rcv+0x28/0x40 net/netlink/genetlink.c:1076 netlink_unicast_kernel net/netlink/af_netlink.c:1339 [inline] netlink_unicast+0x644/0x900 net/netlink/af_netlink.c:1365 netlink_sendmsg+0x934/0xe70 net/netlink/af_netlink.c:1913 sock_sendmsg_nosec net/socket.c:724 [inline] sock_sendmsg+0x1b6/0x200 net/socket.c:747 ____sys_sendmsg+0x6e9/0x890 net/socket.c:2501 ___sys_sendmsg+0x110/0x1b0 net/socket.c:2555 __sys_sendmsg+0xf7/0x1d0 net/socket.c:2584 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3f/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x72/0xdc RIP: 0033:0x7f34640a2389 RSP: 002b:00007f3463415168 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007f34641c1f80 RCX: 00007f34640a2389 RDX: 0000000000000000 RSI: 0000000020000240 RDI: 0000000000000006 RBP: 00007f34640ed493 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007ffe38449ecf R14: 00007f3463415300 R15: 0000000000022000 </TASK> Allocated by task 20116: kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 ____kasan_kmalloc mm/kasan/common.c:374 [inline] __kasan_kmalloc+0x7f/0x90 mm/kasan/common.c:383 kmalloc include/linux/slab.h:580 [inline] kzalloc include/linux/slab.h:720 [inline] nfc_llcp_register_device+0x49/0xa40 net/nfc/llcp_core.c:1567 nfc_register_device+0x61/0x260 net/nfc/core.c:1124 nci_register_device+0x776/0xb20 net/nfc/nci/core.c:1257 virtual_ncidev_open+0x147/0x230 drivers/nfc/virtual_ncidev.c:148 misc_open+0x379/0x4a0 drivers/char/misc.c:165 chrdev_open+0x26c/0x780 fs/char_dev.c:414 do_dentry_open+0x6c4/0x12a0 fs/open.c:920 do_open fs/namei.c:3560 [inline] path_openat+0x24fe/0x37e0 fs/namei.c:3715 do_filp_open+0x1ba/0x410 fs/namei.c:3742 do_sys_openat2+0x171/0x4c0 fs/open.c:1356 do_sys_open fs/open.c:1372 [inline] __do_sys_openat fs/open.c:1388 [inline] __se_sys_openat fs/open.c:1383 [inline] __x64_sys_openat+0x143/0x200 fs/open.c:1383 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3f/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x72/0xdc Freed by task 20115: kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 kasan_set_track+0x25/0x30 mm/kasan/common.c:52 kasan_save_free_info+0x2e/0x50 mm/kasan/generic.c:521 ____kasan_slab_free mm/kasan/common.c:236 [inline] ____kasan_slab_free mm/kasan/common.c:200 [inline] __kasan_slab_free+0x10a/0x190 mm/kasan/common.c:244 kasan_slab_free include/linux/kasan.h:162 [inline] slab_free_hook mm/slub.c:1781 [inline] slab_free_freelist_hook mm/slub.c:1807 [inline] slab_free mm/slub.c:3787 [inline] __kmem_cache_free+0x7a/0x190 mm/slub.c:3800 local_release net/nfc/llcp_core.c:174 [inline] kref_put include/linux/kref.h:65 [inline] nfc_llcp_local_put net/nfc/llcp_core.c:182 [inline] nfc_llcp_local_put net/nfc/llcp_core.c:177 [inline] nfc_llcp_unregister_device+0x206/0x290 net/nfc/llcp_core.c:1620 nfc_unregister_device+0x160/0x1d0 net/nfc/core.c:1179 virtual_ncidev_close+0x52/0xa0 drivers/nfc/virtual_ncidev.c:163 __fput+0x252/0xa20 fs/file_table.c:321 task_work_run+0x174/0x270 kernel/task_work.c:179 resume_user_mode_work include/linux/resume_user_mode.h:49 [inline] exit_to_user_mode_loop kernel/entry/common.c:171 [inline] exit_to_user_mode_prepare+0x108/0x110 kernel/entry/common.c:204 __syscall_exit_to_user_mode_work kernel/entry/common.c:286 [inline] syscall_exit_to_user_mode+0x21/0x50 kernel/entry/common.c:297 do_syscall_64+0x4c/0x90 arch/x86/entry/common.c:86 entry_SYSCALL_64_after_hwframe+0x72/0xdc Last potentially related work creation: kasan_save_stack+0x22/0x50 mm/kasan/common.c:45 __kasan_record_aux_stack+0x95/0xb0 mm/kasan/generic.c:491 kvfree_call_rcu+0x29/0xa80 kernel/rcu/tree.c:3328 drop_sysctl_table+0x3be/0x4e0 fs/proc/proc_sysctl.c:1735 unregister_sysctl_table.part.0+0x9c/0x190 fs/proc/proc_sysctl.c:1773 unregister_sysctl_table+0x24/0x30 fs/proc/proc_sysctl.c:1753 neigh_sysctl_unregister+0x5f/0x80 net/core/neighbour.c:3895 addrconf_notify+0x140/0x17b0 net/ipv6/addrconf.c:3684 notifier_call_chain+0xbe/0x210 kernel/notifier.c:87 call_netdevice_notifiers_info+0xb5/0x150 net/core/dev.c:1937 call_netdevice_notifiers_extack net/core/dev.c:1975 [inline] call_netdevice_notifiers net/core/dev.c:1989 [inline] dev_change_name+0x3c3/0x870 net/core/dev.c:1211 dev_ifsioc+0x800/0xf70 net/core/dev_ioctl.c:376 dev_ioctl+0x3d9/0xf80 net/core/dev_ioctl.c:542 sock_do_ioctl+0x160/0x260 net/socket.c:1213 sock_ioctl+0x3f9/0x670 net/socket.c:1316 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:870 [inline] __se_sys_ioctl fs/ioctl.c:856 [inline] __x64_sys_ioctl+0x19e/0x210 fs/ioctl.c:856 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x3f/0x90 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x72/0xdc The buggy address belongs to the object at ffff888105b0e400 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 16 bytes inside of freed 1024-byte region [ffff888105b0e400, ffff888105b0e800) The buggy address belongs to the physical page: head:ffffea000416c200 order:3 entire_mapcount:0 nr_pages_mapped:0 pincount:0 flags: 0x200000000010200(slab|head|node=0|zone=2) raw: 0200000000010200 ffff8881000430c0 ffffea00044c7010 ffffea0004510e10 raw: 0000000000000000 00000000000a000a 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff888105b0e300: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff888105b0e380: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc >ffff888105b0e400: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff888105b0e480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ffff888105b0e500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb In summary, this patch solves those use-after-free by 1. Re-implement the nfc_llcp_find_local(). The current version does not grab the reference when getting the local from the linked list. For example, the llcp_sock_bind() gets the reference like below: // llcp_sock_bind() local = nfc_llcp_find_local(dev); // A ..... \ | raceable ..... / llcp_sock->local = nfc_llcp_local_get(local); // B There is an apparent race window that one can drop the reference and free the local object fetched in (A) before (B) gets the reference. 2. Some callers of the nfc_llcp_find_local() do not grab the reference at all. For example, the nfc_genl_llc_{{get/set}_params/sdreq} functions. We add the nfc_llcp_local_put() for them. Moreover, we add the necessary error handling function to put the reference. 3. Add the nfc_llcp_remove_local() helper. The local object is removed from the linked list in local_release() when all reference is gone. This patch removes it when nfc_llcp_unregister_device() is called. Therefore, every caller of nfc_llcp_find_local() will get a reference even when the nfc_llcp_unregister_device() is called. This promises no use-after-free for the local object is ever possible. Fixes: 52feb44 ("NFC: Extend netlink interface for LTO, RW, and MIUX parameters support") Fixes: c7aa122 ("NFC: Take a reference on the LLCP local pointer when creating a socket") Signed-off-by: Lin Ma <linma@zju.edu.cn> Reviewed-by: Simon Horman <simon.horman@corigine.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent d1b3554 commit 6709d4b

File tree

6 files changed

+77
-24
lines changed

6 files changed

+77
-24
lines changed

Diff for: net/nfc/llcp.h

-1
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,6 @@ void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
201201
void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
202202
void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock);
203203
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
204-
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
205204
int nfc_llcp_local_put(struct nfc_llcp_local *local);
206205
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
207206
struct nfc_llcp_sock *sock);

Diff for: net/nfc/llcp_commands.c

+9-3
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
359359
struct sk_buff *skb;
360360
struct nfc_llcp_local *local;
361361
u16 size = 0;
362+
int err;
362363

363364
local = nfc_llcp_find_local(dev);
364365
if (local == NULL)
@@ -368,8 +369,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
368369
size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
369370

370371
skb = alloc_skb(size, GFP_KERNEL);
371-
if (skb == NULL)
372-
return -ENOMEM;
372+
if (skb == NULL) {
373+
err = -ENOMEM;
374+
goto out;
375+
}
373376

374377
skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
375378

@@ -379,8 +382,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
379382

380383
nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX);
381384

382-
return nfc_data_exchange(dev, local->target_idx, skb,
385+
err = nfc_data_exchange(dev, local->target_idx, skb,
383386
nfc_llcp_recv, local);
387+
out:
388+
nfc_llcp_local_put(local);
389+
return err;
384390
}
385391

386392
int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)

Diff for: net/nfc/llcp_core.c

+42-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
1818

1919
static LIST_HEAD(llcp_devices);
20+
/* Protects llcp_devices list */
21+
static DEFINE_SPINLOCK(llcp_devices_lock);
2022

2123
static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);
2224

@@ -141,7 +143,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
141143
write_unlock(&local->raw_sockets.lock);
142144
}
143145

144-
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
146+
static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
145147
{
146148
kref_get(&local->ref);
147149

@@ -169,7 +171,6 @@ static void local_release(struct kref *ref)
169171

170172
local = container_of(ref, struct nfc_llcp_local, ref);
171173

172-
list_del(&local->list);
173174
local_cleanup(local);
174175
kfree(local);
175176
}
@@ -282,12 +283,33 @@ static void nfc_llcp_sdreq_timer(struct timer_list *t)
282283
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
283284
{
284285
struct nfc_llcp_local *local;
286+
struct nfc_llcp_local *res = NULL;
285287

288+
spin_lock(&llcp_devices_lock);
286289
list_for_each_entry(local, &llcp_devices, list)
287-
if (local->dev == dev)
290+
if (local->dev == dev) {
291+
res = nfc_llcp_local_get(local);
292+
break;
293+
}
294+
spin_unlock(&llcp_devices_lock);
295+
296+
return res;
297+
}
298+
299+
static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev)
300+
{
301+
struct nfc_llcp_local *local, *tmp;
302+
303+
spin_lock(&llcp_devices_lock);
304+
list_for_each_entry_safe(local, tmp, &llcp_devices, list)
305+
if (local->dev == dev) {
306+
list_del(&local->list);
307+
spin_unlock(&llcp_devices_lock);
288308
return local;
309+
}
310+
spin_unlock(&llcp_devices_lock);
289311

290-
pr_debug("No device found\n");
312+
pr_warn("Shutting down device not found\n");
291313

292314
return NULL;
293315
}
@@ -608,12 +630,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
608630

609631
*general_bytes_len = local->gb_len;
610632

633+
nfc_llcp_local_put(local);
634+
611635
return local->gb;
612636
}
613637

614638
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len)
615639
{
616640
struct nfc_llcp_local *local;
641+
int err;
617642

618643
if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN)
619644
return -EINVAL;
@@ -630,12 +655,16 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len)
630655

631656
if (memcmp(local->remote_gb, llcp_magic, 3)) {
632657
pr_err("MAC does not support LLCP\n");
633-
return -EINVAL;
658+
err = -EINVAL;
659+
goto out;
634660
}
635661

636-
return nfc_llcp_parse_gb_tlv(local,
662+
err = nfc_llcp_parse_gb_tlv(local,
637663
&local->remote_gb[3],
638664
local->remote_gb_len - 3);
665+
out:
666+
nfc_llcp_local_put(local);
667+
return err;
639668
}
640669

641670
static u8 nfc_llcp_dsap(const struct sk_buff *pdu)
@@ -1517,6 +1546,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
15171546

15181547
__nfc_llcp_recv(local, skb);
15191548

1549+
nfc_llcp_local_put(local);
1550+
15201551
return 0;
15211552
}
15221553

@@ -1533,6 +1564,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
15331564

15341565
/* Close and purge all existing sockets */
15351566
nfc_llcp_socket_release(local, true, 0);
1567+
1568+
nfc_llcp_local_put(local);
15361569
}
15371570

15381571
void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
@@ -1558,6 +1591,8 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
15581591
mod_timer(&local->link_timer,
15591592
jiffies + msecs_to_jiffies(local->remote_lto));
15601593
}
1594+
1595+
nfc_llcp_local_put(local);
15611596
}
15621597

15631598
int nfc_llcp_register_device(struct nfc_dev *ndev)
@@ -1608,7 +1643,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
16081643

16091644
void nfc_llcp_unregister_device(struct nfc_dev *dev)
16101645
{
1611-
struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
1646+
struct nfc_llcp_local *local = nfc_llcp_remove_local(dev);
16121647

16131648
if (local == NULL) {
16141649
pr_debug("No such device\n");

Diff for: net/nfc/llcp_sock.c

+10-8
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
9999
}
100100

101101
llcp_sock->dev = dev;
102-
llcp_sock->local = nfc_llcp_local_get(local);
102+
llcp_sock->local = local;
103103
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
104104
llcp_sock->service_name_len = min_t(unsigned int,
105105
llcp_addr.service_name_len,
@@ -186,7 +186,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
186186
}
187187

188188
llcp_sock->dev = dev;
189-
llcp_sock->local = nfc_llcp_local_get(local);
189+
llcp_sock->local = local;
190190
llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
191191

192192
nfc_llcp_sock_link(&local->raw_sockets, sk);
@@ -696,22 +696,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
696696
if (dev->dep_link_up == false) {
697697
ret = -ENOLINK;
698698
device_unlock(&dev->dev);
699-
goto put_dev;
699+
goto sock_llcp_put_local;
700700
}
701701
device_unlock(&dev->dev);
702702

703703
if (local->rf_mode == NFC_RF_INITIATOR &&
704704
addr->target_idx != local->target_idx) {
705705
ret = -ENOLINK;
706-
goto put_dev;
706+
goto sock_llcp_put_local;
707707
}
708708

709709
llcp_sock->dev = dev;
710-
llcp_sock->local = nfc_llcp_local_get(local);
710+
llcp_sock->local = local;
711711
llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
712712
if (llcp_sock->ssap == LLCP_SAP_MAX) {
713713
ret = -ENOMEM;
714-
goto sock_llcp_put_local;
714+
goto sock_llcp_nullify;
715715
}
716716

717717
llcp_sock->reserved_ssap = llcp_sock->ssap;
@@ -757,11 +757,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
757757
sock_llcp_release:
758758
nfc_llcp_put_ssap(local, llcp_sock->ssap);
759759

760-
sock_llcp_put_local:
761-
nfc_llcp_local_put(llcp_sock->local);
760+
sock_llcp_nullify:
762761
llcp_sock->local = NULL;
763762
llcp_sock->dev = NULL;
764763

764+
sock_llcp_put_local:
765+
nfc_llcp_local_put(local);
766+
765767
put_dev:
766768
nfc_put_device(dev);
767769

Diff for: net/nfc/netlink.c

+15-5
Original file line numberDiff line numberDiff line change
@@ -1039,11 +1039,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
10391039
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10401040
if (!msg) {
10411041
rc = -ENOMEM;
1042-
goto exit;
1042+
goto put_local;
10431043
}
10441044

10451045
rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);
10461046

1047+
put_local:
1048+
nfc_llcp_local_put(local);
1049+
10471050
exit:
10481051
device_unlock(&dev->dev);
10491052

@@ -1105,7 +1108,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
11051108
if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
11061109
if (dev->dep_link_up) {
11071110
rc = -EINPROGRESS;
1108-
goto exit;
1111+
goto put_local;
11091112
}
11101113

11111114
local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]);
@@ -1117,6 +1120,9 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
11171120
if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
11181121
local->miux = cpu_to_be16(miux);
11191122

1123+
put_local:
1124+
nfc_llcp_local_put(local);
1125+
11201126
exit:
11211127
device_unlock(&dev->dev);
11221128

@@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
11721178

11731179
if (rc != 0) {
11741180
rc = -EINVAL;
1175-
goto exit;
1181+
goto put_local;
11761182
}
11771183

11781184
if (!sdp_attrs[NFC_SDP_ATTR_URI])
@@ -1191,7 +1197,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
11911197
sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
11921198
if (sdreq == NULL) {
11931199
rc = -ENOMEM;
1194-
goto exit;
1200+
goto put_local;
11951201
}
11961202

11971203
tlvs_len += sdreq->tlv_len;
@@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
12011207

12021208
if (hlist_empty(&sdreq_list)) {
12031209
rc = -EINVAL;
1204-
goto exit;
1210+
goto put_local;
12051211
}
12061212

12071213
rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);
1214+
1215+
put_local:
1216+
nfc_llcp_local_put(local);
1217+
12081218
exit:
12091219
device_unlock(&dev->dev);
12101220

Diff for: net/nfc/nfc.h

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, const u8 *gb, u8 gb_len);
5252
u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
5353
int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
5454
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
55+
int nfc_llcp_local_put(struct nfc_llcp_local *local);
5556
int __init nfc_llcp_init(void);
5657
void nfc_llcp_exit(void);
5758
void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);

0 commit comments

Comments
 (0)