提交 986cadc3 编写于 作者: C Chiqijun 提交者: Yang Yingliang

net/hinic: Check the legality of out_size in nictool

driver inclusion
category: bugfix
bugzilla: 4472

-----------------------------------------------------------------------

The out_size in nictool is passed in by the user mode. If out_size is
not checked, it will cause too much memory in the kernel space to be
copied to the user space.
Signed-off-by: NChiqijun <chiqijun@huawei.com>
Reviewed-by: NZengweiliang <zengweiliang.zengweiliang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 0c19807c
...@@ -83,7 +83,7 @@ int hinic_api_csr_wr64(void *hwdev, u8 dest, u32 addr, u64 val); ...@@ -83,7 +83,7 @@ int hinic_api_csr_wr64(void *hwdev, u8 dest, u32 addr, u64 val);
int hinic_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size); int hinic_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size);
u16 hinic_dbg_clear_hw_stats(void *hwdev); u16 hinic_dbg_clear_hw_stats(void *hwdev, u32 *out_size);
void hinic_get_chip_fault_stats(const void *hwdev, void hinic_get_chip_fault_stats(const void *hwdev,
u8 *chip_fault_stats, int offset); u8 *chip_fault_stats, int offset);
......
...@@ -241,13 +241,20 @@ int hinic_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size) ...@@ -241,13 +241,20 @@ int hinic_dbg_get_hw_stats(const void *hwdev, u8 *hw_stats, u16 *out_size)
return 0; return 0;
} }
u16 hinic_dbg_clear_hw_stats(void *hwdev) u16 hinic_dbg_clear_hw_stats(void *hwdev, u32 *out_size)
{ {
if (*out_size != sizeof(struct hinic_hw_stats)) {
pr_err("Unexpect out buf size from user :%d, expect: %lu\n",
*out_size, sizeof(struct hinic_hw_stats));
return -EFAULT;
}
memset((void *)&((struct hinic_hwdev *)hwdev)->hw_stats, 0, memset((void *)&((struct hinic_hwdev *)hwdev)->hw_stats, 0,
sizeof(struct hinic_hw_stats)); sizeof(struct hinic_hw_stats));
memset((void *)((struct hinic_hwdev *)hwdev)->chip_fault_stats, 0, memset((void *)((struct hinic_hwdev *)hwdev)->chip_fault_stats, 0,
HINIC_CHIP_FAULT_SIZE); HINIC_CHIP_FAULT_SIZE);
return sizeof(struct hinic_hw_stats);
return 0;
} }
void hinic_get_chip_fault_stats(const void *hwdev, void hinic_get_chip_fault_stats(const void *hwdev,
......
...@@ -342,8 +342,6 @@ static int get_inter_num(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -342,8 +342,6 @@ static int get_inter_num(struct hinic_nic_dev *nic_dev, void *buf_in,
} }
*(u16 *)buf_out = intr_num; *(u16 *)buf_out = intr_num;
*out_size = sizeof(u16);
return 0; return 0;
} }
...@@ -361,7 +359,12 @@ static int clear_func_static(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -361,7 +359,12 @@ static int clear_func_static(struct hinic_nic_dev *nic_dev, void *buf_in,
{ {
int i; int i;
*out_size = 0; if (*out_size != 0) {
pr_err("Unexpect out buf size from user: %d, expect: 0\n",
*out_size);
return -EINVAL;
}
clean_nicdev_stats(nic_dev); clean_nicdev_stats(nic_dev);
for (i = 0; i < nic_dev->max_qps; i++) { for (i = 0; i < nic_dev->max_qps; i++) {
hinic_rxq_clean_stats(&nic_dev->rxqs[i].rxq_stats); hinic_rxq_clean_stats(&nic_dev->rxqs[i].rxq_stats);
...@@ -415,7 +418,12 @@ static int set_dcb_cos_up_map(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -415,7 +418,12 @@ static int set_dcb_cos_up_map(struct hinic_nic_dev *nic_dev, void *buf_in,
if (!buf_in || !out_size || in_size != sizeof(*map)) if (!buf_in || !out_size || in_size != sizeof(*map))
return -EINVAL; return -EINVAL;
*out_size = sizeof(*map); if (*out_size != sizeof(*map)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user: %d, expect: %lu\n",
*out_size, sizeof(*map));
return -EINVAL;
}
return hinic_set_cos_up_map(nic_dev, map->cos_up); return hinic_set_cos_up_map(nic_dev, map->cos_up);
} }
...@@ -589,7 +597,6 @@ static int set_loopback_mode(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -589,7 +597,6 @@ static int set_loopback_mode(struct hinic_nic_dev *nic_dev, void *buf_in,
u32 in_size, void *buf_out, u32 *out_size) u32 in_size, void *buf_out, u32 *out_size)
{ {
struct hinic_nic_loop_mode *mode = buf_in; struct hinic_nic_loop_mode *mode = buf_in;
int err;
if (!test_bit(HINIC_INTF_UP, &nic_dev->flags)) { if (!test_bit(HINIC_INTF_UP, &nic_dev->flags)) {
nicif_err(nic_dev, drv, nic_dev->netdev, nicif_err(nic_dev, drv, nic_dev->netdev,
...@@ -600,13 +607,15 @@ static int set_loopback_mode(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -600,13 +607,15 @@ static int set_loopback_mode(struct hinic_nic_dev *nic_dev, void *buf_in,
if (!mode || !out_size || in_size != sizeof(*mode)) if (!mode || !out_size || in_size != sizeof(*mode))
return -EFAULT; return -EFAULT;
err = hinic_set_loopback_mode_ex(nic_dev->hwdev, mode->loop_mode, if (*out_size != sizeof(*mode)) {
mode->loop_ctrl); nicif_err(nic_dev, drv, nic_dev->netdev,
if (err) "Unexpect out buf size from user: %d, expect: %lu\n",
return err; *out_size, sizeof(*mode));
return -EINVAL;
}
*out_size = sizeof(*mode); return hinic_set_loopback_mode_ex(nic_dev->hwdev, mode->loop_mode,
return 0; mode->loop_ctrl);
} }
static int set_link_mode(struct hinic_nic_dev *nic_dev, void *buf_in, static int set_link_mode(struct hinic_nic_dev *nic_dev, void *buf_in,
...@@ -624,6 +633,13 @@ static int set_link_mode(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -624,6 +633,13 @@ static int set_link_mode(struct hinic_nic_dev *nic_dev, void *buf_in,
if (!link || !out_size || in_size != sizeof(*link)) if (!link || !out_size || in_size != sizeof(*link))
return -EFAULT; return -EFAULT;
if (*out_size != sizeof(*link)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user: %d, expect: %lu\n",
*out_size, sizeof(*link));
return -EINVAL;
}
switch (*link) { switch (*link) {
case HINIC_LINK_MODE_AUTO: case HINIC_LINK_MODE_AUTO:
if (hinic_get_link_state(nic_dev->hwdev, &link_status)) if (hinic_get_link_state(nic_dev->hwdev, &link_status))
...@@ -649,7 +665,6 @@ static int set_link_mode(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -649,7 +665,6 @@ static int set_link_mode(struct hinic_nic_dev *nic_dev, void *buf_in,
return -EINVAL; return -EINVAL;
} }
*out_size = sizeof(*link);
return 0; return 0;
} }
...@@ -676,7 +691,6 @@ static int set_dcb_cfg(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -676,7 +691,6 @@ static int set_dcb_cfg(struct hinic_nic_dev *nic_dev, void *buf_in,
} }
dcb_ctl.dcb_data.err = (u8)err; dcb_ctl.dcb_data.err = (u8)err;
*((u32 *)buf_out) = (u32)dcb_ctl.data; *((u32 *)buf_out) = (u32)dcb_ctl.data;
*out_size = sizeof(u32);
return 0; return 0;
} }
...@@ -699,7 +713,6 @@ int get_pfc_info(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -699,7 +713,6 @@ int get_pfc_info(struct hinic_nic_dev *nic_dev, void *buf_in,
hinic_dcbnl_get_tc_num_tool(nic_dev->netdev, hinic_dcbnl_get_tc_num_tool(nic_dev->netdev,
&pfc.pfc_data.num_of_tc); &pfc.pfc_data.num_of_tc);
*((u32 *)buf_out) = (u32)pfc.data; *((u32 *)buf_out) = (u32)pfc.data;
*out_size = sizeof(u32);
return 0; return 0;
} }
...@@ -732,7 +745,7 @@ int set_pfc_control(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -732,7 +745,7 @@ int set_pfc_control(struct hinic_nic_dev *nic_dev, void *buf_in,
exit: exit:
*((u8 *)buf_out) = (u8)err; *((u8 *)buf_out) = (u8)err;
*out_size = sizeof(u8);
return 0; return 0;
} }
...@@ -807,7 +820,7 @@ int set_ets(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -807,7 +820,7 @@ int set_ets(struct hinic_nic_dev *nic_dev, void *buf_in,
} }
exit: exit:
*((u8 *)buf_out) = err; *((u8 *)buf_out) = err;
*out_size = sizeof(err);
return 0; return 0;
} }
...@@ -874,7 +887,6 @@ int get_ets_info(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -874,7 +887,6 @@ int get_ets_info(struct hinic_nic_dev *nic_dev, void *buf_in,
hinic_dcbnl_set_ets_strict_tool(nic_dev->netdev, &ets->strict, false); hinic_dcbnl_set_ets_strict_tool(nic_dev->netdev, &ets->strict, false);
ets->err = 0; ets->err = 0;
*out_size = sizeof(*ets);
return 0; return 0;
} }
...@@ -907,7 +919,6 @@ int set_pfc_priority(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -907,7 +919,6 @@ int set_pfc_priority(struct hinic_nic_dev *nic_dev, void *buf_in,
} }
exit: exit:
*((u8 *)buf_out) = (u8)err; *((u8 *)buf_out) = (u8)err;
*out_size = sizeof(u8);
return 0; return 0;
} }
...@@ -940,7 +951,6 @@ static int set_pf_bw_limit(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -940,7 +951,6 @@ static int set_pf_bw_limit(struct hinic_nic_dev *nic_dev, void *buf_in,
} }
*((u8 *)buf_out) = (u8)err; *((u8 *)buf_out) = (u8)err;
*out_size = sizeof(u8);
return 0; return 0;
} }
...@@ -992,15 +1002,16 @@ static int set_poll_weight(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -992,15 +1002,16 @@ static int set_poll_weight(struct hinic_nic_dev *nic_dev, void *buf_in,
{ {
struct hinic_nic_poll_weight *weight_info = buf_in; struct hinic_nic_poll_weight *weight_info = buf_in;
if (!buf_in || in_size != sizeof(*weight_info)) { if (!buf_in || in_size != sizeof(*weight_info) ||
*out_size != sizeof(u32)) {
nicif_err(nic_dev, drv, nic_dev->netdev, nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect in buf size from user: %u, expect: %lu\n", "Unexpect in buf size: %u or out buf size: %d from user, expect: %lu\n",
*out_size, sizeof(*weight_info)); in_size, *out_size, sizeof(*weight_info));
return -EFAULT; return -EFAULT;
} }
nic_dev->poll_weight = weight_info->poll_weight; nic_dev->poll_weight = weight_info->poll_weight;
*out_size = sizeof(u32);
return 0; return 0;
} }
...@@ -1021,8 +1032,6 @@ static int get_homologue(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -1021,8 +1032,6 @@ static int get_homologue(struct hinic_nic_dev *nic_dev, void *buf_in,
else else
homo->homo_state = HINIC_HOMOLOGUES_OFF; homo->homo_state = HINIC_HOMOLOGUES_OFF;
*out_size = sizeof(*homo);
return 0; return 0;
} }
...@@ -1031,10 +1040,11 @@ static int set_homologue(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -1031,10 +1040,11 @@ static int set_homologue(struct hinic_nic_dev *nic_dev, void *buf_in,
{ {
struct hinic_homologues *homo = buf_in; struct hinic_homologues *homo = buf_in;
if (!buf_in || in_size != sizeof(*homo)) { if (!buf_in || in_size != sizeof(*homo) ||
*out_size != sizeof(*homo)) {
nicif_err(nic_dev, drv, nic_dev->netdev, nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect in buf size from user: %d, expect: %lu\n", "Unexpect in buf size: %d or out buf size: %d from user, expect: %lu\n",
*out_size, sizeof(*homo)); in_size, *out_size, sizeof(*homo));
return -EFAULT; return -EFAULT;
} }
...@@ -1047,8 +1057,6 @@ static int set_homologue(struct hinic_nic_dev *nic_dev, void *buf_in, ...@@ -1047,8 +1057,6 @@ static int set_homologue(struct hinic_nic_dev *nic_dev, void *buf_in,
return -EFAULT; return -EFAULT;
} }
*out_size = sizeof(*homo);
return 0; return 0;
} }
...@@ -1146,7 +1154,7 @@ static int get_func_id(void *hwdev, void *buf_in, u32 in_size, ...@@ -1146,7 +1154,7 @@ static int get_func_id(void *hwdev, void *buf_in, u32 in_size,
func_id = hinic_global_func_id_hw(hwdev); func_id = hinic_global_func_id_hw(hwdev);
*(u16 *)buf_out = func_id; *(u16 *)buf_out = func_id;
*out_size = sizeof(u16);
return 0; return 0;
} }
...@@ -1179,8 +1187,7 @@ static int get_hw_stats(void *hwdev, void *buf_in, u32 in_size, ...@@ -1179,8 +1187,7 @@ static int get_hw_stats(void *hwdev, void *buf_in, u32 in_size,
static int clear_hw_stats(void *hwdev, void *buf_in, u32 in_size, static int clear_hw_stats(void *hwdev, void *buf_in, u32 in_size,
void *buf_out, u32 *out_size) void *buf_out, u32 *out_size)
{ {
*out_size = hinic_dbg_clear_hw_stats(hwdev); return hinic_dbg_clear_hw_stats(hwdev, out_size);
return 0;
} }
static int get_drv_version(void *hwdev, void *buf_in, u32 in_size, static int get_drv_version(void *hwdev, void *buf_in, u32 in_size,
...@@ -1231,7 +1238,6 @@ static int get_single_card_info(void *hwdev, void *buf_in, u32 in_size, ...@@ -1231,7 +1238,6 @@ static int get_single_card_info(void *hwdev, void *buf_in, u32 in_size,
} }
hinic_get_card_info(hwdev, buf_out); hinic_get_card_info(hwdev, buf_out);
*out_size = in_size;
return 0; return 0;
} }
...@@ -1242,8 +1248,7 @@ static int get_device_id(void *hwdev, void *buf_in, u32 in_size, ...@@ -1242,8 +1248,7 @@ static int get_device_id(void *hwdev, void *buf_in, u32 in_size,
u16 dev_id; u16 dev_id;
int err; int err;
if (!buf_out || !buf_in || *out_size != sizeof(u16) || if (!buf_out || *out_size != sizeof(u16)) {
in_size != sizeof(u16)) {
pr_err("Unexpect out buf size from user: %d, expect: %lu\n", pr_err("Unexpect out buf size from user: %d, expect: %lu\n",
*out_size, sizeof(u16)); *out_size, sizeof(u16));
return -EFAULT; return -EFAULT;
...@@ -1254,7 +1259,6 @@ static int get_device_id(void *hwdev, void *buf_in, u32 in_size, ...@@ -1254,7 +1259,6 @@ static int get_device_id(void *hwdev, void *buf_in, u32 in_size,
return err; return err;
*((u32 *)buf_out) = dev_id; *((u32 *)buf_out) = dev_id;
*out_size = in_size;
return 0; return 0;
} }
...@@ -1294,8 +1298,6 @@ static int get_pf_id(void *hwdev, void *buf_in, u32 in_size, ...@@ -1294,8 +1298,6 @@ static int get_pf_id(void *hwdev, void *buf_in, u32 in_size,
if (err) if (err)
return err; return err;
*out_size = sizeof(*pf_info);
return 0; return 0;
} }
...@@ -1478,6 +1480,12 @@ static int get_firmware_active_status(void *hwdev, void *buf_in, u32 in_size, ...@@ -1478,6 +1480,12 @@ static int get_firmware_active_status(void *hwdev, void *buf_in, u32 in_size,
{ {
u32 loop_cnt = 0; u32 loop_cnt = 0;
if (*out_size != 0) {
pr_err("Unexpect out buf size from user: %d, expect: 0\n",
*out_size);
return -EINVAL;
}
while (loop_cnt < GET_FIRMWARE_ACTIVE_STATUS_TIMEOUT) { while (loop_cnt < GET_FIRMWARE_ACTIVE_STATUS_TIMEOUT) {
if (!hinic_get_mgmt_channel_status(hwdev)) if (!hinic_get_mgmt_channel_status(hwdev))
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册