From c29b37ed7a4d9856ed758a82282456d69cee2ed1 Mon Sep 17 00:00:00 2001 From: Pengpeng Hou Date: Sun, 30 Aug 2026 22:24:58 +0800 Subject: [PATCH] net: fbnic: validate mailbox TLV extents The mailbox path warns when a message claims more bytes than the descriptor but still parses it. The attribute walkers also validate a child TLV before proving that its declared span fits in the parent remainder. Reject invalid mailbox message extents and bound each child attribute before type-specific validation. Cc: stable+noautosel@kernel.org # assumes malicious PCIe device Signed-off-by: Pengpeng Hou Link: https://patch.msgid.link/20260830142516.38145-1-pengpeng@iscas.ac.cn Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 9 ++++++--- drivers/net/ethernet/meta/fbnic/fbnic_tlv.c | 13 ++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c index 283d25fae79e..ff1674eff7ad 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c @@ -1677,16 +1677,19 @@ static void fbnic_mbx_process_rx_msgs(struct fbnic_dev *fbd) if (!length) goto next_page; - /* Report descriptors with length greater than page size */ - if (length > PAGE_SIZE) { + /* Report descriptors with invalid message extents. */ + if (length < sizeof(msg->hdr) || length > PAGE_SIZE) { dev_warn(fbd->dev, "Invalid mailbox descriptor length: %lld\n", length); goto next_page; } - if (le16_to_cpu(msg->hdr.len) * sizeof(u32) > length) + if (!le16_to_cpu(msg->hdr.len) || + le16_to_cpu(msg->hdr.len) * sizeof(u32) > length) { dev_warn(fbd->dev, "Mailbox message length mismatch\n"); + goto next_page; + } /* If parsing fails dump contents of message to dmesg */ err = fbnic_tlv_msg_parse(fbd, msg, fbnic_fw_tlv_parser); diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c index c55d4f76a5fc..3ef3935c0419 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c @@ -430,6 +430,10 @@ int fbnic_tlv_attr_parse_array(struct fbnic_tlv_msg *attr, int len, u16 attr_len; int err; + attr_len = FBNIC_TLV_MSG_SIZE(le16_to_cpu(attr->hdr.len)); + if (!attr_len || attr_len > len) + return -EINVAL; + if (tlv_attr_id != attr_id) return -EINVAL; @@ -443,7 +447,6 @@ int fbnic_tlv_attr_parse_array(struct fbnic_tlv_msg *attr, int len, results[i++] = attr; - attr_len = FBNIC_TLV_MSG_SIZE(le16_to_cpu(attr->hdr.len)); len -= attr_len; attr += attr_len; } @@ -476,11 +479,16 @@ int fbnic_tlv_attr_parse(struct fbnic_tlv_msg *attr, int len, /* Work through list of attributes, parsing them as necessary */ while (len > 0) { - int err = fbnic_tlv_attr_validate(attr, tlv_index); u16 attr_id = attr->hdr.type; u16 attr_len; + int err; + + attr_len = FBNIC_TLV_MSG_SIZE(le16_to_cpu(attr->hdr.len)); + if (!attr_len || attr_len > len) + return -EINVAL; /* Stop parsing on full error */ + err = fbnic_tlv_attr_validate(attr, tlv_index); if (err < 0) return err; @@ -493,7 +501,6 @@ int fbnic_tlv_attr_parse(struct fbnic_tlv_msg *attr, int len, results[attr_id] = attr; } - attr_len = FBNIC_TLV_MSG_SIZE(le16_to_cpu(attr->hdr.len)); len -= attr_len; attr += attr_len; }