From nobody Sat Jul 25 02:43:54 2026 Received: from cstnet.cn (smtp25.cstnet.cn [159.226.251.25]) (using TLSv1.2 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5C2874071DA for ; Mon, 20 Jul 2026 11:55:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.226.251.25 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784548534; cv=none; b=hYxz6wD2jpQJtkwoByZ9igfbZBp2kav0bYzm40JM124BEteHGPzeQlydDGIXu6fUaF+cUOWYVCksIZ3jA07+CUFs+F0NxqRbnWDL/WFIAOUHmEzBpL33c1/Cc9tUcSG7CaGAeNfWR/RGk0bJWmH1/EXWmT7e6juc7l4Q+rwyrRc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784548534; c=relaxed/simple; bh=3PO0t8ZtqUOoq0w2EgdGjZdylLOHKyXzDDe7R1lF44Y=; h=From:To:Cc:Subject:Date:Message-ID:Content-Type:MIME-Version; b=BgjBcg9HSonDxL0/hAdaGBy2UzprgCjItf3pcmjCE6659/TEPhbBddXT+MhEYbgEzxeYOHaeOJ0pXBesQkfsNre34XZ65qbDJG6XO3BiGWhDAHC3vfnwDjWYrqzBbTvdYaZ/1fwVS6a8e3E0OjaQXDzd80JYXsJ/R58AkUdJfHk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn; spf=pass smtp.mailfrom=iscas.ac.cn; arc=none smtp.client-ip=159.226.251.25 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iscas.ac.cn Received: from localhost.localdomain (unknown [111.196.245.140]) by APP-05 (Coremail) with SMTP id zQCowAA3pT+rDF5qCdKIAA--.52081S2; Mon, 20 Jul 2026 19:55:24 +0800 (CST) From: Pengpeng Hou To: Lee Jones Cc: mfd@lists.linux.dev, linux-kernel@vger.kernel.org, Pengpeng Hou Subject: [PATCH v2] mfd: rave-sp: validate received frame payload lengths Date: Mon, 20 Jul 2026 19:55:23 +0800 Message-ID: <20260720115523.99956-1-pengpeng@iscas.ac.cn> X-Mailer: git-send-email 2.50.1 Content-Type: text/plain; charset="utf-8" Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: zQCowAA3pT+rDF5qCdKIAA--.52081S2 X-Coremail-Antispam: 1UD129KBjvJXoWxtrW5ZFW8GFW7tryfXrWUurg_yoW7Kr1kpa sYga45Zr45Jws7Cw43Jw4rC3s0kayxKw4UKFn8Ja4xAFn29ayDKFy7GF4vq340vrn5Ca4j g34UtrW7ta1DtFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUyl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI8IcIk0 rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xGY2AK02 1l84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14v26F4j 6r4UJwA2z4x0Y4vEx4A2jsIE14v26rxl6s0DM28EF7xvwVC2z280aVCY1x0267AKxVW0oV Cq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0 I7IYx2IY67AKxVWUtVWrXwAv7VC2z280aVAFwI0_Gr0_Cr1lOx8S6xCaFVCjc4AY6r1j6r 4UM4x0Y48IcxkI7VAKI48JM4x0x7Aq67IIx4CEVc8vx2IErcIFxwCF04k20xvY0x0EwIxG rwCFx2IqxVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4 vE14v26r106r1rMI8E67AF67kF1VAFwI0_JF0_Jw1lIxkGc2Ij64vIr41lIxAIcVC0I7IY x2IY67AKxVW8JVW5JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE42xK8V AvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E 14v26r4j6r4UJbIYCTnIWIevJa73UjIFyTuYvjfU0pBTUUUUU X-CM-SenderInfo: pshqw1xhqjqxpvfd2hldfou0/ A received RAVE-SP frame contains protocol data followed by a variant-specific one- or two-byte checksum. rave_sp_receive_frame() derives a checksum pointer before proving that the frame contains the checksum, then passes the checksum-inclusive length to handlers that index the command, acknowledgment ID and event-data bytes or derive a reply payload length. Name those protocol field offsets, prove the checksum extent before deriving the protocol-data length, pass only that data length to the handlers, and require the complete event or reply prefix before consuming it. Fixes: 538ee27290fa ("mfd: Add driver for RAVE Supervisory Processor") Signed-off-by: Pengpeng Hou --- Changes since v1: https://lore.kernel.org/all/20260706092337.78754-1-pengpe= ng@iscas.ac.cn/ - replace numeric bytes 0, 1 and 2 with protocol field offsets - strip the variant checksum from the length passed to event and reply handlers - rebase onto v7.2-rc4 drivers/mfd/rave-sp.c | 64 +++++++++++++++++++++++++++++++++++------------= ---- 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c index c1b78d127a26..05d26d92df03 100644 --- a/drivers/mfd/rave-sp.c +++ b/drivers/mfd/rave-sp.c @@ -63,6 +63,12 @@ #define RAVE_SP_TX_BUFFER_SIZE \ (RAVE_SP_STX_ETX_SIZE + 2 * RAVE_SP_RX_BUFFER_SIZE) =20 +enum rave_sp_frame_offset { + RAVE_SP_FRAME_CODE_OFFSET, + RAVE_SP_FRAME_ACK_ID_OFFSET, + RAVE_SP_FRAME_DATA_OFFSET, +}; + /** * enum rave_sp_deframer_state - Possible state for de-framer * @@ -352,7 +358,7 @@ int rave_sp_exec(struct rave_sp *sp, int command, ret =3D 0; u8 ackid; =20 - command =3D sp->variant->cmd.translate(data[0]); + command =3D sp->variant->cmd.translate(data[RAVE_SP_FRAME_CODE_OFFSET]); if (command < 0) return command; =20 @@ -366,8 +372,8 @@ int rave_sp_exec(struct rave_sp *sp, sp->reply =3D &reply; mutex_unlock(&sp->reply_lock); =20 - data[0] =3D command; - data[1] =3D ackid; + data[RAVE_SP_FRAME_CODE_OFFSET] =3D command; + data[RAVE_SP_FRAME_ACK_ID_OFFSET] =3D ackid; =20 rave_sp_write(sp, data, data_size); =20 @@ -388,16 +394,23 @@ EXPORT_SYMBOL_GPL(rave_sp_exec); static void rave_sp_receive_event(struct rave_sp *sp, const unsigned char *data, size_t length) { - u8 cmd[] =3D { - [0] =3D rave_sp_reply_code(data[0]), - [1] =3D data[1], - }; + unsigned long action; + u8 cmd[RAVE_SP_FRAME_DATA_OFFSET]; + + if (length < RAVE_SP_FRAME_DATA_OFFSET + 1) { + dev_warn(&sp->serdev->dev, "Dropping short event frame\n"); + return; + } + + cmd[RAVE_SP_FRAME_CODE_OFFSET] =3D + rave_sp_reply_code(data[RAVE_SP_FRAME_CODE_OFFSET]); + cmd[RAVE_SP_FRAME_ACK_ID_OFFSET] =3D data[RAVE_SP_FRAME_ACK_ID_OFFSET]; =20 rave_sp_write(sp, cmd, sizeof(cmd)); =20 - blocking_notifier_call_chain(&sp->event_notifier_list, - rave_sp_action_pack(data[0], data[2]), - NULL); + action =3D rave_sp_action_pack(data[RAVE_SP_FRAME_CODE_OFFSET], + data[RAVE_SP_FRAME_DATA_OFFSET]); + blocking_notifier_call_chain(&sp->event_notifier_list, action, NULL); } =20 static void rave_sp_receive_reply(struct rave_sp *sp, @@ -405,27 +418,35 @@ static void rave_sp_receive_reply(struct rave_sp *sp, { struct device *dev =3D &sp->serdev->dev; struct rave_sp_reply *reply; - const size_t payload_length =3D length - 2; + size_t payload_length; + + if (length < RAVE_SP_FRAME_DATA_OFFSET) { + dev_warn(dev, "Dropping short reply frame\n"); + return; + } + payload_length =3D length - RAVE_SP_FRAME_DATA_OFFSET; =20 mutex_lock(&sp->reply_lock); reply =3D sp->reply; =20 if (reply) { - if (reply->code =3D=3D data[0] && reply->ackid =3D=3D data[1] && + if (reply->code =3D=3D data[RAVE_SP_FRAME_CODE_OFFSET] && + reply->ackid =3D=3D data[RAVE_SP_FRAME_ACK_ID_OFFSET] && payload_length >=3D reply->length) { /* * We are relying on memcpy(dst, src, 0) to be a no-op * when handling commands that have a no-payload reply */ - memcpy(reply->data, &data[2], reply->length); + memcpy(reply->data, &data[RAVE_SP_FRAME_DATA_OFFSET], + reply->length); complete(&reply->received); sp->reply =3D NULL; } else { dev_err(dev, "Ignoring incorrect reply\n"); dev_dbg(dev, "Code: expected =3D 0x%08x received =3D 0x%08x\n", - reply->code, data[0]); + reply->code, data[RAVE_SP_FRAME_CODE_OFFSET]); dev_dbg(dev, "ACK ID: expected =3D 0x%08x received =3D 0x%08x\n", - reply->ackid, data[1]); + reply->ackid, data[RAVE_SP_FRAME_ACK_ID_OFFSET]); dev_dbg(dev, "Length: expected =3D %zu received =3D %zu\n", reply->length, payload_length); } @@ -439,10 +460,10 @@ static void rave_sp_receive_frame(struct rave_sp *sp, size_t length) { const size_t checksum_length =3D sp->variant->checksum->length; - const size_t payload_length =3D length - checksum_length; - const u8 *crc_reported =3D &data[payload_length]; struct device *dev =3D &sp->serdev->dev; u8 crc_calculated[RAVE_SP_CHECKSUM_SIZE]; + const u8 *crc_reported; + size_t payload_length; =20 if (unlikely(checksum_length > sizeof(crc_calculated))) { dev_warn(dev, "Checksum too long, dropping\n"); @@ -457,6 +478,9 @@ static void rave_sp_receive_frame(struct rave_sp *sp, return; } =20 + payload_length =3D length - checksum_length; + crc_reported =3D &data[payload_length]; + sp->variant->checksum->subroutine(data, payload_length, crc_calculated); =20 @@ -465,10 +489,10 @@ static void rave_sp_receive_frame(struct rave_sp *sp, return; } =20 - if (rave_sp_id_is_event(data[0])) - rave_sp_receive_event(sp, data, length); + if (rave_sp_id_is_event(data[RAVE_SP_FRAME_CODE_OFFSET])) + rave_sp_receive_event(sp, data, payload_length); else - rave_sp_receive_reply(sp, data, length); + rave_sp_receive_reply(sp, data, payload_length); } =20 static size_t rave_sp_receive_buf(struct serdev_device *serdev,