Skip to content

Commit a5a8fc0

Browse files
hvenevgregkh
authored andcommitted
be2net: Fix buffer overflow in be_get_module_eeprom
[ Upstream commit d7241f679a59cfe27f92cb5c6272cb429fb1f7ec ] be_cmd_read_port_transceiver_data assumes that it is given a buffer that is at least PAGE_DATA_LEN long, or twice that if the module supports SFF 8472. However, this is not always the case. Fix this by passing the desired offset and length to be_cmd_read_port_transceiver_data so that we only copy the bytes once. Fixes: e36edd9 ("be2net: add ethtool "-m" option support") Signed-off-by: Hristo Venev <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Abeni <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 91e21df commit a5a8fc0

File tree

3 files changed

+25
-18
lines changed

3 files changed

+25
-18
lines changed

drivers/net/ethernet/emulex/benet/be_cmds.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,7 +2291,7 @@ int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num, u32 *state)
22912291

22922292
/* Uses sync mcc */
22932293
int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
2294-
u8 page_num, u8 *data)
2294+
u8 page_num, u32 off, u32 len, u8 *data)
22952295
{
22962296
struct be_dma_mem cmd;
22972297
struct be_mcc_wrb *wrb;
@@ -2325,10 +2325,10 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
23252325
req->port = cpu_to_le32(adapter->hba_port_num);
23262326
req->page_num = cpu_to_le32(page_num);
23272327
status = be_mcc_notify_wait(adapter);
2328-
if (!status) {
2328+
if (!status && len > 0) {
23292329
struct be_cmd_resp_port_type *resp = cmd.va;
23302330

2331-
memcpy(data, resp->page_data, PAGE_DATA_LEN);
2331+
memcpy(data, resp->page_data + off, len);
23322332
}
23332333
err:
23342334
mutex_unlock(&adapter->mcc_lock);
@@ -2419,7 +2419,7 @@ int be_cmd_query_cable_type(struct be_adapter *adapter)
24192419
int status;
24202420

24212421
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
2422-
page_data);
2422+
0, PAGE_DATA_LEN, page_data);
24232423
if (!status) {
24242424
switch (adapter->phy.interface_type) {
24252425
case PHY_TYPE_QSFP:
@@ -2444,7 +2444,7 @@ int be_cmd_query_sfp_info(struct be_adapter *adapter)
24442444
int status;
24452445

24462446
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
2447-
page_data);
2447+
0, PAGE_DATA_LEN, page_data);
24482448
if (!status) {
24492449
strlcpy(adapter->phy.vendor_name, page_data +
24502450
SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);

drivers/net/ethernet/emulex/benet/be_cmds.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2431,7 +2431,7 @@ int be_cmd_set_beacon_state(struct be_adapter *adapter, u8 port_num, u8 beacon,
24312431
int be_cmd_get_beacon_state(struct be_adapter *adapter, u8 port_num,
24322432
u32 *state);
24332433
int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
2434-
u8 page_num, u8 *data);
2434+
u8 page_num, u32 off, u32 len, u8 *data);
24352435
int be_cmd_query_cable_type(struct be_adapter *adapter);
24362436
int be_cmd_query_sfp_info(struct be_adapter *adapter);
24372437
int lancer_cmd_read_object(struct be_adapter *adapter, struct be_dma_mem *cmd,

drivers/net/ethernet/emulex/benet/be_ethtool.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1345,7 +1345,7 @@ static int be_get_module_info(struct net_device *netdev,
13451345
return -EOPNOTSUPP;
13461346

13471347
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
1348-
page_data);
1348+
0, PAGE_DATA_LEN, page_data);
13491349
if (!status) {
13501350
if (!page_data[SFP_PLUS_SFF_8472_COMP]) {
13511351
modinfo->type = ETH_MODULE_SFF_8079;
@@ -1363,25 +1363,32 @@ static int be_get_module_eeprom(struct net_device *netdev,
13631363
{
13641364
struct be_adapter *adapter = netdev_priv(netdev);
13651365
int status;
1366+
u32 begin, end;
13661367

13671368
if (!check_privilege(adapter, MAX_PRIVILEGES))
13681369
return -EOPNOTSUPP;
13691370

1370-
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
1371-
data);
1372-
if (status)
1373-
goto err;
1371+
begin = eeprom->offset;
1372+
end = eeprom->offset + eeprom->len;
1373+
1374+
if (begin < PAGE_DATA_LEN) {
1375+
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0, begin,
1376+
min_t(u32, end, PAGE_DATA_LEN) - begin,
1377+
data);
1378+
if (status)
1379+
goto err;
1380+
1381+
data += PAGE_DATA_LEN - begin;
1382+
begin = PAGE_DATA_LEN;
1383+
}
13741384

1375-
if (eeprom->offset + eeprom->len > PAGE_DATA_LEN) {
1376-
status = be_cmd_read_port_transceiver_data(adapter,
1377-
TR_PAGE_A2,
1378-
data +
1379-
PAGE_DATA_LEN);
1385+
if (end > PAGE_DATA_LEN) {
1386+
status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A2,
1387+
begin - PAGE_DATA_LEN,
1388+
end - begin, data);
13801389
if (status)
13811390
goto err;
13821391
}
1383-
if (eeprom->offset)
1384-
memcpy(data, data + eeprom->offset, eeprom->len);
13851392
err:
13861393
return be_cmd_status(status);
13871394
}

0 commit comments

Comments
 (0)