FAILED: patch "[PATCH] HID: mcp2221: clear rxbuf after I2C/SMBus transfer completes" failed to apply to 6.1-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x db2333f88729c8aae062cb171ed058725ff5c901
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090357-reference-varied-a710@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From db2333f88729c8aae062cb171ed058725ff5c901 Mon Sep 17 00:00:00 2001
From: Jiangshan Yi <[email protected]>
Date: Tue, 28 Jul 2026 21:14:41 +0800
Subject: [PATCH] HID: mcp2221: clear rxbuf after I2C/SMBus transfer completes
mcp_i2c_smbus_read() stores the caller-supplied buffer pointer in mcp->rxbuf for the duration of a transfer but never clears it when the transfer finishes or times out. Once the caller frees or reuses the buffer, mcp->rxbuf becomes a dangling pointer. A delayed or spurious MCP2221_I2C_GET_DATA report can then drive mcp2221_raw_event() to memcpy device data into the freed memory, causing a write use-after-free.
Route all return paths through a single exit point that clears mcp->rxbuf and mcp->rxbuf_size, so that the existing !mcp->rxbuf guard in the raw_event handler can reject any report arriving after the transfer has ended.
drivers/hid/hid-mcp2221.c +6 -2
@@ -343,7 +343,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, ret =mcp_send_data_req_status (mcp, mcp->txbuf,4 );if (ret) -return ret; + goto out; mcp->rxbuf_idx =0 ;
@@ -365,7 +365,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, }else {usleep_range (980 ,1000 );mcp_cancel_last_cmd (mcp); -return ret; + goto out; } }else { retries =0 ;
@@ -375,6 +375,10 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,usleep_range (980 ,1000 ); ret =mcp_chk_last_cmd_status_free_bus (mcp); +out: + mcp->rxbuf =NULL ; + mcp->rxbuf_size =0 ; +return ret; }
Sasha Levin
maintainerPATCH 1/2 HID: mcp2221: fix OOB write in mcp2221_raw_event()
From: Florian Pradines <[email protected]>
[ Upstream commit f097d246677b03db814c5862f368cea341b76a00 ]
mcp2221_raw_event() copies device-supplied data into mcp->rxbuf at offset rxbuf_idx without checking that the copy fits within the destination buffer. A device responding with up to 60 bytes to a small I2C/SMBus read can overflow the buffer.
Add a rxbuf_size field to struct mcp2221, set it alongside rxbuf in mcp_i2c_smbus_read(), and check rxbuf_idx + data[3] <= rxbuf_size before the memcpy.
Stable-dep-of: db2333f88729 ("HID: mcp2221: clear rxbuf after I2C/SMBus transfer completes")
--- drivers/hid/hid-mcp2221.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/hid/hid-mcp2221.c +7 -0
@@ -93,6 +93,7 @@ struct mcp2221 {u8 *rxbuf;u8 txbuf[64 ];int rxbuf_idx; +int rxbuf_size;int status;u8 cur_i2c_clk_div;struct gpio_chip *gc;
@@ -289,12 +290,14 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, mcp->txbuf[3 ] = (u8)(msg->addr <<1 ); total_len = msg->len; mcp->rxbuf = msg->buf; + mcp->rxbuf_size = msg->len; }else { mcp->txbuf[1 ] = smbus_len; mcp->txbuf[2 ] =0 ; mcp->txbuf[3 ] = (u8)(smbus_addr <<1 ); total_len = smbus_len; mcp->rxbuf = smbus_buf; + mcp->rxbuf_size = smbus_len; } ret =mcp_send_data_req_status (mcp, mcp->txbuf,4 );
@@ -797,6 +800,10 @@ static int mcp2221_raw_event(struct hid_device *hdev, mcp->status = -EINVAL ;break ; } +if (mcp->rxbuf_idx + data[3 ] > mcp->rxbuf_size) { + mcp->status = -EINVAL ; +break ; + } buf = mcp->rxbuf;memcpy (&buf[mcp->rxbuf_idx], &data[4 ], data[3 ]); mcp->rxbuf_idx = mcp->rxbuf_idx + data[3 ];
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 HID: mcp2221: clear rxbuf after I2C/SMBus transfer completes
From: Jiangshan Yi <[email protected]>
[ Upstream commit db2333f88729c8aae062cb171ed058725ff5c901 ]
mcp_i2c_smbus_read() stores the caller-supplied buffer pointer in mcp->rxbuf for the duration of a transfer but never clears it when the transfer finishes or times out. Once the caller frees or reuses the buffer, mcp->rxbuf becomes a dangling pointer. A delayed or spurious MCP2221_I2C_GET_DATA report can then drive mcp2221_raw_event() to memcpy device data into the freed memory, causing a write use-after-free.
Route all return paths through a single exit point that clears mcp->rxbuf and mcp->rxbuf_size, so that the existing !mcp->rxbuf guard in the raw_event handler can reject any report arriving after the transfer has ended.
--- drivers/hid/hid-mcp2221.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/hid/hid-mcp2221.c +6 -2
@@ -302,7 +302,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, ret =mcp_send_data_req_status (mcp, mcp->txbuf,4 );if (ret) -return ret; + goto out; mcp->rxbuf_idx =0 ;
@@ -324,7 +324,7 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp, }else {usleep_range (980 ,1000 );mcp_cancel_last_cmd (mcp); -return ret; + goto out; } }else { retries =0 ;
@@ -334,6 +334,10 @@ static int mcp_i2c_smbus_read(struct mcp2221 *mcp,usleep_range (980 ,1000 ); ret =mcp_chk_last_cmd_status_free_bus (mcp); +out: + mcp->rxbuf =NULL ; + mcp->rxbuf_size =0 ; +return ret; }
Signature · 1 line
2.53.0