Skip to content

Commit c8c29ec

Browse files
Luo bindavem330
authored andcommitted
hinic: add check for mailbox msg from VF
PF should check whether the cmd from VF is supported and its content is right before passing it to hw. Signed-off-by: Luo bin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 088c5f0 commit c8c29ec

File tree

4 files changed

+255
-2
lines changed

4 files changed

+255
-2
lines changed

drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131
(((u64)(val) & HINIC_CMDQ_CTXT_##member##_MASK) \
3232
<< HINIC_CMDQ_CTXT_##member##_SHIFT)
3333

34+
#define HINIC_CMDQ_CTXT_PAGE_INFO_GET(val, member) \
35+
(((u64)(val) >> HINIC_CMDQ_CTXT_##member##_SHIFT) \
36+
& HINIC_CMDQ_CTXT_##member##_MASK)
37+
3438
#define HINIC_CMDQ_CTXT_PAGE_INFO_CLEAR(val, member) \
3539
((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \
3640
<< HINIC_CMDQ_CTXT_##member##_SHIFT)))
@@ -45,6 +49,10 @@
4549
(((u64)(val) & HINIC_CMDQ_CTXT_##member##_MASK) \
4650
<< HINIC_CMDQ_CTXT_##member##_SHIFT)
4751

52+
#define HINIC_CMDQ_CTXT_BLOCK_INFO_GET(val, member) \
53+
(((u64)(val) >> HINIC_CMDQ_CTXT_##member##_SHIFT) \
54+
& HINIC_CMDQ_CTXT_##member##_MASK)
55+
4856
#define HINIC_CMDQ_CTXT_BLOCK_INFO_CLEAR(val, member) \
4957
((val) & (~((u64)HINIC_CMDQ_CTXT_##member##_MASK \
5058
<< HINIC_CMDQ_CTXT_##member##_SHIFT)))

drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.c

Lines changed: 172 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ enum hinic_mbox_tx_status {
153153
(MBOX_MSG_ID(func_to_func_mbox) + 1) & MBOX_MSG_ID_MASK)
154154

155155
#define FUNC_ID_OFF_SET_8B 8
156-
#define FUNC_ID_OFF_SET_10B 10
157156

158157
/* max message counter wait to process for one function */
159158
#define HINIC_MAX_MSG_CNT_TO_PROCESS 10
@@ -189,6 +188,37 @@ enum mbox_aeq_trig_type {
189188
TRIGGER,
190189
};
191190

191+
static bool check_func_id(struct hinic_hwdev *hwdev, u16 src_func_idx,
192+
const void *buf_in, u16 in_size, u16 offset)
193+
{
194+
u16 func_idx;
195+
196+
if (in_size < offset + sizeof(func_idx)) {
197+
dev_warn(&hwdev->hwif->pdev->dev,
198+
"Receive mailbox msg len: %d less than %d Bytes is invalid\n",
199+
in_size, offset);
200+
return false;
201+
}
202+
203+
func_idx = *((u16 *)((u8 *)buf_in + offset));
204+
205+
if (src_func_idx != func_idx) {
206+
dev_warn(&hwdev->hwif->pdev->dev,
207+
"Receive mailbox function id: 0x%x not equal to msg function id: 0x%x\n",
208+
src_func_idx, func_idx);
209+
return false;
210+
}
211+
212+
return true;
213+
}
214+
215+
bool hinic_mbox_check_func_id_8B(struct hinic_hwdev *hwdev, u16 func_idx,
216+
void *buf_in, u16 in_size)
217+
{
218+
return check_func_id(hwdev, func_idx, buf_in, in_size,
219+
FUNC_ID_OFF_SET_8B);
220+
}
221+
192222
/**
193223
* hinic_register_pf_mbox_cb - register mbox callback for pf
194224
* @hwdev: the pointer to hw device
@@ -1205,15 +1235,156 @@ static void free_mbox_wb_status(struct hinic_mbox_func_to_func *func_to_func)
12051235
send_mbox->wb_paddr);
12061236
}
12071237

1238+
bool hinic_mbox_check_cmd_valid(struct hinic_hwdev *hwdev,
1239+
struct vf_cmd_check_handle *cmd_handle,
1240+
u16 vf_id, u8 cmd, void *buf_in,
1241+
u16 in_size, u8 size)
1242+
{
1243+
u16 src_idx = vf_id + hinic_glb_pf_vf_offset(hwdev->hwif);
1244+
int i;
1245+
1246+
for (i = 0; i < size; i++) {
1247+
if (cmd == cmd_handle[i].cmd) {
1248+
if (cmd_handle[i].check_cmd)
1249+
return cmd_handle[i].check_cmd(hwdev, src_idx,
1250+
buf_in, in_size);
1251+
else
1252+
return true;
1253+
}
1254+
}
1255+
1256+
dev_err(&hwdev->hwif->pdev->dev,
1257+
"PF Receive VF(%d) unsupported cmd(0x%x)\n",
1258+
vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd);
1259+
1260+
return false;
1261+
}
1262+
1263+
static bool hinic_cmdq_check_vf_ctxt(struct hinic_hwdev *hwdev,
1264+
struct hinic_cmdq_ctxt *cmdq_ctxt)
1265+
{
1266+
struct hinic_cmdq_ctxt_info *ctxt_info = &cmdq_ctxt->ctxt_info;
1267+
u64 curr_pg_pfn, wq_block_pfn;
1268+
1269+
if (cmdq_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif) ||
1270+
cmdq_ctxt->cmdq_type > HINIC_MAX_CMDQ_TYPES)
1271+
return false;
1272+
1273+
curr_pg_pfn = HINIC_CMDQ_CTXT_PAGE_INFO_GET
1274+
(ctxt_info->curr_wqe_page_pfn, CURR_WQE_PAGE_PFN);
1275+
wq_block_pfn = HINIC_CMDQ_CTXT_BLOCK_INFO_GET
1276+
(ctxt_info->wq_block_pfn, WQ_BLOCK_PFN);
1277+
/* VF must use 0-level CLA */
1278+
if (curr_pg_pfn != wq_block_pfn)
1279+
return false;
1280+
1281+
return true;
1282+
}
1283+
1284+
static bool check_cmdq_ctxt(struct hinic_hwdev *hwdev, u16 func_idx,
1285+
void *buf_in, u16 in_size)
1286+
{
1287+
if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))
1288+
return false;
1289+
1290+
return hinic_cmdq_check_vf_ctxt(hwdev, buf_in);
1291+
}
1292+
1293+
#define HW_CTX_QPS_VALID(hw_ctxt) \
1294+
((hw_ctxt)->rq_depth >= HINIC_QUEUE_MIN_DEPTH && \
1295+
(hw_ctxt)->rq_depth <= HINIC_QUEUE_MAX_DEPTH && \
1296+
(hw_ctxt)->sq_depth >= HINIC_QUEUE_MIN_DEPTH && \
1297+
(hw_ctxt)->sq_depth <= HINIC_QUEUE_MAX_DEPTH && \
1298+
(hw_ctxt)->rx_buf_sz_idx <= HINIC_MAX_RX_BUFFER_SIZE)
1299+
1300+
static bool hw_ctxt_qps_param_valid(struct hinic_cmd_hw_ioctxt *hw_ctxt)
1301+
{
1302+
if (HW_CTX_QPS_VALID(hw_ctxt))
1303+
return true;
1304+
1305+
if (!hw_ctxt->rq_depth && !hw_ctxt->sq_depth &&
1306+
!hw_ctxt->rx_buf_sz_idx)
1307+
return true;
1308+
1309+
return false;
1310+
}
1311+
1312+
static bool check_hwctxt(struct hinic_hwdev *hwdev, u16 func_idx,
1313+
void *buf_in, u16 in_size)
1314+
{
1315+
struct hinic_cmd_hw_ioctxt *hw_ctxt = buf_in;
1316+
1317+
if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))
1318+
return false;
1319+
1320+
if (hw_ctxt->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif))
1321+
return false;
1322+
1323+
if (hw_ctxt->set_cmdq_depth) {
1324+
if (hw_ctxt->cmdq_depth >= HINIC_QUEUE_MIN_DEPTH &&
1325+
hw_ctxt->cmdq_depth <= HINIC_QUEUE_MAX_DEPTH)
1326+
return true;
1327+
1328+
return false;
1329+
}
1330+
1331+
return hw_ctxt_qps_param_valid(hw_ctxt);
1332+
}
1333+
1334+
static bool check_set_wq_page_size(struct hinic_hwdev *hwdev, u16 func_idx,
1335+
void *buf_in, u16 in_size)
1336+
{
1337+
struct hinic_wq_page_size *page_size_info = buf_in;
1338+
1339+
if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size))
1340+
return false;
1341+
1342+
if (page_size_info->ppf_idx != HINIC_HWIF_PPF_IDX(hwdev->hwif))
1343+
return false;
1344+
1345+
if (((1U << page_size_info->page_size) * SZ_4K) !=
1346+
HINIC_DEFAULT_WQ_PAGE_SIZE)
1347+
return false;
1348+
1349+
return true;
1350+
}
1351+
1352+
static struct vf_cmd_check_handle hw_cmd_support_vf[] = {
1353+
{HINIC_COMM_CMD_START_FLR, hinic_mbox_check_func_id_8B},
1354+
{HINIC_COMM_CMD_DMA_ATTR_SET, hinic_mbox_check_func_id_8B},
1355+
{HINIC_COMM_CMD_CMDQ_CTXT_SET, check_cmdq_ctxt},
1356+
{HINIC_COMM_CMD_CMDQ_CTXT_GET, check_cmdq_ctxt},
1357+
{HINIC_COMM_CMD_HWCTXT_SET, check_hwctxt},
1358+
{HINIC_COMM_CMD_HWCTXT_GET, check_hwctxt},
1359+
{HINIC_COMM_CMD_SQ_HI_CI_SET, hinic_mbox_check_func_id_8B},
1360+
{HINIC_COMM_CMD_RES_STATE_SET, hinic_mbox_check_func_id_8B},
1361+
{HINIC_COMM_CMD_IO_RES_CLEAR, hinic_mbox_check_func_id_8B},
1362+
{HINIC_COMM_CMD_CEQ_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B},
1363+
{HINIC_COMM_CMD_MSI_CTRL_REG_WR_BY_UP, hinic_mbox_check_func_id_8B},
1364+
{HINIC_COMM_CMD_MSI_CTRL_REG_RD_BY_UP, hinic_mbox_check_func_id_8B},
1365+
{HINIC_COMM_CMD_L2NIC_RESET, hinic_mbox_check_func_id_8B},
1366+
{HINIC_COMM_CMD_PAGESIZE_SET, check_set_wq_page_size},
1367+
};
1368+
12081369
static int comm_pf_mbox_handler(void *handle, u16 vf_id, u8 cmd, void *buf_in,
12091370
u16 in_size, void *buf_out, u16 *out_size)
12101371
{
1372+
u8 size = ARRAY_SIZE(hw_cmd_support_vf);
12111373
struct hinic_hwdev *hwdev = handle;
12121374
struct hinic_pfhwdev *pfhwdev;
12131375
int err = 0;
12141376

12151377
pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
12161378

1379+
if (!hinic_mbox_check_cmd_valid(handle, hw_cmd_support_vf, vf_id, cmd,
1380+
buf_in, in_size, size)) {
1381+
dev_err(&hwdev->hwif->pdev->dev,
1382+
"PF Receive VF: %d common cmd: 0x%x or mbox len: 0x%x is invalid\n",
1383+
vf_id + hinic_glb_pf_vf_offset(hwdev->hwif), cmd,
1384+
in_size);
1385+
return HINIC_MBOX_VF_CMD_ERROR;
1386+
}
1387+
12171388
if (cmd == HINIC_COMM_CMD_START_FLR) {
12181389
*out_size = 0;
12191390
} else {

drivers/net/ethernet/huawei/hinic/hinic_hw_mbox.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424

2525
#define MAX_FUNCTION_NUM 512
2626

27+
struct vf_cmd_check_handle {
28+
u8 cmd;
29+
bool (*check_cmd)(struct hinic_hwdev *hwdev, u16 src_func_idx,
30+
void *buf_in, u16 in_size);
31+
};
32+
2733
enum hinic_mbox_ack_type {
2834
MBOX_ACK,
2935
MBOX_NO_ACK,
@@ -122,6 +128,14 @@ struct vf_cmd_msg_handle {
122128
void *buf_out, u16 *out_size);
123129
};
124130

131+
bool hinic_mbox_check_func_id_8B(struct hinic_hwdev *hwdev, u16 func_idx,
132+
void *buf_in, u16 in_size);
133+
134+
bool hinic_mbox_check_cmd_valid(struct hinic_hwdev *hwdev,
135+
struct vf_cmd_check_handle *cmd_handle,
136+
u16 vf_id, u8 cmd, void *buf_in,
137+
u16 in_size, u8 size);
138+
125139
int hinic_register_pf_mbox_cb(struct hinic_hwdev *hwdev,
126140
enum hinic_mod_type mod,
127141
hinic_pf_mbox_cb callback);

drivers/net/ethernet/huawei/hinic/hinic_sriov.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,18 @@ static int hinic_get_vf_link_status_msg_handler(void *hwdev, u16 vf_id,
429429
return 0;
430430
}
431431

432+
static bool check_func_table(struct hinic_hwdev *hwdev, u16 func_idx,
433+
void *buf_in, u16 in_size)
434+
{
435+
struct hinic_cmd_fw_ctxt *function_table = buf_in;
436+
437+
if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size) ||
438+
!function_table->rx_buf_sz)
439+
return false;
440+
441+
return true;
442+
}
443+
432444
static struct vf_cmd_msg_handle nic_vf_cmd_msg_handler[] = {
433445
{HINIC_PORT_CMD_VF_REGISTER, hinic_register_vf_msg_handler},
434446
{HINIC_PORT_CMD_VF_UNREGISTER, hinic_unregister_vf_msg_handler},
@@ -439,6 +451,45 @@ static struct vf_cmd_msg_handle nic_vf_cmd_msg_handler[] = {
439451
{HINIC_PORT_CMD_GET_LINK_STATE, hinic_get_vf_link_status_msg_handler},
440452
};
441453

454+
static struct vf_cmd_check_handle nic_cmd_support_vf[] = {
455+
{HINIC_PORT_CMD_VF_REGISTER, NULL},
456+
{HINIC_PORT_CMD_VF_UNREGISTER, NULL},
457+
{HINIC_PORT_CMD_CHANGE_MTU, hinic_mbox_check_func_id_8B},
458+
{HINIC_PORT_CMD_ADD_VLAN, hinic_mbox_check_func_id_8B},
459+
{HINIC_PORT_CMD_DEL_VLAN, hinic_mbox_check_func_id_8B},
460+
{HINIC_PORT_CMD_SET_MAC, hinic_mbox_check_func_id_8B},
461+
{HINIC_PORT_CMD_GET_MAC, hinic_mbox_check_func_id_8B},
462+
{HINIC_PORT_CMD_DEL_MAC, hinic_mbox_check_func_id_8B},
463+
{HINIC_PORT_CMD_SET_RX_MODE, hinic_mbox_check_func_id_8B},
464+
{HINIC_PORT_CMD_GET_PAUSE_INFO, hinic_mbox_check_func_id_8B},
465+
{HINIC_PORT_CMD_GET_LINK_STATE, hinic_mbox_check_func_id_8B},
466+
{HINIC_PORT_CMD_SET_LRO, hinic_mbox_check_func_id_8B},
467+
{HINIC_PORT_CMD_SET_RX_CSUM, hinic_mbox_check_func_id_8B},
468+
{HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD, hinic_mbox_check_func_id_8B},
469+
{HINIC_PORT_CMD_GET_VPORT_STAT, hinic_mbox_check_func_id_8B},
470+
{HINIC_PORT_CMD_CLEAN_VPORT_STAT, hinic_mbox_check_func_id_8B},
471+
{HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
472+
hinic_mbox_check_func_id_8B},
473+
{HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},
474+
{HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},
475+
{HINIC_PORT_CMD_SET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},
476+
{HINIC_PORT_CMD_GET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},
477+
{HINIC_PORT_CMD_GET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},
478+
{HINIC_PORT_CMD_SET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},
479+
{HINIC_PORT_CMD_RSS_TEMP_MGR, hinic_mbox_check_func_id_8B},
480+
{HINIC_PORT_CMD_RSS_CFG, hinic_mbox_check_func_id_8B},
481+
{HINIC_PORT_CMD_FWCTXT_INIT, check_func_table},
482+
{HINIC_PORT_CMD_GET_MGMT_VERSION, NULL},
483+
{HINIC_PORT_CMD_SET_FUNC_STATE, hinic_mbox_check_func_id_8B},
484+
{HINIC_PORT_CMD_GET_GLOBAL_QPN, hinic_mbox_check_func_id_8B},
485+
{HINIC_PORT_CMD_SET_TSO, hinic_mbox_check_func_id_8B},
486+
{HINIC_PORT_CMD_SET_RQ_IQ_MAP, hinic_mbox_check_func_id_8B},
487+
{HINIC_PORT_CMD_LINK_STATUS_REPORT, hinic_mbox_check_func_id_8B},
488+
{HINIC_PORT_CMD_UPDATE_MAC, hinic_mbox_check_func_id_8B},
489+
{HINIC_PORT_CMD_GET_CAP, hinic_mbox_check_func_id_8B},
490+
{HINIC_PORT_CMD_GET_LINK_MODE, hinic_mbox_check_func_id_8B},
491+
};
492+
442493
#define CHECK_IPSU_15BIT 0X8000
443494

444495
static
@@ -972,6 +1023,7 @@ int hinic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
9721023
static int nic_pf_mbox_handler(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
9731024
u16 in_size, void *buf_out, u16 *out_size)
9741025
{
1026+
u8 size = ARRAY_SIZE(nic_cmd_support_vf);
9751027
struct vf_cmd_msg_handle *vf_msg_handle;
9761028
struct hinic_hwdev *dev = hwdev;
9771029
struct hinic_func_to_io *nic_io;
@@ -980,7 +1032,15 @@ static int nic_pf_mbox_handler(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
9801032
u32 i;
9811033

9821034
if (!hwdev)
983-
return -EFAULT;
1035+
return -EINVAL;
1036+
1037+
if (!hinic_mbox_check_cmd_valid(hwdev, nic_cmd_support_vf, vf_id, cmd,
1038+
buf_in, in_size, size)) {
1039+
dev_err(&dev->hwif->pdev->dev,
1040+
"PF Receive VF nic cmd: 0x%x, mbox len: 0x%x is invalid\n",
1041+
cmd, in_size);
1042+
return HINIC_MBOX_VF_CMD_ERROR;
1043+
}
9841044

9851045
pfhwdev = container_of(dev, struct hinic_pfhwdev, hwdev);
9861046
nic_io = &dev->func_to_io;

0 commit comments

Comments
 (0)