From: Paul Greenwalt <[email protected]> Prevent out-of-bounds MMIO accesses triggered through user-controlled register offsets. IXGBE_HFDR (0x15FE8) is the highest valid MMIO register in the ixgbe register map; any offset beyond it would address unmapped memory.
Add a defense-in-depth check at two levels: 1. ixgbe_read_reg() -- the noinline register read accessor. A WARN_ON_ONCE() guard here catches any future code path (including ioctl extensions) that might inadvertently pass an out-of-range offset without relying on higher layers to catch it first. ixgbe_write_reg() is a static inline called from the TX/RX hot path; adding WARN_ON_ONCE there would inline the check at every call site, so only the read path gets this guard. 2. ixgbe_dbg_reg_ops_write() -- the debugfs 'reg_ops' interface is the only current path where a raw, user-supplied offset enters the driver. Gating it before invoking the register accessors provides a clean, user-visible failure (silent ignore with no kernel splat) for deliberately malformed debugfs writes. Add a reg <= IXGBE_HFDR guard to both the read and write paths in ixgbe_dbg_reg_ops_write(), and a WARN_ON_ONCE + early-return guard to ixgbe_read_reg(). Signed-off-by: Paul Greenwalt <[email protected]> Signed-off-by: Aleksandr Loktionov <[email protected]> --- drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c | 6 ++++-- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c index 5b1cf49d..a6a19c0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c @@ -86,7 +86,8 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp, u32 reg, value; int cnt; cnt = sscanf(&ixgbe_dbg_reg_ops_buf[5], "%x %x", ®, &value); - if (cnt == 2) { + /* check format and bounds check register access */ + if (cnt == 2 && reg <= IXGBE_HFDR) { IXGBE_WRITE_REG(&adapter->hw, reg, value); value = IXGBE_READ_REG(&adapter->hw, reg); e_dev_info("write: 0x%08x = 0x%08x\n", reg, value); @@ -97,7 +98,8 @@ static ssize_t ixgbe_dbg_reg_ops_write(struct file *filp, u32 reg, value; int cnt; cnt = sscanf(&ixgbe_dbg_reg_ops_buf[4], "%x", ®); - if (cnt == 1) { + /* check format and bounds check register access */ + if (cnt == 1 && reg <= IXGBE_HFDR) { value = IXGBE_READ_REG(&adapter->hw, reg); e_dev_info("read 0x%08x = 0x%08x\n", reg, value); } else { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 210c7b9..4a1f3c2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -354,4 +354,6 @@ u32 ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg) if (ixgbe_removed(reg_addr)) return IXGBE_FAILED_READ_REG; + if (WARN_ON_ONCE(reg > IXGBE_HFDR)) + return IXGBE_FAILED_READ_REG; if (unlikely(hw->phy.nw_mng_if_sel & IXGBE_NW_MNG_IF_SEL_SGMII_ENABLE)) { -- 2.52.0
