Skip to content

Commit b0654e6

Browse files
alobakinanguy11
authored andcommitted
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 <[email protected]> Reviewed-by: Kees Cook <[email protected]> Tested-by: Rafal Romanowski <[email protected]> Signed-off-by: Tony Nguyen <[email protected]>
1 parent 5e7f59f commit b0654e6

File tree

5 files changed

+40
-37
lines changed

5 files changed

+40
-37
lines changed

drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf,
506506
struct virtchnl_rdma_qv_info *qv_info;
507507
u32 v_idx, i, reg_idx, reg;
508508
u32 next_q_idx, next_q_type;
509+
size_t size;
509510
u32 msix_vf;
510511
int ret = 0;
511512

@@ -521,9 +522,9 @@ i40e_config_rdma_qvlist(struct i40e_vf *vf,
521522
}
522523

523524
kfree(vf->qvlist_info);
524-
vf->qvlist_info = kzalloc(struct_size(vf->qvlist_info, qv_info,
525-
qvlist_info->num_vectors - 1),
526-
GFP_KERNEL);
525+
size = virtchnl_struct_size(vf->qvlist_info, qv_info,
526+
qvlist_info->num_vectors);
527+
vf->qvlist_info = kzalloc(size, GFP_KERNEL);
527528
if (!vf->qvlist_info) {
528529
ret = -ENOMEM;
529530
goto err_out;

drivers/net/ethernet/intel/iavf/iavf_client.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,8 +469,8 @@ static int iavf_client_setup_qvlist(struct iavf_info *ldev,
469469
}
470470

471471
v_qvlist_info = (struct virtchnl_rdma_qvlist_info *)qvlist_info;
472-
msg_size = struct_size(v_qvlist_info, qv_info,
473-
v_qvlist_info->num_vectors - 1);
472+
msg_size = virtchnl_struct_size(v_qvlist_info, qv_info,
473+
v_qvlist_info->num_vectors);
474474

475475
adapter->client_pending |= BIT(VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP);
476476
err = iavf_aq_send_msg_to_pf(&adapter->hw,

drivers/net/ethernet/intel/iavf/iavf_client.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ struct iavf_qv_info {
5353

5454
struct iavf_qvlist_info {
5555
u32 num_vectors;
56-
struct iavf_qv_info qv_info[1];
56+
struct iavf_qv_info qv_info[];
5757
};
5858

5959
#define IAVF_CLIENT_MSIX_ALL 0xFFFFFFFF

drivers/net/ethernet/intel/iavf/iavf_virtchnl.c

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -727,15 +727,12 @@ void iavf_add_vlans(struct iavf_adapter *adapter)
727727
more = true;
728728
}
729729

730-
len = sizeof(*vvfl_v2) + ((count - 1) *
731-
sizeof(struct virtchnl_vlan_filter));
730+
len = virtchnl_struct_size(vvfl_v2, filters, count);
732731
if (len > IAVF_MAX_AQ_BUF_SIZE) {
733732
dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
734-
count = (IAVF_MAX_AQ_BUF_SIZE - sizeof(*vvfl_v2)) /
735-
sizeof(struct virtchnl_vlan_filter);
736-
len = sizeof(*vvfl_v2) +
737-
((count - 1) *
738-
sizeof(struct virtchnl_vlan_filter));
733+
while (len > IAVF_MAX_AQ_BUF_SIZE)
734+
len = virtchnl_struct_size(vvfl_v2, filters,
735+
--count);
739736
more = true;
740737
}
741738

@@ -879,16 +876,12 @@ void iavf_del_vlans(struct iavf_adapter *adapter)
879876

880877
adapter->current_op = VIRTCHNL_OP_DEL_VLAN_V2;
881878

882-
len = sizeof(*vvfl_v2) +
883-
((count - 1) * sizeof(struct virtchnl_vlan_filter));
879+
len = virtchnl_struct_size(vvfl_v2, filters, count);
884880
if (len > IAVF_MAX_AQ_BUF_SIZE) {
885881
dev_warn(&adapter->pdev->dev, "Too many add VLAN changes in one request\n");
886-
count = (IAVF_MAX_AQ_BUF_SIZE -
887-
sizeof(*vvfl_v2)) /
888-
sizeof(struct virtchnl_vlan_filter);
889-
len = sizeof(*vvfl_v2) +
890-
((count - 1) *
891-
sizeof(struct virtchnl_vlan_filter));
882+
while (len > IAVF_MAX_AQ_BUF_SIZE)
883+
len = virtchnl_struct_size(vvfl_v2, filters,
884+
--count);
892885
more = true;
893886
}
894887

@@ -1492,7 +1485,7 @@ void iavf_enable_channels(struct iavf_adapter *adapter)
14921485
return;
14931486
}
14941487

1495-
len = struct_size(vti, list, adapter->num_tc - 1);
1488+
len = virtchnl_struct_size(vti, list, adapter->num_tc);
14961489
vti = kzalloc(len, GFP_KERNEL);
14971490
if (!vti)
14981491
return;

include/linux/avf/virtchnl.h

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -716,10 +716,11 @@ struct virtchnl_vlan_filter_list_v2 {
716716
u16 vport_id;
717717
u16 num_elements;
718718
u8 pad[4];
719-
struct virtchnl_vlan_filter filters[1];
719+
struct virtchnl_vlan_filter filters[];
720720
};
721721

722-
VIRTCHNL_CHECK_STRUCT_LEN(40, virtchnl_vlan_filter_list_v2);
722+
VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_vlan_filter_list_v2);
723+
#define virtchnl_vlan_filter_list_v2_LEGACY_SIZEOF 40
723724

