[PATCH] net: fbnic: validate mailbox TLV extents
From: Pengpeng Hou
Date: Sun Aug 30 2026 - 10:27:22 EST
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.
Fixes: da3cde08209e ("eth: fbnic: Add FW communication mechanism")
Signed-off-by: Pengpeng Hou <pengpeng@xxxxxxxxxxx>
---
drivers/net/ethernet/meta/fbnic/fbnic_fw.c | 9 ++++++---
drivers/net/ethernet/meta/fbnic/fbnic_tlv.c | 15 ++++++++++-----
2 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.c b/drivers/net/ethernet/meta/fbnic/fbnic_fw.c
index 283d25fae79e7..ff1674eff7ad5 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 c55d4f76a5fc0..639f90664d982 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c
@@ -427,9 +427,12 @@ int fbnic_tlv_attr_parse_array(struct fbnic_tlv_msg *attr, int len,
/* Work through list of attributes, parsing them as necessary */
while (len > 0) {
u16 attr_id = attr->hdr.type;
- u16 attr_len;
+ u16 attr_len = FBNIC_TLV_MSG_SIZE(le16_to_cpu(attr->hdr.len));
int err;
+ if (!attr_len || attr_len > len)
+ return -EINVAL;
+
if (tlv_attr_id != attr_id)
return -EINVAL;
@@ -443,7 +446,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 +478,15 @@ 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;
+ u16 attr_len = FBNIC_TLV_MSG_SIZE(le16_to_cpu(attr->hdr.len));
+ int err;
+
+ 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 +499,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;
}
base-commit: 08dbfad3f5040f5bdb6c529da20d6d4e81fefd72
--
2.50.1