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 <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260830142516.38145-1-pengpeng@iscas.ac.cn
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Pengpeng Hou 2026-08-30 22:24:58 +08:00 committed by Jakub Kicinski
parent 0a1071aa32
commit c29b37ed7a
2 changed files with 16 additions and 6 deletions

View File

@ -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);

View File

@ -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;
}