mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-28 12:53:14 +01:00
ethtool: cmis: validate start_cmd_payload_size from module
The CMIS firmware update code reads start_cmd_payload_size from
the module's FW Management Features CDB reply and uses it directly
as the byte count for memcpy. The destination buffer is 112 bytes
(ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH - 8). So a malicious
module (or corrupted response) can cause a OOB write later on in
cmis_fw_update_start_download().
Let's error out. If modules that expect longer LPL writes actually
exist we should revisit.
struct cmis_cdb_start_fw_download_pl's definition has to move,
no change there.
Fixes: c4f78134d4 ("ethtool: cmis_fw_update: add a layer for supporting firmware update using CDB")
Reviewed-by: Maxime Chevallier <[email protected]>
Reviewed-by: Danielle Ratson <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
This commit is contained in:
1 parent
3e8c3d464c
commit
12c2496a71
1 file changed
+22
-14
@@ -44,6 +44,20 @@ enum cmis_cdb_fw_write_mechanism {
|
||||
CMIS_CDB_FW_WRITE_MECHANISM_BOTH = 0x11,
|
||||
};
|
||||
|
||||
/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
|
||||
* revision 5.2.
|
||||
* struct cmis_cdb_start_fw_download_pl is a structured layout of the
|
||||
* flat array, ethtool_cmis_cdb_request::payload.
|
||||
*/
|
||||
struct cmis_cdb_start_fw_download_pl {
|
||||
__struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
|
||||
__be32 image_size;
|
||||
__be32 resv1;
|
||||
);
|
||||
u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
|
||||
sizeof(struct cmis_cdb_start_fw_download_pl_h)];
|
||||
};
|
||||
|
||||
static int
|
||||
cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
|
||||
struct net_device *dev,
|
||||
@@ -86,6 +100,14 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
|
||||
*/
|
||||
cdb->read_write_len_ext = rpl->read_write_len_ext;
|
||||
fw_mng->start_cmd_payload_size = rpl->start_cmd_payload_size;
|
||||
if (fw_mng->start_cmd_payload_size >
|
||||
sizeof_field(struct cmis_cdb_start_fw_download_pl, vendor_data)) {
|
||||
ethnl_module_fw_flash_ntf_err(dev, ntf_params,
|
||||
"Start cmd payload size exceeds max LPL payload",
|
||||
NULL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
fw_mng->write_mechanism =
|
||||
rpl->write_mechanism == CMIS_CDB_FW_WRITE_MECHANISM_LPL ?
|
||||
CMIS_CDB_FW_WRITE_MECHANISM_LPL :
|
||||
@@ -97,20 +119,6 @@ cmis_fw_update_fw_mng_features_get(struct ethtool_cmis_cdb *cdb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* See section 9.7.2 "CMD 0101h: Start Firmware Download" in CMIS standard
|
||||
* revision 5.2.
|
||||
* struct cmis_cdb_start_fw_download_pl is a structured layout of the
|
||||
* flat array, ethtool_cmis_cdb_request::payload.
|
||||
*/
|
||||
struct cmis_cdb_start_fw_download_pl {
|
||||
__struct_group(cmis_cdb_start_fw_download_pl_h, head, /* no attrs */,
|
||||
__be32 image_size;
|
||||
__be32 resv1;
|
||||
);
|
||||
u8 vendor_data[ETHTOOL_CMIS_CDB_LPL_MAX_PL_LENGTH -
|
||||
sizeof(struct cmis_cdb_start_fw_download_pl_h)];
|
||||
};
|
||||
|
||||
static int
|
||||
cmis_fw_update_start_download(struct ethtool_cmis_cdb *cdb,
|
||||
struct ethtool_cmis_fw_update_params *fw_update,
|
||||
|
||||
Reference in new issue
Block a user