From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D8BC1481FB9; Tue, 25 Aug 2026 13:56:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787666181; cv=none; b=RaAf8AloH7BLiq9ymhldCsgEMiLTc3urJcPgYg7LY5somAXmujQrdBOpkSBbLi4naKqbOkiUAyZWhNEskdZ0sCFQiHVNm9I2lfFgboiuIuLIFQe8oeo0VW9P9CLZFDQ00AH9nuudI+3enL0gNhQX14WGzJO4dvEdIxhT3adCxA0= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787666181; c=relaxed/simple; bh=NI6WzmGcfUDeE/ww5b2V1IKuF1udb5QjIjS5ycje0Ak=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rKmzd2VRbrytuTnZUx1ojDPN1an/sEWz+7vEJPtc/kdxam4KzfchcRhX/pQ8CvKF6iy2ulL6sLMTCY2FXG6VWrF59PiTAiI52tYwnIsqh3gtTu2msXPc9UR4xItaSMs8hUzkRo34EwSNiR+jbswBMI16vI21xxJmZkN/GTR/8i0= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=DPNyOF8n; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="DPNyOF8n" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3B7181F000E9; Tue, 25 Aug 2026 13:56:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1787666179; bh=WYI3lOmCMGGsgwBm/064jgrysOJ5vzHRTm3+FwlzO2o=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=DPNyOF8nGkmX4r+X5Kzq5vCYg0tnZzcILG/3sfKIfpxA+eCOFrfvuKxC1ZrNnuuql PjCYaF4/dhVMF3O/8NXR2ObC/l/m5+sc7i507Qndr2TR8FnLQpfn1vZmouydrsLFDz ljEdHGffQLZoTBWAJIZK/ODZ2+b5CcJCKAjF/8C8= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Simon Horman , Bryam Vargas , David Heidelberg Subject: [PATCH 5.15 30/76] nfc: fdp: bound the device-reported read length and fix an skb leak Date: Tue, 25 Aug 2026 15:26:23 +0200 Message-ID: <20260825132542.741609110@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260825132541.568214149@linuxfoundation.org> References: <20260825132541.568214149@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 5.15-stable review patch. If anyone has any objections, please let me know. ------------------ From: Bryam Vargas commit 7ad21dcfeb5181af0c3ee2608808c0c0a5283aa1 upstream. fdp_nci_i2c_read() takes the next packet length from two device-supplied bytes and never validates it. The value is a u16 used as the i2c_master_recv() count into a 261-byte on-stack buffer: a malicious, counterfeit or malfunctioning controller (or an i2c bus interposer) can drive it far past the buffer for a stack out-of-bounds write that clobbers the canary and return address, or below the minimum frame size (directly, or by truncating the computed sum) so the header/LRC strip and the next length read run past a short receive. Reject a length outside [FDP_NCI_I2C_MIN_PAYLOAD, FDP_NCI_I2C_MAX_PAYLOAD], as a corrupted packet already is, and force resynchronization. The same loop allocates one data skb per iteration and assumes a length packet followed by a data packet; a device that sends two data packets in one call leaks the first skb when the second allocation overwrites it. Free a previously allocated skb before allocating the next. Fixes: a06347c04c13 ("NFC: Add Intel Fields Peak NFC solution driver") Cc: stable@vger.kernel.org Suggested-by: Simon Horman Signed-off-by: Bryam Vargas Link: https://patch.msgid.link/20260616-b4-disp-b1f8ab4c-v2-1-2d1fe5955325@proton.me Signed-off-by: David Heidelberg Signed-off-by: Greg Kroah-Hartman --- drivers/nfc/fdp/i2c.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) --- a/drivers/nfc/fdp/i2c.c +++ b/drivers/nfc/fdp/i2c.c @@ -166,9 +166,36 @@ static int fdp_nci_i2c_read(struct fdp_i /* Packet that contains a length */ if (tmp[0] == 0 && tmp[1] == 0) { phy->next_read_size = (tmp[2] << 8) + tmp[3] + 3; + + /* + * next_read_size is taken from the device and is used + * as the i2c_master_recv() count for the next packet + * and as the data skb size. A value above the receive + * buffer overflows tmp[]; one below the minimum frame + * size runs the header/LRC strip and the length-field + * read past a short receive. Either way the packet is + * corrupt: drop it and force resynchronization. + */ + if (phy->next_read_size < FDP_NCI_I2C_MIN_PAYLOAD || + phy->next_read_size > FDP_NCI_I2C_MAX_PAYLOAD) { + dev_dbg(&client->dev, "%s: corrupted packet\n", + __func__); + phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD; + goto flush; + } } else { phy->next_read_size = FDP_NCI_I2C_MIN_PAYLOAD; + /* + * Only one data packet is delivered per call; if the + * device sends another, do not overwrite and leak the + * skb allocated for the previous one. + */ + if (*skb) { + kfree_skb(*skb); + *skb = NULL; + } + *skb = alloc_skb(len, GFP_KERNEL); if (*skb == NULL) { r = -ENOMEM;