nfc pull request for net:

Code improvements
  - llcp: Fix use-after-free in llcp_sock_release()
  - llcp: Fix use-after-free race in nfc_llcp_recv_cc()
  - hci: fix out-of-bounds read in HCP header parsing
 Regression fixes:
  - nxp-nci: i2c: use rising-edge IRQ on ACPI systems
 
 Signed-off-by: David Heidelberg <david@ixit.cz>
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE13oJz+7cK71TpwR0YAI/xNNJIHIFAmoVkekACgkQYAI/xNNJ
 IHLrlBAApY2wQyqOR/HLGtO99SOKjzyAk5Ke8qv0tkGcTMhH4tlED3rD2tjOs1d6
 Fn5LEG7CqqfxX3ly/4B4hGYW4QtXlkTmCPwq7Bv5QnhTYNjwtrW2deLQB0vnPpKN
 qH8YD227zP12Wt+L68b/envlNDqiHvhkz5yiBfrEJ6yNHQ2ZYzOlVs/8yDqGtzJC
 HpkL+b3VyCd3RJCPiuWvBmySoQjryij+y51UAfleJSate3y1PnJbjMecRJt50+Vv
 cwp73Lq+rNHRGDFNwM2XwQh4Sc0QfnIFSHKlrS4N02mtF6tRThvOO28joYPMlDKw
 k047uZfF9PFeWV2df3bAmfGDK1bAIwb5G9+H2NSnh55pNORxvIb/fyQSWp854riv
 asJ1iagteRGPHYpKuTLeUxK4+1PW2PWG0vMGOXOrFpWbg4iiOWHqmStTUpNt8j0J
 M87Ym0rWyBWXljOyVaQySQQY8kjnOVJBX0WdRyo0VZamcqlUv8c8hk3WYvoZo5ko
 mlMRRbVIO8v4aHhBwLis5UwsYLKoBeoQHYNSIf5gKw+DBqz3KjSFcVSNLEXCP0yG
 nwqzArAUCok4a5tY08xMGHhJbQbP5F5qt6JTGVikO9Ua6zrbq6ilFQT0d1XFPtBq
 H2SP5FtnliCnBm+9bs1wxcWzLW+rFcZ9y3/xH7dE0m2CnHaQhxo=
 =aWIg
 -----END PGP SIGNATURE-----

Merge tag 'nfc-7.1-rc6' of https://codeberg.org/linux-nfc/linux

David Heidelberg says:

====================
nfc pull request for net:

Code improvements
 - llcp: Fix use-after-free in llcp_sock_release()
 - llcp: Fix use-after-free race in nfc_llcp_recv_cc()
 - hci: fix out-of-bounds read in HCP header parsing
Regression fixes:
 - nxp-nci: i2c: use rising-edge IRQ on ACPI systems

Signed-off-by: David Heidelberg <david@ixit.cz>

* tag 'nfc-7.1-rc6' of https://codeberg.org/linux-nfc/linux:
  nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
  nfc: hci: fix out-of-bounds read in HCP header parsing
  nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
  nfc: llcp: Fix use-after-free in llcp_sock_release()
====================

Link: https://patch.msgid.link/217c0646-8a30-4037-b613-580c2b189729@ixit.cz
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-05-26 18:32:34 -07:00
commit e66c456f7c
5 changed files with 53 additions and 1 deletions

View File

@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/nfc.h>
#include <linux/gpio/consumer.h>
@ -267,6 +268,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct nxp_nci_i2c_phy *phy;
unsigned long irqflags;
int r;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
@ -303,9 +305,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client)
if (r < 0)
return r;
/*
* ACPI platforms may report incorrect IRQ trigger types
* (e.g. level-high), which can lead to interrupt storms.
*
* Use the historically stable rising-edge trigger for ACPI devices.
*
* On non-ACPI systems (e.g. Device Tree), prefer the firmware-
* provided trigger type, falling back to rising-edge if not set.
*/
if (ACPI_COMPANION(dev)) {
irqflags = IRQF_TRIGGER_RISING;
} else {
irqflags = irq_get_trigger_type(client->irq);
if (!irqflags)
irqflags = IRQF_TRIGGER_RISING;
}
r = request_threaded_irq(client->irq, NULL,
nxp_nci_i2c_irq_thread_fn,
IRQF_ONESHOT,
irqflags | IRQF_ONESHOT,
NXP_NCI_I2C_DRIVER_NAME, phy);
if (r < 0)
nfc_err(&client->dev, "Unable to register IRQ handler\n");

View File

@ -861,6 +861,11 @@ static void nfc_hci_recv_from_llc(struct nfc_hci_dev *hdev, struct sk_buff *skb)
struct sk_buff *frag_skb;
int msg_len;
if (!pskb_may_pull(skb, NFC_HCI_HCP_PACKET_HEADER_LEN)) {
kfree_skb(skb);
return;
}
packet = (struct hcp_packet *)skb->data;
if ((packet->header & ~NFC_HCI_FRAGMENT) == 0) {
skb_queue_tail(&hdev->rx_hcp_frags, skb);
@ -904,6 +909,11 @@ static void nfc_hci_recv_from_llc(struct nfc_hci_dev *hdev, struct sk_buff *skb)
* unblock waiting cmd context. Otherwise, enqueue to dispatch
* in separate context where handler can also execute command.
*/
if (!pskb_may_pull(hcp_skb, NFC_HCI_HCP_HEADER_LEN)) {
kfree_skb(hcp_skb);
return;
}
packet = (struct hcp_packet *)hcp_skb->data;
type = HCP_MSG_GET_TYPE(packet->message.header);
if (type == NFC_HCI_HCP_RESPONSE) {

View File

@ -1218,6 +1218,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
sk = &llcp_sock->sk;
lock_sock(sk);
/* Check if socket was destroyed whilst waiting for the lock */
if (!sk_hashed(sk)) {
release_sock(sk);
nfc_llcp_sock_put(llcp_sock);
return;
}
/* Unlink from connecting and link to the client array */
nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
nfc_llcp_sock_link(&local->sockets, sk);
@ -1229,6 +1238,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local,
sk->sk_state = LLCP_CONNECTED;
sk->sk_state_change(sk);
release_sock(sk);
nfc_llcp_sock_put(llcp_sock);
}

View File

@ -633,6 +633,8 @@ static int llcp_sock_release(struct socket *sock)
if (sock->type == SOCK_RAW)
nfc_llcp_sock_unlink(&local->raw_sockets, sk);
else if (sk->sk_state == LLCP_CONNECTING)
nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
else
nfc_llcp_sock_unlink(&local->sockets, sk);

View File

@ -439,6 +439,11 @@ void nci_hci_data_received_cb(void *context,
return;
}
if (!pskb_may_pull(skb, NCI_HCI_HCP_PACKET_HEADER_LEN)) {
kfree_skb(skb);
return;
}
packet = (struct nci_hcp_packet *)skb->data;
if ((packet->header & ~NCI_HCI_FRAGMENT) == 0) {
skb_queue_tail(&ndev->hci_dev->rx_hcp_frags, skb);
@ -482,6 +487,11 @@ void nci_hci_data_received_cb(void *context,
* unblock waiting cmd context. Otherwise, enqueue to dispatch
* in separate context where handler can also execute command.
*/
if (!pskb_may_pull(hcp_skb, NCI_HCI_HCP_HEADER_LEN)) {
kfree_skb(hcp_skb);
return;
}
packet = (struct nci_hcp_packet *)hcp_skb->data;
type = NCI_HCP_MSG_GET_TYPE(packet->message.header);
if (type == NCI_HCI_HCP_RESPONSE) {