The number of memory windows used by the peer is read from a
scratchpad register written by the peer, and is then used as the loop
bound to fill peer_mw_base[], which is allocated with mw_cnt entries.
A peer advertising more windows (bug, version mismatch, or a stale
scratchpad) makes the driver write past the end of this array.
On Intel, the 32-bit register value was also silently truncated into
the 8-bit peer_used_mws field.
Reject a peer configuration using more windows than the local device
has.
Fixes: c39d1e082a4b ("raw/ntb: setup queues")
Fixes: d6dc5a7f8b06 ("raw/ntb: support AMD NTB")
Cc: [email protected]
Signed-off-by: Raghavendra Ningoji <[email protected]>
---
drivers/raw/ntb/ntb_hw_amd.c | 10 ++++++++--
drivers/raw/ntb/ntb_hw_intel.c | 7 ++++++-
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/drivers/raw/ntb/ntb_hw_amd.c b/drivers/raw/ntb/ntb_hw_amd.c
index ab78675218..dba5b03671 100644
--- a/drivers/raw/ntb/ntb_hw_amd.c
+++ b/drivers/raw/ntb/ntb_hw_amd.c
@@ -502,7 +502,7 @@ static int
amd_ntb_read_peer_config(const struct rte_rawdev *dev)
{
struct ntb_hw *ntb = dev->dev_private;
- uint32_t info, peer_qps, peer_qsz, lo, hi;
+ uint32_t info, peer_qps, peer_qsz, peer_used_mws, lo, hi;
int i;
info = amd_ntb_spad_read(dev, AMD_SPAD_CNT_INFO, 0);
@@ -520,7 +520,13 @@ amd_ntb_read_peer_config(const struct rte_rawdev *dev)
return -EINVAL;
}
- ntb->peer_used_mws = (info >> 16) & 0xff;
+ peer_used_mws = (info >> 16) & 0xff;
+ if (peer_used_mws > ntb->mw_cnt) {
+ NTB_LOG(ERR, "Peer used mws %u > mw cnt %u.", peer_used_mws,
ntb->mw_cnt);
+ return -EINVAL;
+ }
+ ntb->peer_used_mws = peer_used_mws;
+
for (i = 0; i < ntb->peer_used_mws; i++) {
lo = amd_ntb_spad_read(dev, AMD_SPAD_MW0_BA_L + 2 * i, 0);
hi = amd_ntb_spad_read(dev, AMD_SPAD_MW0_BA_H + 2 * i, 0);
diff --git a/drivers/raw/ntb/ntb_hw_intel.c b/drivers/raw/ntb/ntb_hw_intel.c
index 1b784055ca..78fce9ffac 100644
--- a/drivers/raw/ntb/ntb_hw_intel.c
+++ b/drivers/raw/ntb/ntb_hw_intel.c
@@ -724,7 +724,12 @@ intel_ntb_read_peer_config(const struct rte_rawdev *dev)
return -EINVAL;
}
- hw->peer_used_mws = intel_ntb_spad_read(dev, SPAD_USED_MWS, 0);
+ peer_val = intel_ntb_spad_read(dev, SPAD_USED_MWS, 0);
+ if (peer_val > hw->mw_cnt) {
+ NTB_LOG(ERR, "Peer used mws %u > mw cnt %u.", peer_val,
hw->mw_cnt);
+ return -EINVAL;
+ }
+ hw->peer_used_mws = peer_val;
for (i = 0; i < hw->peer_used_mws; i++) {
peer_base_h = intel_ntb_spad_read(dev, SPAD_MW0_BA_H + 2 * i,
0);
--
2.34.1