724725
/* VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2
725726
* VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2
@@ -918,10 +919,11 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_channel_info);
918919
struct virtchnl_tc_info {
919920
u32 num_tc;
920921
u32 pad;
921-
struct virtchnl_channel_info list[1];
922+
struct virtchnl_channel_info list[];
922923
};
923924

924-
VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_tc_info);
925+
VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_tc_info);
926+
#define virtchnl_tc_info_LEGACY_SIZEOF 24
925927

926928
/* VIRTCHNL_ADD_CLOUD_FILTER
927929
* VIRTCHNL_DEL_CLOUD_FILTER
@@ -1059,10 +1061,11 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_rdma_qv_info);
10591061

10601062
struct virtchnl_rdma_qvlist_info {
10611063
u32 num_vectors;
1062-
struct virtchnl_rdma_qv_info qv_info[1];
1064+
struct virtchnl_rdma_qv_info qv_info[];
10631065
};
10641066

1065-
VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_rdma_qvlist_info);
1067+
VIRTCHNL_CHECK_STRUCT_LEN(4, virtchnl_rdma_qvlist_info);
1068+
#define virtchnl_rdma_qvlist_info_LEGACY_SIZEOF 16
10661069

10671070
/* VF reset states - these are written into the RSTAT register:
10681071
* VFGEN_RSTAT on the VF
@@ -1377,6 +1380,9 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del);
13771380
#define __vss_byone(p, member, count, old) \
13781381
(struct_size(p, member, count) + (old - 1 - struct_size(p, member, 0)))
13791382

1383+
#define __vss_byelem(p, member, count, old) \
1384+
(struct_size(p, member, count - 1) + (old - struct_size(p, member, 0)))
1385+
13801386
#define __vss_full(p, member, count, old) \
13811387
(struct_size(p, member, count) + (old - struct_size(p, member, 0)))
13821388

@@ -1390,6 +1396,9 @@ VIRTCHNL_CHECK_STRUCT_LEN(12, virtchnl_fdir_del);
13901396
__vss(virtchnl_irq_map_info, __vss_full, p, m, c), \
13911397
__vss(virtchnl_ether_addr_list, __vss_full, p, m, c), \
13921398
__vss(virtchnl_vlan_filter_list, __vss_full, p, m, c), \
1399+
__vss(virtchnl_vlan_filter_list_v2, __vss_byelem, p, m, c), \
1400+
__vss(virtchnl_tc_info, __vss_byelem, p, m, c), \
1401+
__vss(virtchnl_rdma_qvlist_info, __vss_byelem, p, m, c), \
13931402
__vss(virtchnl_rss_key, __vss_byone, p, m, c), \
13941403
__vss(virtchnl_rss_lut, __vss_byone, p, m, c))
13951404

@@ -1495,13 +1504,13 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
14951504
case VIRTCHNL_OP_RELEASE_RDMA_IRQ_MAP:
14961505
break;
14971506
case VIRTCHNL_OP_CONFIG_RDMA_IRQ_MAP:
1498-
valid_len = sizeof(struct virtchnl_rdma_qvlist_info);
1507+
valid_len = virtchnl_rdma_qvlist_info_LEGACY_SIZEOF;
14991508
if (msglen >= valid_len) {
15001509
struct virtchnl_rdma_qvlist_info *qv =
15011510
(struct virtchnl_rdma_qvlist_info *)msg;
15021511

1503-
valid_len += ((qv->num_vectors - 1) *
1504-
sizeof(struct virtchnl_rdma_qv_info));
1512+
valid_len = virtchnl_struct_size(qv, qv_info,
1513+
qv->num_vectors);
15051514
}
15061515
break;
15071516
case VIRTCHNL_OP_CONFIG_RSS_KEY:
@@ -1534,12 +1543,12 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
15341543
valid_len = sizeof(struct virtchnl_vf_res_request);
15351544
break;
15361545
case VIRTCHNL_OP_ENABLE_CHANNELS:
1537-
valid_len = sizeof(struct virtchnl_tc_info);
1546+
valid_len = virtchnl_tc_info_LEGACY_SIZEOF;
15381547
if (msglen >= valid_len) {
15391548
struct virtchnl_tc_info *vti =
15401549
(struct virtchnl_tc_info *)msg;
1541-
valid_len += (vti->num_tc - 1) *
1542-
sizeof(struct virtchnl_channel_info);
1550+
valid_len = virtchnl_struct_size(vti, list,
1551+
vti->num_tc);
15431552
if (vti->num_tc == 0)
15441553
err_msg_format = true;
15451554
}
@@ -1566,13 +1575,13 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
15661575
break;
15671576
case VIRTCHNL_OP_ADD_VLAN_V2:
15681577
case VIRTCHNL_OP_DEL_VLAN_V2:
1569-
valid_len = sizeof(struct virtchnl_vlan_filter_list_v2);
1578+
valid_len = virtchnl_vlan_filter_list_v2_LEGACY_SIZEOF;
15701579
if (msglen >= valid_len) {
15711580
struct virtchnl_vlan_filter_list_v2 *vfl =
15721581
(struct virtchnl_vlan_filter_list_v2 *)msg;
15731582

1574-
valid_len += (vfl->num_elements - 1) *
1575-
sizeof(struct virtchnl_vlan_filter);
1583+
valid_len = virtchnl_struct_size(vfl, filters,
1584+
vfl->num_elements);
15761585

15771586
if (vfl->num_elements == 0) {
15781587
err_msg_format = true;

0 commit comments

Comments
 (0)