mirror of
https://github.com/lkl/linux.git
synced 2025-12-19 08:03:01 +09:00
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: Alexander Lobakin <aleksander.lobakin@intel.com> Reviewed-by: Kees Cook <keescook@chromium.org> Tested-by: Rafal Romanowski <rafal.romanowski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
committed by
Tony Nguyen
parent
5e7f59fa07
commit
b0654e64db
@@ -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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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 {
|
|||||||
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);
|
|||||||
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);
|
|||||||
|
|
||||||
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);
|
|||||||
#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);
|
|||||||
__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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user