Commit c700f4e6 authored by Emil Tantilov's avatar Emil Tantilov Committed by Jeff Kirsher

ixgbe: Bounds checking for set_rar, clear_rar, set_vmdq, clear_vmdq

This change makes it so that out of bounds requests to these calls will
now return IXGBE_ERR_INVALID_ARGUMENT instead of returning 0.
Signed-off-by: default avatarEmil Tantilov <emil.s.tantilov@intel.com>
Tested-by: default avatarStephen Ko <stephen.s.ko@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 26d6899b
...@@ -858,6 +858,13 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) ...@@ -858,6 +858,13 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
{ {
u32 rar_high; u32 rar_high;
u32 rar_entries = hw->mac.num_rar_entries;
/* Make sure we are using a valid rar index range */
if (rar >= rar_entries) {
hw_dbg(hw, "RAR index %d is out of range.\n", rar);
return IXGBE_ERR_INVALID_ARGUMENT;
}
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
rar_high &= ~IXGBE_RAH_VIND_MASK; rar_high &= ~IXGBE_RAH_VIND_MASK;
...@@ -877,14 +884,17 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq) ...@@ -877,14 +884,17 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
u32 rar_high; u32 rar_high;
u32 rar_entries = hw->mac.num_rar_entries; u32 rar_entries = hw->mac.num_rar_entries;
if (rar < rar_entries) {
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar)); /* Make sure we are using a valid rar index range */
if (rar_high & IXGBE_RAH_VIND_MASK) { if (rar >= rar_entries) {
rar_high &= ~IXGBE_RAH_VIND_MASK;
IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
}
} else {
hw_dbg(hw, "RAR index %d is out of range.\n", rar); hw_dbg(hw, "RAR index %d is out of range.\n", rar);
return IXGBE_ERR_INVALID_ARGUMENT;
}
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
if (rar_high & IXGBE_RAH_VIND_MASK) {
rar_high &= ~IXGBE_RAH_VIND_MASK;
IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
} }
return 0; return 0;
......
...@@ -1239,37 +1239,37 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, ...@@ -1239,37 +1239,37 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq,
u32 rar_low, rar_high; u32 rar_low, rar_high;
u32 rar_entries = hw->mac.num_rar_entries; u32 rar_entries = hw->mac.num_rar_entries;
/* Make sure we are using a valid rar index range */
if (index >= rar_entries) {
hw_dbg(hw, "RAR index %d is out of range.\n", index);
return IXGBE_ERR_INVALID_ARGUMENT;
}
/* setup VMDq pool selection before this RAR gets enabled */ /* setup VMDq pool selection before this RAR gets enabled */
hw->mac.ops.set_vmdq(hw, index, vmdq); hw->mac.ops.set_vmdq(hw, index, vmdq);
/* Make sure we are using a valid rar index range */ /*
if (index < rar_entries) { * HW expects these in little endian so we reverse the byte
/* * order from network order (big endian) to little endian
* HW expects these in little endian so we reverse the byte */
* order from network order (big endian) to little endian rar_low = ((u32)addr[0] |
*/ ((u32)addr[1] << 8) |
rar_low = ((u32)addr[0] | ((u32)addr[2] << 16) |
((u32)addr[1] << 8) | ((u32)addr[3] << 24));
((u32)addr[2] << 16) | /*
((u32)addr[3] << 24)); * Some parts put the VMDq setting in the extra RAH bits,
/* * so save everything except the lower 16 bits that hold part
* Some parts put the VMDq setting in the extra RAH bits, * of the address and the address valid bit.
* so save everything except the lower 16 bits that hold part */
* of the address and the address valid bit. rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
*/ rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
if (enable_addr != 0) if (enable_addr != 0)
rar_high |= IXGBE_RAH_AV; rar_high |= IXGBE_RAH_AV;
IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
} else {
hw_dbg(hw, "RAR index %d is out of range.\n", index);
return IXGBE_ERR_RAR_INDEX;
}
return 0; return 0;
} }
...@@ -1287,22 +1287,22 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) ...@@ -1287,22 +1287,22 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index)
u32 rar_entries = hw->mac.num_rar_entries; u32 rar_entries = hw->mac.num_rar_entries;
/* Make sure we are using a valid rar index range */ /* Make sure we are using a valid rar index range */
if (index < rar_entries) { if (index >= rar_entries) {
/*
* Some parts put the VMDq setting in the extra RAH bits,
* so save everything except the lower 16 bits that hold part
* of the address and the address valid bit.
*/
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
} else {
hw_dbg(hw, "RAR index %d is out of range.\n", index); hw_dbg(hw, "RAR index %d is out of range.\n", index);
return IXGBE_ERR_RAR_INDEX; return IXGBE_ERR_INVALID_ARGUMENT;
} }
/*
* Some parts put the VMDq setting in the extra RAH bits,
* so save everything except the lower 16 bits that hold part
* of the address and the address valid bit.
*/
rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
/* clear VMDq pool/queue selection for this RAR */ /* clear VMDq pool/queue selection for this RAR */
hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
...@@ -2468,37 +2468,38 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) ...@@ -2468,37 +2468,38 @@ s32 ixgbe_clear_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
u32 mpsar_lo, mpsar_hi; u32 mpsar_lo, mpsar_hi;
u32 rar_entries = hw->mac.num_rar_entries; u32 rar_entries = hw->mac.num_rar_entries;
if (rar < rar_entries) { /* Make sure we are using a valid rar index range */
mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar)); if (rar >= rar_entries) {
mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar)); hw_dbg(hw, "RAR index %d is out of range.\n", rar);
return IXGBE_ERR_INVALID_ARGUMENT;
}
if (!mpsar_lo && !mpsar_hi) mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
goto done; mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
if (vmdq == IXGBE_CLEAR_VMDQ_ALL) { if (!mpsar_lo && !mpsar_hi)
if (mpsar_lo) { goto done;
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
mpsar_lo = 0;
}
if (mpsar_hi) {
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
mpsar_hi = 0;
}
} else if (vmdq < 32) {
mpsar_lo &= ~(1 << vmdq);
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
} else {
mpsar_hi &= ~(1 << (vmdq - 32));
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
}
/* was that the last pool using this rar? */ if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0) if (mpsar_lo) {
hw->mac.ops.clear_rar(hw, rar); IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
mpsar_lo = 0;
}
if (mpsar_hi) {
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
mpsar_hi = 0;
}
} else if (vmdq < 32) {
mpsar_lo &= ~(1 << vmdq);
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
} else { } else {
hw_dbg(hw, "RAR index %d is out of range.\n", rar); mpsar_hi &= ~(1 << (vmdq - 32));
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
} }
/* was that the last pool using this rar? */
if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
hw->mac.ops.clear_rar(hw, rar);
done: done:
return 0; return 0;
} }
...@@ -2514,18 +2515,20 @@ s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq) ...@@ -2514,18 +2515,20 @@ s32 ixgbe_set_vmdq_generic(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
u32 mpsar; u32 mpsar;
u32 rar_entries = hw->mac.num_rar_entries; u32 rar_entries = hw->mac.num_rar_entries;
if (rar < rar_entries) { /* Make sure we are using a valid rar index range */
if (vmdq < 32) { if (rar >= rar_entries) {
mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
mpsar |= 1 << vmdq;
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
} else {
mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
mpsar |= 1 << (vmdq - 32);
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
}
} else {
hw_dbg(hw, "RAR index %d is out of range.\n", rar); hw_dbg(hw, "RAR index %d is out of range.\n", rar);
return IXGBE_ERR_INVALID_ARGUMENT;
}
if (vmdq < 32) {
mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
mpsar |= 1 << vmdq;
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
} else {
mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
mpsar |= 1 << (vmdq - 32);
IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
} }
return 0; return 0;
} }
......
...@@ -2689,7 +2689,6 @@ struct ixgbe_info { ...@@ -2689,7 +2689,6 @@ struct ixgbe_info {
#define IXGBE_ERR_EEPROM_VERSION -24 #define IXGBE_ERR_EEPROM_VERSION -24
#define IXGBE_ERR_NO_SPACE -25 #define IXGBE_ERR_NO_SPACE -25
#define IXGBE_ERR_OVERTEMP -26 #define IXGBE_ERR_OVERTEMP -26
#define IXGBE_ERR_RAR_INDEX -27
#define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30 #define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE -30
#define IXGBE_ERR_PBA_SECTION -31 #define IXGBE_ERR_PBA_SECTION -31
#define IXGBE_ERR_INVALID_ARGUMENT -32 #define IXGBE_ERR_INVALID_ARGUMENT -32
......
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