[PATCH net] nfc: nci: Fix uninit-value in nci_dev_up

From: Ryosuke Yasuoka
Date: Tue Mar 12 2024 - 10:57:48 EST


syzbot reported the following unitit-value access issue [1]:

nci_ntf_packet() calls each ntf operation parsed from skb->data. When
the payload length is zero, each operation handler reads uninitialized
payload and KMSAN detects this issue. Such notification packet should be
silently discarded since it is unexpected for any notification handlers.

This patch resolved this issue by checking payload size before calling
each notification handler codes.

BUG: KMSAN: uninit-value in nci_init_req net/nfc/nci/core.c:177 [inline]
BUG: KMSAN: uninit-value in __nci_request net/nfc/nci/core.c:108 [inline]
BUG: KMSAN: uninit-value in nci_open_device net/nfc/nci/core.c:521 [inline]
BUG: KMSAN: uninit-value in nci_dev_up+0xfec/0x1b10 net/nfc/nci/core.c:632
nci_init_req net/nfc/nci/core.c:177 [inline]
__nci_request net/nfc/nci/core.c:108 [inline]
nci_open_device net/nfc/nci/core.c:521 [inline]
nci_dev_up+0xfec/0x1b10 net/nfc/nci/core.c:632
nfc_dev_up+0x26e/0x440 net/nfc/core.c:118
nfc_genl_dev_up+0xfe/0x1d0 net/nfc/netlink.c:770
genl_family_rcv_msg_doit net/netlink/genetlink.c:972 [inline]
genl_family_rcv_msg net/netlink/genetlink.c:1052 [inline]
genl_rcv_msg+0x11ec/0x1290 net/netlink/genetlink.c:1067
netlink_rcv_skb+0x371/0x650 net/netlink/af_netlink.c:2545
genl_rcv+0x40/0x60 net/netlink/genetlink.c:1076
netlink_unicast_kernel net/netlink/af_netlink.c:1342 [inline]
netlink_unicast+0xf47/0x1250 net/netlink/af_netlink.c:1368
netlink_sendmsg+0x1238/0x13d0 net/netlink/af_netlink.c:1910
sock_sendmsg_nosec net/socket.c:730 [inline]
__sock_sendmsg net/socket.c:745 [inline]
____sys_sendmsg+0x9c2/0xd60 net/socket.c:2584
___sys_sendmsg+0x28d/0x3c0 net/socket.c:2638
__sys_sendmsg net/socket.c:2667 [inline]
__do_sys_sendmsg net/socket.c:2676 [inline]
__se_sys_sendmsg net/socket.c:2674 [inline]
__x64_sys_sendmsg+0x307/0x490 net/socket.c:2674
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0x6d/0x140 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

Uninit was stored to memory at:
nci_core_reset_ntf_packet net/nfc/nci/ntf.c:36 [inline]
nci_ntf_packet+0x19dc/0x39c0 net/nfc/nci/ntf.c:782
nci_rx_work+0x213/0x500 net/nfc/nci/core.c:1522
process_one_work kernel/workqueue.c:2633 [inline]
process_scheduled_works+0x104e/0x1e70 kernel/workqueue.c:2706
worker_thread+0xf45/0x1490 kernel/workqueue.c:2787
kthread+0x3ed/0x540 kernel/kthread.c:388
ret_from_fork+0x66/0x80 arch/x86/kernel/process.c:147
ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:242

Uninit was created at:
slab_post_alloc_hook+0x129/0xa70 mm/slab.h:768
slab_alloc_node mm/slub.c:3478 [inline]
kmem_cache_alloc_node+0x5e9/0xb10 mm/slub.c:3523
kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:560
__alloc_skb+0x318/0x740 net/core/skbuff.c:651
alloc_skb include/linux/skbuff.h:1286 [inline]
virtual_ncidev_write+0x6d/0x280 drivers/nfc/virtual_ncidev.c:120
vfs_write+0x48b/0x1200 fs/read_write.c:588
ksys_write+0x20f/0x4c0 fs/read_write.c:643
__do_sys_write fs/read_write.c:655 [inline]
__se_sys_write fs/read_write.c:652 [inline]
__x64_sys_write+0x93/0xd0 fs/read_write.c:652
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0x6d/0x140 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x63/0x6b

CPU: 1 PID: 5012 Comm: syz-executor935 Not tainted 6.7.0-syzkaller-00562-g9f8413c4a66f #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/17/2023

Fixes: 6a2968aaf50c ("NFC: basic NCI protocol implementation")
Reported-and-tested-by: syzbot+7ea9413ea6749baf5574@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=7ea9413ea6749baf5574 [1]
Signed-off-by: Ryosuke Yasuoka <ryasuoka@xxxxxxxxxx>
---
net/nfc/nci/ntf.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 994a0a1efb58..56624387e253 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -765,6 +765,9 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
nci_opcode_oid(ntf_opcode),
nci_plen(skb->data));

+ if (!nci_plen(skb->data))
+ goto end;
+
/* strip the nci control header */
skb_pull(skb, NCI_CTRL_HDR_SIZE);

--
2.44.0