From 679cfd5353da2165dbf5b89769bbd5b69209bc5b Mon Sep 17 00:00:00 2001
From: Junxian Huang <huangjunxian6@hisilicon.com>
Date: Tue, 24 Oct 2023 15:12:41 +0800
Subject: hikptool/roce: Fix missing check of reg num responsed from FW

If the reg num responsed from a new-version FW exceeds the array
length in the old-version hikptool, an out-of-bounds access error
will occur. So add a check to ensure the reg num is not greater
than tha array length.

Fixes: 392c269be165 ("support querying RoCE module information")
Fixes: 87f8605c32d3 ("hikptool/roce: Add ext query for roce_qmm cmd")
Signed-off-by: Junxian Huang <huangjunxian6@hisilicon.com>
---
 net/roce/roce_caep/hikp_roce_caep.c   |  7 +++++++
 net/roce/roce_pkt/hikp_roce_pkt.c     |  7 +++++++
 net/roce/roce_qmm/hikp_roce_qmm.c     |  7 +++++++
 net/roce/roce_timer/hikp_roce_timer.c | 12 ++++++++++++
 net/roce/roce_tsp/hikp_roce_tsp.c     |  6 ++++++
 5 files changed, 39 insertions(+)

diff --git a/net/roce/roce_caep/hikp_roce_caep.c b/net/roce/roce_caep/hikp_roce_caep.c
index 6c92ea1..126551a 100644
--- a/net/roce/roce_caep/hikp_roce_caep.c
+++ b/net/roce/roce_caep/hikp_roce_caep.c
@@ -85,7 +85,14 @@ static void hikp_roce_caep_execute_origin(struct major_cmd_ctrl *self)
 		printf("hikptool roce_caep get data failed.\n");
 		goto exec_error;
 	}
+
 	roce_caep_res = (struct roce_caep_res_param *)cmd_ret->rsp_data;
+	if (roce_caep_res->total_block_num > ROCE_HIKP_CAEP_REG_NUM) {
+		printf("version might not match, adjust the reg num to %d.\n",
+		       ROCE_HIKP_CAEP_REG_NUM);
+		roce_caep_res->total_block_num = ROCE_HIKP_CAEP_REG_NUM;
+	}
+
 	hikp_roce_caep_print(roce_caep_res->total_block_num,
 			     roce_caep_res->reg_data.offset,
 			     roce_caep_res->reg_data.data);
diff --git a/net/roce/roce_pkt/hikp_roce_pkt.c b/net/roce/roce_pkt/hikp_roce_pkt.c
index d3bf885..e710e08 100644
--- a/net/roce/roce_pkt/hikp_roce_pkt.c
+++ b/net/roce/roce_pkt/hikp_roce_pkt.c
@@ -87,7 +87,14 @@ static void hikp_roce_pkt_execute(struct major_cmd_ctrl *self)
 		self->err_no = ret;
 		return;
 	}
+
 	roce_pkt_res = (struct roce_pkt_res_param *)cmd_ret->rsp_data;
+	if (roce_pkt_res->total_block_num > ROCE_HIKP_PKT_REG_NUM) {
+		printf("version might not match, adjust the reg num to %d.\n",
+		       ROCE_HIKP_PKT_REG_NUM);
+		roce_pkt_res->total_block_num = ROCE_HIKP_PKT_REG_NUM;
+	}
+
 	hikp_roce_pkt_print(roce_pkt_res->total_block_num,
 			    roce_pkt_res->reg_data.offset, roce_pkt_res->reg_data.data);
 
diff --git a/net/roce/roce_qmm/hikp_roce_qmm.c b/net/roce/roce_qmm/hikp_roce_qmm.c
index b020c6a..d127264 100644
--- a/net/roce/roce_qmm/hikp_roce_qmm.c
+++ b/net/roce/roce_qmm/hikp_roce_qmm.c
@@ -108,7 +108,14 @@ static void hikp_roce_qmm_execute_origin(struct major_cmd_ctrl *self)
 		printf("hikptool roce_qmm get data failed.\n");
 		goto exec_error;
 	}
+
 	roce_qmm_res = (struct roce_qmm_rsp_data *)cmd_ret->rsp_data;
+	if (roce_qmm_res->reg_num > ROCE_HIKP_QMM_REG_NUM) {
+		printf("version might not match, adjust the reg num to %d.\n",
+		       ROCE_HIKP_QMM_REG_NUM);
+		roce_qmm_res->reg_num = ROCE_HIKP_QMM_REG_NUM;
+	}
+
 	hikp_roce_qmm_print(roce_qmm_res);
 
 exec_error:
diff --git a/net/roce/roce_timer/hikp_roce_timer.c b/net/roce/roce_timer/hikp_roce_timer.c
index c4e979f..a78d383 100644
--- a/net/roce/roce_timer/hikp_roce_timer.c
+++ b/net/roce/roce_timer/hikp_roce_timer.c
@@ -76,6 +76,12 @@ static int hikp_roce_timer_show_qpc(struct major_cmd_ctrl *self)
 		goto out;
 
 	timer_rsp = (struct roce_timer_rsp_data *)(cmd_ret->rsp_data);
+	if (timer_rsp->reg_num > ROCE_HIKP_TIMER_REG_NUM) {
+		printf("version might not match, adjust the reg num to %d.\n",
+		       ROCE_HIKP_TIMER_REG_NUM);
+		timer_rsp->reg_num = ROCE_HIKP_TIMER_REG_NUM;
+	}
+
 	printf("**************QPC TIMER INFO*************\n");
 	hikp_roce_timer_print(timer_rsp);
 out:
@@ -104,6 +110,12 @@ static int hikp_roce_timer_show_cqc(struct major_cmd_ctrl *self)
 		goto out;
 
 	timer_rsp = (struct roce_timer_rsp_data *)(cmd_ret->rsp_data);
+	if (timer_rsp->reg_num > ROCE_HIKP_TIMER_REG_NUM) {
+		printf("version might not match, adjust the reg num to %d.\n",
+		       ROCE_HIKP_TIMER_REG_NUM);
+		timer_rsp->reg_num = ROCE_HIKP_TIMER_REG_NUM;
+	}
+
 	printf("**************CQC TIMER INFO*************\n");
 	hikp_roce_timer_print(timer_rsp);
 out:
diff --git a/net/roce/roce_tsp/hikp_roce_tsp.c b/net/roce/roce_tsp/hikp_roce_tsp.c
index a036fae..5bb2649 100644
--- a/net/roce/roce_tsp/hikp_roce_tsp.c
+++ b/net/roce/roce_tsp/hikp_roce_tsp.c
@@ -181,6 +181,12 @@ static void hikp_roce_tsp_execute(struct major_cmd_ctrl *self)
 	}
 
 	roce_tsp_res = (struct roce_tsp_res_param *)cmd_ret->rsp_data;
+	if (roce_tsp_res->total_block_num > ROCE_HIKP_TSP_REG_NUM) {
+		printf("version might not match, adjust the reg num to %d.\n",
+		       ROCE_HIKP_TSP_REG_NUM);
+		roce_tsp_res->total_block_num = ROCE_HIKP_TSP_REG_NUM;
+	}
+
 	hikp_roce_tsp_print(roce_tsp_res->total_block_num,
 			    roce_tsp_res->reg_data.offset, roce_tsp_res->reg_data.data);
 
--
2.30.0