Commit b0654e64 authored by Alexander Lobakin's avatar Alexander Lobakin Committed by Tony Nguyen

virtchnl: fix fake 1-elem arrays for structures allocated as `nents`

Finally, fix 3 structures which are allocated technically correctly,
i.e. the calculated size equals to the one that struct_size() would
return, except for sizeof(). For &virtchnl_vlan_filter_list_v2, use
the same approach when there are no enough space as taken previously
for &virtchnl_vlan_filter_list, i.e. let the maximum size be calculated
automatically instead of trying to guestimate it using maths.
Signed-off-by: default avatarAlexander Lobakin <aleksander.lobakin@intel.com>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Tested-by: default avatarRafal Romanowski <rafal.romanowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 5e7f59fa
...@@ -506,6 +506,7 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf, ...@@ -506,6 +506,7 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf,
struct virtchnl_rdma_qv_info *qv_info; struct virtchnl_rdma_qv_info *qv_info;
u32 v_idx, i, reg_idx, reg; u32 v_idx, i, reg_idx, reg;
u32 next_q_idx, next_q_type; u32 next_q_idx, next_q_type;
size_t size;
u32 msix_vf; u32 msix_vf;
int ret = 0; int ret = 0;
...@@ -521,9 +522,9 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf, ...@@ -521,9 +522,9 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf,
} }
kfree(vf->qvlist_info); kfree(vf->qvlist_info);
vf->qvlist_info = kzalloc(struct_size(vf->qvlist_info, qv_info, size = virtchnl_struct_size(vf->qvlist_info, qv_info,
qvlist_info->num_vectors - 1), qvlist_info->num_vectors);
GFP_KERNEL); vf->qvlist_info = kzalloc(size, GFP_KERNEL);
if (!vf->qvlist_info) { if (!vf->qvlist_info) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_out; goto err_out;
......
...@@ -469,8 +469,8 @@ static int iavf_client_setup_qvlist(struct iavf_info *ldev, ...@@ -469,8 +469,8 @@ static int iavf_client_setup_qvlist(struct iavf_info *ldev,
} }
v_qvlist_info = (struct virtchnl_rdma_qvlist_info *)qvlist_info; v_qvlist_info = (struct virtchnl_rdma_qvlist_info *)qvlist_info;
msg_size = struct_size(v_qvlist_info, qv_info, msg_size = virtchnl_struct_size(v_qvlist_info, qv_info,
v_qvlist_info->num_vectors - 1); v_qvlist_info->num_vectors);
adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP); adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP);
err = iavf_aq_send_msg_to_pf(&adapter->hw, err = iavf_aq_send_msg_to_pf(&adapter->hw,
......
...@@ -53,7 +53,7 @@ struct iavf_qv_info { ...@@ -53,7 +53,7 @@ struct iavf_qv_info {
struct iavf_qvlist_info { struct iavf_qvlist_info {
u32 num_vectors; u32 num_vectors;
struct iavf_qv_info qv_info[1]; struct iavf_qv_info qv_info[];
}; };
#define IAVF_CLIENT_MSIX_ALL 0xFFFFFFFF #define IAVF_CLIENT_MSIX_ALL 0xFFFFFFFF
......
...@@ -727,15 +727,12 @@ void iavf_add_vlans(struct iavf_adapter *adapter) ...@@ -727,15 +727,12 @@ void iavf_add_vlans(struct iavf_adapter *adapter)
more = true; more = true;
} }
len = sizeof(*vvfl_v2) + ((count - 1) * len = virtchnl_struct_size(vvfl_v2, filters, count);
sizeof(struct virtchnl_vlan_filter));
if (len > IAVF_MAX_AQ_BUF_SIZE) { if (len > IAVF_MAX_AQ_BUF_SIZE) {
dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n"); dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
count = (IAVF_MAX_AQ_BUF_SIZE - sizeof(*vvfl_v2)) / while (len > IAVF_MAX_AQ_BUF_SIZE)
sizeof(struct virtchnl_vlan_filter); len = virtchnl_struct_size(vvfl_v2, filters,
len = sizeof(*vvfl_v2) + --count);
((count - 1) *
sizeof(struct virtchnl_vlan_filter));
more = true; more = true;
} }
...@@ -879,16 +876,12 @@ void iavf_del_vlans(struct iavf_adapter *adapter) ...@@ -879,16 +876,12 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
adapter->current_op = VIRTCHNL_OP_DEL_VLAN_V2; adapter->current_op = VIRTCHNL_OP_DEL_VLAN_V2;
len = sizeof(*vvfl_v2) + len = virtchnl_struct_size(vvfl_v2, filters, count);
((count - 1) * sizeof(struct virtchnl_vlan_filter));
if (len > IAVF_MAX_AQ_BUF_SIZE) { if (len > IAVF_MAX_AQ_BUF_SIZE) {
dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n"); dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
count = (IAVF_MAX_AQ_BUF_SIZE - while (len > IAVF_MAX_AQ_BUF_SIZE)
sizeof(*vvfl_v2)) / len = virtchnl_struct_size(vvfl_v2, filters,
sizeof(struct virtchnl_vlan_filter); --count);
len = sizeof(*vvfl_v2) +
((count - 1) *
sizeof(struct virtchnl_vlan_filter));
more = true; more = true;
} }
...@@ -1492,7 +1485,7 @@ void iavf_enable_channels(struct iavf_adapter *adapter) ...@@ -1492,7 +1485,7 @@ void iavf_enable_channels(struct iavf_adapter *adapter)
return; return;
} }
len = struct_size(vti, list, adapter->num_tc - 1); len = virtchnl_struct_size(vti, list, adapter->num_tc);
vti = kzalloc(len, GFP_KERNEL); vti = kzalloc(len, GFP_KERNEL);
if (!vti) if (!vti)
return; return;
......
...@@ -716,10 +716,11 @@ struct virtchnl_vlan_filter_list_v2 { ...@@ -716,10 +716,11 @@ struct virtchnl_vlan_filter_list_v2 {
u16 vport_id; u16 vport_id;
u16 num_elements; u16 num_elements;
u8 pad[4]; u8 pad[4];
struct virtchnl_vlan_filter filters[1]; struct virtchnl_vlan_filter filters[];
}; };
VIRTCHNL_CHECK_STRUCT_LEN(40, virtchnl_vlan_filter_list_v2); VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_vlan_filter_list_v2);
#define virtchnl_vlan_filter_list_v2_LEGACY_SIZEOF 40
/* VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2 /* VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2
* VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2 * VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2
...@@ -918,10 +919,11 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_channel_info); ...@@ -918,10 +919,11 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_channel_info);
struct virtchnl_tc_info { struct virtchnl_tc_info {
u32 num_tc; u32 num_tc;
u32 pad; u32 pad;
struct virtchnl_channel_info list[1]; struct virtchnl_channel_info list[];
}; };
VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_tc_info); VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_tc_info);
#define virtchnl_tc_info_LEGACY_SIZEOF 24
/* VIRTCHNL_ADD_CLOUD_FILTER /* VIRTCHNL_ADD_CLOUD_FILTER
* VIRTCHNL_DEL_CLOUD_FILTER * VIRTCHNL_DEL_CLOUD_FILTER
...@@ -1059,10 +1061,11 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_rdma_qv_info); ...@@ -1059,10 +1061,11 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_rdma_qv_info);
struct virtchnl_rdma_qvlist_info { struct virtchnl_rdma_qvlist_info {
u32 num_vectors; u32 num_vectors;
struct virtchnl_rdma_qv_info qv_info[1]; struct virtchnl_rdma_qv_info qv_info[];
}; };
VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_rdma_qvlist_info); VIRTCHNL_CHECK_STRUCT_LEN(4, virtchnl_rdma_qvlist_info);
#define virtchnl_rdma_qvlist_info_LEGACY_SIZEOF 16
/* VF reset states - these are written into the RSTAT register: /* VF reset states - these are written into the RSTAT register:
* VFGEN_RSTAT on the VF * VFGEN_RSTAT on the VF
...@@ -1377,6 +1380,9 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del); ...@@ -1377,6 +1380,9 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del);
#define __vss_byone(p, member, count, old) \ #define __vss_byone(p, member, count, old) \
(struct_size(p, member, count) + (old - 1 - struct_size(p, member, 0))) (struct_size(p, member, count) + (old - 1 - struct_size(p, member, 0)))
#define __vss_byelem(p, member, count, old) \
(struct_size(p, member, count - 1) + (old - struct_size(p, member, 0)))
#define __vss_full(p, member, count, old) \ #define __vss_full(p, member, count, old) \
(struct_size(p, member, count) + (old - struct_size(p, member, 0))) (struct_size(p, member, count) + (old - struct_size(p, member, 0)))
...@@ -1390,6 +1396,9 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del); ...@@ -1390,6 +1396,9 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del);
__vss(virtchnl_irq_map_info, __vss_full, p, m, c), \ __vss(virtchnl_irq_map_info, __vss_full, p, m, c), \
__vss(virtchnl_ether_addr_list, __vss_full, p, m, c), \ __vss(virtchnl_ether_addr_list, __vss_full, p, m, c), \
__vss(virtchnl_vlan_filter_list, __vss_full, p, m, c), \ __vss(virtchnl_vlan_filter_list, __vss_full, p, m, c), \
__vss(virtchnl_vlan_filter_list_v2, __vss_byelem, p, m, c), \
__vss(virtchnl_tc_info, __vss_byelem, p, m, c), \
__vss(virtchnl_rdma_qvlist_info, __vss_byelem, p, m, c), \
__vss(virtchnl_rss_key, __vss_byone, p, m, c), \ __vss(virtchnl_rss_key, __vss_byone, p, m, c), \
__vss(virtchnl_rss_lut, __vss_byone, p, m, c)) __vss(virtchnl_rss_lut, __vss_byone, p, m, c))
...@@ -1495,13 +1504,13 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, ...@@ -1495,13 +1504,13 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
case VIRTCHNL_OP_RELEASE_RDMA_IRQ_MAP: case VIRTCHNL_OP_RELEASE_RDMA_IRQ_MAP:
break; break;
case VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP: case VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP:
valid_len = sizeof(struct virtchnl_rdma_qvlist_info); valid_len = virtchnl_rdma_qvlist_info_LEGACY_SIZEOF;
if (msglen >= valid_len) { if (msglen >= valid_len) {
struct virtchnl_rdma_qvlist_info *qv = struct virtchnl_rdma_qvlist_info *qv =
(struct virtchnl_rdma_qvlist_info *)msg; (struct virtchnl_rdma_qvlist_info *)msg;
valid_len += ((qv->num_vectors - 1) * valid_len = virtchnl_struct_size(qv, qv_info,
sizeof(struct virtchnl_rdma_qv_info)); qv->num_vectors);
} }
break; break;
case VIRTCHNL_OP_CONFIG_RSS_KEY: case VIRTCHNL_OP_CONFIG_RSS_KEY:
...@@ -1534,12 +1543,12 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, ...@@ -1534,12 +1543,12 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
valid_len = sizeof(struct virtchnl_vf_res_request); valid_len = sizeof(struct virtchnl_vf_res_request);
break; break;
case VIRTCHNL_OP_ENABLE_CHANNELS: case VIRTCHNL_OP_ENABLE_CHANNELS:
valid_len = sizeof(struct virtchnl_tc_info); valid_len = virtchnl_tc_info_LEGACY_SIZEOF;
if (msglen >= valid_len) { if (msglen >= valid_len) {
struct virtchnl_tc_info *vti = struct virtchnl_tc_info *vti =
(struct virtchnl_tc_info *)msg; (struct virtchnl_tc_info *)msg;
valid_len += (vti->num_tc - 1) * valid_len = virtchnl_struct_size(vti, list,
sizeof(struct virtchnl_channel_info); vti->num_tc);
if (vti->num_tc == 0) if (vti->num_tc == 0)
err_msg_format = true; err_msg_format = true;
} }
...@@ -1566,13 +1575,13 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode, ...@@ -1566,13 +1575,13 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
break; break;
case VIRTCHNL_OP_ADD_VLAN_V2: case VIRTCHNL_OP_ADD_VLAN_V2:
case VIRTCHNL_OP_DEL_VLAN_V2: case VIRTCHNL_OP_DEL_VLAN_V2:
valid_len = sizeof(struct virtchnl_vlan_filter_list_v2); valid_len = virtchnl_vlan_filter_list_v2_LEGACY_SIZEOF;
if (msglen >= valid_len) { if (msglen >= valid_len) {
struct virtchnl_vlan_filter_list_v2 *vfl = struct virtchnl_vlan_filter_list_v2 *vfl =
(struct virtchnl_vlan_filter_list_v2 *)msg; (struct virtchnl_vlan_filter_list_v2 *)msg;
valid_len += (vfl->num_elements - 1) * valid_len = virtchnl_struct_size(vfl, filters,
sizeof(struct virtchnl_vlan_filter); vfl->num_elements);
if (vfl->num_elements == 0) { if (vfl->num_elements == 0) {
err_msg_format = true; err_msg_format = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment