From: Guanglei Zhu <zhugl3@xiaopeng.com>
To: chandrashekar.devegowda@intel.com, loic.poulain@oss.qualcomm.com,
ryazanov.s.a@gmail.com
Cc: haijun.liu@mediatek.com, ricardo.martinez@linux.intel.com,
johannes@sipsolutions.net, andrew+netdev@lunn.ch,
davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org, stable@vger.kernel.org,
guozh23@xiaopeng.com
Subject: [PATCH v2] net: wwan: t7xx: validate the HS2 message data length
Date: Tue, 29 Sep 2026 10:39:14 +0800 [thread overview]
Message-ID: <20260929023914.247374-1-zhugl3@xiaopeng.com> (raw)
In-Reply-To: <20260909054401.718959-1-zhugl3@xiaopeng.com>
control_msg_handler() passes the modem-supplied data_length field of a
CTL_ID_HS2_MSG message straight to t7xx_fsm_append_event(), which
memcpy()s that many bytes out of the skb. Nothing compares the field
with the actual length of the message, so a modem reporting a larger
data_length makes the driver read past the end of the skb and store
kernel heap memory in the FSM event.
The message is not even checked against the control header itself:
for a message shorter than sizeof(struct ctrl_msg_header) the
skb_pull() is a no-op and ctrl_msg_h->data_length is read past the
skb tail. And on the consumer side, t7xx_prepare_device_rt_data()
reads a full struct feature_query out of the event without looking at
its length, so a short data_length makes it read past the end of the
event allocation and echo the out-of-bounds bytes back to the modem
in the HS3 reply.
Reject the message when it is shorter than the control header or when
data_length does not fit into the skb, and make
t7xx_prepare_device_rt_data() bail out when the payload is shorter
than struct feature_query.
Fixes: da45d2566a1d ("net: wwan: t7xx: Add control port")
Cc: stable@vger.kernel.org
Signed-off-by: Guanglei Zhu <zhugl3@xiaopeng.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
---
Changes in v2, addressing the sashiko AI review:
- reject messages shorter than the control header, so
ctrl_msg_h->data_length is not read past the skb tail
- make t7xx_prepare_device_rt_data() length-aware: a payload shorter
than struct feature_query is rejected instead of being read past
the end of the event allocation and echoed back in the HS3 reply
- flatten the HS2 arm nesting while at it
The data_length upper-bound check was verified in a QEMU guest with a
fault injector feeding the driver's control port thread a handshake
message whose data_length exceeds the skb: the unpatched driver trips
KASAN on a read of 8192 bytes past a 500-byte payload, and the extra
bytes land in the FSM event. With this check the message is
rejected, and well-formed handshakes are unaffected.
drivers/net/wwan/t7xx/t7xx_modem_ops.c | 10 ++++++--
drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c | 27 ++++++++++++++++++----
2 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wwan/t7xx/t7xx_modem_ops.c b/drivers/net/wwan/t7xx/t7xx_modem_ops.c
index adb29d3..de689aa 100644
--- a/drivers/net/wwan/t7xx/t7xx_modem_ops.c
+++ b/drivers/net/wwan/t7xx/t7xx_modem_ops.c
@@ -400,13 +400,18 @@ static void t7xx_prepare_host_rt_data_query(struct t7xx_sys_info *core)
}
static int t7xx_prepare_device_rt_data(struct t7xx_sys_info *core, struct device *dev,
- void *data)
+ void *data, int data_length)
{
struct feature_query *md_feature = data;
struct mtk_runtime_feature *rt_feature;
unsigned int i, rt_data_len = 0;
struct sk_buff *skb;
+ if (data_length < sizeof(*md_feature)) {
+ dev_err(dev, "Invalid runtime data length: %d\n", data_length);
+ return -EINVAL;
+ }
+
/* Parse MD runtime data query */
if (le32_to_cpu(md_feature->head_pattern) != MD_FEATURE_QUERY_ID ||
le32_to_cpu(md_feature->tail_pattern) != MD_FEATURE_QUERY_ID) {
@@ -563,7 +568,8 @@ static void t7xx_core_hk_handler(struct t7xx_modem *md, struct t7xx_sys_info *co
if (ctl->exp_flg)
goto err_free_event;
- ret = t7xx_prepare_device_rt_data(core_info, dev, event->data);
+ ret = t7xx_prepare_device_rt_data(core_info, dev, event->data,
+ event->length);
if (ret) {
dev_err(dev, "Device failure parsing runtime data: %d", ret);
goto err_free_event;
diff --git a/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c b/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c
index f869e4e..5ed07c4 100644
--- a/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c
+++ b/drivers/net/wwan/t7xx/t7xx_port_ctrl_msg.c
@@ -178,22 +178,39 @@ static int control_msg_handler(struct t7xx_port *port, struct sk_buff *skb)
ctrl_msg_h = (struct ctrl_msg_header *)skb->data;
switch (le32_to_cpu(ctrl_msg_h->ctrl_msg_id)) {
- case CTL_ID_HS2_MSG:
- skb_pull(skb, sizeof(*ctrl_msg_h));
+ case CTL_ID_HS2_MSG: {
+ u32 data_length;
+
+ if (skb->len < sizeof(*ctrl_msg_h)) {
+ dev_err(port->dev,
+ "Invalid HS2 message: need %zu, have %u\n",
+ sizeof(*ctrl_msg_h), skb->len);
+ ret = -EINVAL;
+ dev_kfree_skb_any(skb);
+ break;
+ }
- if (port_conf->rx_ch == PORT_CH_CONTROL_RX ||
- port_conf->rx_ch == PORT_CH_AP_CONTROL_RX) {
+ skb_pull(skb, sizeof(*ctrl_msg_h));
+ data_length = le32_to_cpu(ctrl_msg_h->data_length);
+
+ if (data_length > skb->len) {
+ dev_err(port->dev, "Invalid HS2 message length %u\n",
+ data_length);
+ ret = -EINVAL;
+ } else if (port_conf->rx_ch == PORT_CH_CONTROL_RX ||
+ port_conf->rx_ch == PORT_CH_AP_CONTROL_RX) {
int event = port_conf->rx_ch == PORT_CH_CONTROL_RX ?
FSM_EVENT_MD_HS2 : FSM_EVENT_AP_HS2;
ret = t7xx_fsm_append_event(ctl, event, skb->data,
- le32_to_cpu(ctrl_msg_h->data_length));
+ data_length);
if (ret)
dev_err(port->dev, "Failed to append Handshake 2 event");
}
dev_kfree_skb_any(skb);
break;
+ }
case CTL_ID_MD_EX:
case CTL_ID_MD_EX_ACK:
--
2.43.0
next prev parent reply other threads:[~2026-09-29 2:39 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-09 5:44 [PATCH] " Guanglei Zhu
2026-09-09 13:10 ` Loic Poulain
2026-09-10 5:46 ` netdev-bot+sashiko
2026-09-29 2:39 ` Guanglei Zhu [this message]
2026-09-29 2:44 ` [PATCH v2] " netdev-bot+sinfo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260929023914.247374-1-zhugl3@xiaopeng.com \
--to=zhugl3@xiaopeng.com \
--cc=andrew+netdev@lunn.ch \
--cc=chandrashekar.devegowda@intel.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=guozh23@xiaopeng.com \
--cc=haijun.liu@mediatek.com \
--cc=johannes@sipsolutions.net \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=loic.poulain@oss.qualcomm.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=ricardo.martinez@linux.intel.com \
--cc=ryazanov.s.a@gmail.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®