Commit eb656d45 authored by Bruce Allan's avatar Bruce Allan Committed by David S. Miller

e1000e: guard against buffer overflow in cable length tables

Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent caaddaf8
...@@ -99,6 +99,8 @@ ...@@ -99,6 +99,8 @@
*/ */
static const u16 e1000_gg82563_cable_length_table[] = static const u16 e1000_gg82563_cable_length_table[] =
{ 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF }; { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
#define GG82563_CABLE_LENGTH_TABLE_SIZE \
ARRAY_SIZE(e1000_gg82563_cable_length_table)
static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw); static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask);
...@@ -694,20 +696,27 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) ...@@ -694,20 +696,27 @@ static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw) static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
{ {
struct e1000_phy_info *phy = &hw->phy; struct e1000_phy_info *phy = &hw->phy;
s32 ret_val; s32 ret_val = 0;
u16 phy_data, index; u16 phy_data, index;
ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
if (ret_val) if (ret_val)
return ret_val; goto out;
index = phy_data & GG82563_DSPD_CABLE_LENGTH; index = phy_data & GG82563_DSPD_CABLE_LENGTH;
if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) {
ret_val = -E1000_ERR_PHY;
goto out;
}
phy->min_cable_length = e1000_gg82563_cable_length_table[index]; phy->min_cable_length = e1000_gg82563_cable_length_table[index];
phy->max_cable_length = e1000_gg82563_cable_length_table[index+5]; phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
return 0; out:
return ret_val;
} }
/** /**
......
...@@ -44,6 +44,8 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, ...@@ -44,6 +44,8 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
/* Cable length tables */ /* Cable length tables */
static const u16 e1000_m88_cable_length_table[] = static const u16 e1000_m88_cable_length_table[] =
{ 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED }; { 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
#define M88E1000_CABLE_LENGTH_TABLE_SIZE \
ARRAY_SIZE(e1000_m88_cable_length_table)
static const u16 e1000_igp_2_cable_length_table[] = static const u16 e1000_igp_2_cable_length_table[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3, { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
...@@ -1717,15 +1719,21 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw) ...@@ -1717,15 +1719,21 @@ s32 e1000e_get_cable_length_m88(struct e1000_hw *hw)
ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
if (ret_val) if (ret_val)
return ret_val; goto out;
index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
M88E1000_PSSR_CABLE_LENGTH_SHIFT; M88E1000_PSSR_CABLE_LENGTH_SHIFT;
if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) {
ret_val = -E1000_ERR_PHY;
goto out;
}
phy->min_cable_length = e1000_m88_cable_length_table[index]; phy->min_cable_length = e1000_m88_cable_length_table[index];
phy->max_cable_length = e1000_m88_cable_length_table[index+1]; phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
out:
return ret_val; return ret_val;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment