Skip to content

Commit 14b526f

Browse files
Erick Archerjgunthorpe
authored andcommitted
RDMA/uverbs: Remove flexible arrays from struct *_filter
When a struct containing a flexible array is included in another struct, and there is a member after the struct-with-flex-array, there is a possibility of memory overlap. These cases must be audited [1]. See: struct inner { ... int flex[]; }; struct outer { ... struct inner header; int overlap; ... }; This is the scenario for all the "struct *_filter" structures that are included in the following "struct ib_flow_spec_*" structures: struct ib_flow_spec_eth struct ib_flow_spec_ib struct ib_flow_spec_ipv4 struct ib_flow_spec_ipv6 struct ib_flow_spec_tcp_udp struct ib_flow_spec_tunnel struct ib_flow_spec_esp struct ib_flow_spec_gre struct ib_flow_spec_mpls The pattern is like the one shown below: struct *_filter { ... u8 real_sz[]; }; struct ib_flow_spec_* { ... struct *_filter val; struct *_filter mask; }; In this case, the trailing flexible array "real_sz" is never allocated and is only used to calculate the size of the structures. Here the use of the "offsetof" helper can be changed by the "sizeof" operator because the goal is to get the size of these structures. Therefore, the trailing flexible arrays can also be removed. However, due to the trailing padding that can be induced in structs it is possible that the: offsetof(struct *_filter, real_sz) != sizeof(struct *_filter) This situation happens with the "struct ib_flow_ipv6_filter" and to avoid it the "__packed" macro is used in this structure. But now, the "sizeof(struct ib_flow_ipv6_filter)" has changed. This is not a problem since this size is not used in the code. The situation now is that "sizeof(struct ib_flow_spec_ipv6)" has also changed (this struct contains the struct ib_flow_ipv6_filter). This is also not a problem since it is only used to set the size of the "union ib_flow_spec", which can store all the "ib_flow_spec_*" structures. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Erick Archer <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 7a8bccd commit 14b526f

File tree

2 files changed

+9
-26
lines changed

2 files changed

+9
-26
lines changed

drivers/infiniband/core/uverbs_cmd.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2737,7 +2737,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
27372737

