digital_recv_dep_data_gather() allocates chaining_skb with nfc_alloc_recv_skb(), which only reserves 1 byte of headroom. Once the chained payload is fully gathered, it is passed to digital_tg_send_dep_res() or digital_in_send_dep_req(), both of which push a 3-byte DEP header plus up to 2 bytes of SoD, needing at least 5 bytes of headroom. skb_push() unconditionally calls skb_under_panic() when headroom is insufficient, so this is a guaranteed kernel BUG. A remote NFC peer can trigger it in target mode by sending MI-flagged DEP_REQ fragments followed by an ACK with matching PNI, or in initiator mode via the symmetric chaining ACK path. Normal DEP frames use digital_skb_alloc() which gets headroom from ddev->tx_headroom, so the bug only manifests through the chaining_skb path. The skb_copy_expand() reallocation in the same function preserves the original 1-byte headroom and does not add tailroom for the CRC or DID byte appended by the send path. Switch to digital_skb_alloc() which reserves the same headroom and tailroom that every other send buffer in this file uses, and pass ddev->tx_headroom and ddev->tx_tailroom to skb_copy_expand(). Fixes: c12715ab3f01 ("NFC: digital: Add NFC-DEP Receive Chaining Support") Cc: stable@vger.kernel.org Signed-off-by: Liu Chao --- net/nfc/digital_dep.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c index 3982fa084..6d8e662a3 100644 --- a/net/nfc/digital_dep.c +++ b/net/nfc/digital_dep.c @@ -240,8 +240,8 @@ digital_recv_dep_data_gather(struct nfc_digital_dev *ddev, u8 pfb, if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb) && (!ddev->chaining_skb)) { ddev->chaining_skb = - nfc_alloc_recv_skb(8 * ddev->local_payload_max, - GFP_KERNEL); + digital_skb_alloc(ddev, + 8 * ddev->local_payload_max); if (!ddev->chaining_skb) { rc = -ENOMEM; goto error; @@ -251,9 +251,9 @@ digital_recv_dep_data_gather(struct nfc_digital_dev *ddev, u8 pfb, if (ddev->chaining_skb) { if (resp->len > skb_tailroom(ddev->chaining_skb)) { new_skb = skb_copy_expand(ddev->chaining_skb, - skb_headroom( - ddev->chaining_skb), - 8 * ddev->local_payload_max, + ddev->tx_headroom, + 8 * ddev->local_payload_max + + ddev->tx_tailroom, GFP_KERNEL); if (!new_skb) { rc = -ENOMEM; -- 2.50.1