Malicious SFP module could respond with rpl_len longer than
what cmis_cdb_process_reply() expected, leading to OOB writes.
Malicious HW is a bit theoretical but some modules may just
be buggy and/or the reads may occasionally get corrupted,
so let's protect the kernel.
The existing check protects from short replies. We need to
protect from long ones, too. All callers that pass a non-zero
rpl_exp_len cast the reply payload to a fixed-layout struct
and read fields at fixed offsets, with no version negotiation
or short-reply handling:
- cmis_cdb_validate_password()
- cmis_cdb_module_features_get()
- cmis_fw_update_fw_mng_features_get()
so let's assume that responses longer than expected do not
have to be handled gracefully here. Add a warning message
to make the debug easier in case my understanding is wrong...
Note that page_data->length (argument of kmalloc) comes from
last arg to ethtool_cmis_page_init() which is rpl_exp_len.
Note2 that AIs also like to point out overflows in args->req.payload
itself (which is a fixed-size 120 B buffer, on the stack),
but callers should be reading structs defined by the standard,
so protecting from requests for more data than max seem like
defensive programming.
Fixes: a39c84d79625 ("ethtool: cmis_cdb: Add a layer for supporting CDB commands")
Reviewed-by: Danielle Ratson <danieller@nvidia.com>
Link: https://patch.msgid.link/20260522231312.1710836-7-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
}
rpl = (struct ethtool_cmis_cdb_rpl *)page_data->data;
- if ((args->rpl_exp_len > rpl->hdr.rpl_len + rpl_hdr_len) ||
- !rpl->hdr.rpl_chk_code) {
+ if (rpl->hdr.rpl_len != args->rpl_exp_len) {
+ netdev_warn(dev, "CDB reply length mismatch, expected %u got %u\n",
+ args->rpl_exp_len, rpl->hdr.rpl_len);
+ err = -EIO;
+ goto out;
+ }
+ if (!rpl->hdr.rpl_chk_code) {
err = -EIO;
goto out;
}