27382738
switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) {
27392739
case IB_FLOW_SPEC_ETH:
2740-
ib_filter_sz = offsetof(struct ib_flow_eth_filter, real_sz);
2740+
ib_filter_sz = sizeof(struct ib_flow_eth_filter);
27412741
actual_filter_sz = spec_filter_size(kern_spec_mask,
27422742
kern_filter_sz,
27432743
ib_filter_sz);
@@ -2748,7 +2748,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
27482748
memcpy(&ib_spec->eth.mask, kern_spec_mask, actual_filter_sz);
27492749
break;
27502750
case IB_FLOW_SPEC_IPV4:
2751-
ib_filter_sz = offsetof(struct ib_flow_ipv4_filter, real_sz);
2751+
ib_filter_sz = sizeof(struct ib_flow_ipv4_filter);
27522752
actual_filter_sz = spec_filter_size(kern_spec_mask,
27532753
kern_filter_sz,
27542754
ib_filter_sz);
@@ -2759,7 +2759,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
27592759
memcpy(&ib_spec->ipv4.mask, kern_spec_mask, actual_filter_sz);
27602760
break;
27612761
case IB_FLOW_SPEC_IPV6:
2762-
ib_filter_sz = offsetof(struct ib_flow_ipv6_filter, real_sz);
2762+
ib_filter_sz = sizeof(struct ib_flow_ipv6_filter);
27632763
actual_filter_sz = spec_filter_size(kern_spec_mask,
27642764
kern_filter_sz,
27652765
ib_filter_sz);
@@ -2775,7 +2775,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
27752775
break;
27762776
case IB_FLOW_SPEC_TCP:
27772777
case IB_FLOW_SPEC_UDP:
2778-
ib_filter_sz = offsetof(struct ib_flow_tcp_udp_filter, real_sz);
2778+
ib_filter_sz = sizeof(struct ib_flow_tcp_udp_filter);
27792779
actual_filter_sz = spec_filter_size(kern_spec_mask,
27802780
kern_filter_sz,
27812781
ib_filter_sz);
@@ -2786,7 +2786,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
27862786
memcpy(&ib_spec->tcp_udp.mask, kern_spec_mask, actual_filter_sz);
27872787
break;
27882788
case IB_FLOW_SPEC_VXLAN_TUNNEL:
2789-
ib_filter_sz = offsetof(struct ib_flow_tunnel_filter, real_sz);
2789+
ib_filter_sz = sizeof(struct ib_flow_tunnel_filter);
27902790
actual_filter_sz = spec_filter_size(kern_spec_mask,
27912791
kern_filter_sz,
27922792
ib_filter_sz);
@@ -2801,7 +2801,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
28012801
return -EINVAL;
28022802
break;
28032803
case IB_FLOW_SPEC_ESP:
2804-
ib_filter_sz = offsetof(struct ib_flow_esp_filter, real_sz);
2804+
ib_filter_sz = sizeof(struct ib_flow_esp_filter);
28052805
actual_filter_sz = spec_filter_size(kern_spec_mask,
28062806
kern_filter_sz,
28072807
ib_filter_sz);
@@ -2812,7 +2812,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
28122812
memcpy(&ib_spec->esp.mask, kern_spec_mask, actual_filter_sz);
28132813
break;
28142814
case IB_FLOW_SPEC_GRE:
2815-
ib_filter_sz = offsetof(struct ib_flow_gre_filter, real_sz);
2815+
ib_filter_sz = sizeof(struct ib_flow_gre_filter);
28162816
actual_filter_sz = spec_filter_size(kern_spec_mask,
28172817
kern_filter_sz,
28182818
ib_filter_sz);
@@ -2823,7 +2823,7 @@ int ib_uverbs_kern_spec_to_ib_spec_filter(enum ib_flow_spec_type type,
28232823
memcpy(&ib_spec->gre.mask, kern_spec_mask, actual_filter_sz);
28242824
break;
28252825
case IB_FLOW_SPEC_MPLS:
2826-
ib_filter_sz = offsetof(struct ib_flow_mpls_filter, real_sz);
2826+
ib_filter_sz = sizeof(struct ib_flow_mpls_filter);
28272827
actual_filter_sz = spec_filter_size(kern_spec_mask,
28282828
kern_filter_sz,
28292829
ib_filter_sz);

include/rdma/ib_verbs.h

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1910,8 +1910,6 @@ struct ib_flow_eth_filter {
19101910
u8 src_mac[6];
19111911
__be16 ether_type;
19121912
__be16 vlan_tag;
1913-
/* Must be last */
1914-
u8 real_sz[];
19151913
};
19161914

19171915
struct ib_flow_spec_eth {
@@ -1924,8 +1922,6 @@ struct ib_flow_spec_eth {
19241922
struct ib_flow_ib_filter {
19251923
__be16 dlid;
19261924
__u8 sl;
1927-
/* Must be last */
1928-
u8 real_sz[];
19291925
};
19301926

19311927
struct ib_flow_spec_ib {
@@ -1949,8 +1945,6 @@ struct ib_flow_ipv4_filter {
19491945
u8 tos;
19501946
u8 ttl;
19511947
u8 flags;
1952-
/* Must be last */
1953-
u8 real_sz[];
19541948
};
19551949

19561950
struct ib_flow_spec_ipv4 {
@@ -1967,9 +1961,7 @@ struct ib_flow_ipv6_filter {
19671961
u8 next_hdr;
19681962
u8 traffic_class;
19691963
u8 hop_limit;
1970-
/* Must be last */
1971-
u8 real_sz[];
1972-
};
1964+
} __packed;
19731965

19741966
struct ib_flow_spec_ipv6 {
19751967
u32 type;
@@ -1981,8 +1973,6 @@ struct ib_flow_spec_ipv6 {
19811973
struct ib_flow_tcp_udp_filter {
19821974
__be16 dst_port;
19831975
__be16 src_port;
1984-
/* Must be last */
1985-
u8 real_sz[];
19861976
};
19871977

19881978
struct ib_flow_spec_tcp_udp {
@@ -1994,7 +1984,6 @@ struct ib_flow_spec_tcp_udp {
19941984

19951985
struct ib_flow_tunnel_filter {
19961986
__be32 tunnel_id;
1997-
u8 real_sz[];
19981987
};
19991988

20001989
/* ib_flow_spec_tunnel describes the Vxlan tunnel
@@ -2010,8 +1999,6 @@ struct ib_flow_spec_tunnel {
20101999
struct ib_flow_esp_filter {
20112000
__be32 spi;
20122001
__be32 seq;
2013-
/* Must be last */
2014-
u8 real_sz[];
20152002
};
20162003

20172004
struct ib_flow_spec_esp {
@@ -2025,8 +2012,6 @@ struct ib_flow_gre_filter {
20252012
__be16 c_ks_res0_ver;
20262013
__be16 protocol;
20272014
__be32 key;
2028-
/* Must be last */
2029-
u8 real_sz[];
20302015
};
20312016

20322017
struct ib_flow_spec_gre {
@@ -2038,8 +2023,6 @@ struct ib_flow_spec_gre {
20382023

20392024
struct ib_flow_mpls_filter {
20402025
__be32 tag;
2041-
/* Must be last */
2042-
u8 real_sz[];
20432026
};
20442027

20452028
struct ib_flow_spec_mpls {

0 commit comments

Comments
 (0)