Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipv4/inet_sock.h: Avoid thousands of -Wflex-array-member-not-at-end warnings

Use DEFINE_RAW_FLEX() to avoid thousands of -Wflex-array-member-not-at-end
warnings.

Remove struct ip_options_data, and adjust the rest of the code so that
flexible-array member struct ip_options_rcu::opt.__data[] ends last
in struct icmp_bxm.

Compensate for this by using the DEFINE_RAW_FLEX() helper to define each
on-stack struct instance that contained struct ip_options_data as a member,
and to define struct ip_options_rcu with a fixed on-stack size for its
nested flexible-array member opt.__data[].

Also, add a couple of code comments to prevent people from adding members
to a struct after another member that contains a flexible array.

With these changes, fix 2600 warnings of the following type:

include/net/inet_sock.h:65:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]

Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Link: https://patch.msgid.link/aVteBadWA6AbTp7X@kspp
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Gustavo A. R. Silva and committed by
Jakub Kicinski
c86af46b 915a5f60

+79 -68
+4 -5
include/net/inet_sock.h
··· 26 26 #include <net/tcp_states.h> 27 27 #include <net/l3mdev.h> 28 28 29 + #define IP_OPTIONS_DATA_FIXED_SIZE 40 30 + 29 31 /** struct ip_options - IP Options 30 32 * 31 33 * @faddr - Saved first hop address ··· 60 58 61 59 struct ip_options_rcu { 62 60 struct rcu_head rcu; 63 - struct ip_options opt; 64 - }; 65 61 66 - struct ip_options_data { 67 - struct ip_options_rcu opt; 68 - char data[40]; 62 + /* Must be last as it ends in a flexible-array member. */ 63 + struct ip_options opt; 69 64 }; 70 65 71 66 struct inet_request_sock {
+56 -48
net/ipv4/icmp.c
··· 112 112 __be32 times[3]; 113 113 } data; 114 114 int head_len; 115 - struct ip_options_data replyopts; 115 + 116 + /* Must be last as it ends in a flexible-array member. */ 117 + struct ip_options_rcu replyopts; 116 118 }; 117 119 118 120 /* An array of errno for error messages from dest unreach. */ ··· 355 353 static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, 356 354 struct sk_buff *skb) 357 355 { 358 - struct icmp_bxm *icmp_param = from; 356 + DEFINE_RAW_FLEX(struct icmp_bxm, icmp_param, replyopts.opt.__data, 357 + IP_OPTIONS_DATA_FIXED_SIZE); 359 358 __wsum csum; 359 + 360 + icmp_param = from; 360 361 361 362 csum = skb_copy_and_csum_bits(icmp_param->skb, 362 363 icmp_param->offset + offset, ··· 418 413 int type = icmp_param->data.icmph.type; 419 414 int code = icmp_param->data.icmph.code; 420 415 421 - if (ip_options_echo(net, &icmp_param->replyopts.opt.opt, skb)) 416 + if (ip_options_echo(net, &icmp_param->replyopts.opt, skb)) 422 417 return; 423 418 424 419 /* Needed by both icmpv4_global_allow and icmp_xmit_lock */ ··· 440 435 daddr = ipc.addr = ip_hdr(skb)->saddr; 441 436 saddr = fib_compute_spec_dst(skb); 442 437 443 - if (icmp_param->replyopts.opt.opt.optlen) { 444 - ipc.opt = &icmp_param->replyopts.opt; 438 + if (icmp_param->replyopts.opt.optlen) { 439 + ipc.opt = &icmp_param->replyopts; 445 440 if (ipc.opt->opt.srr) 446 - daddr = icmp_param->replyopts.opt.opt.faddr; 441 + daddr = icmp_param->replyopts.opt.faddr; 447 442 } 448 443 memset(&fl4, 0, sizeof(fl4)); 449 444 fl4.daddr = daddr; ··· 496 491 int err; 497 492 498 493 memset(fl4, 0, sizeof(*fl4)); 499 - fl4->daddr = (param->replyopts.opt.opt.srr ? 500 - param->replyopts.opt.opt.faddr : iph->saddr); 494 + fl4->daddr = (param->replyopts.opt.srr ? 495 + param->replyopts.opt.faddr : iph->saddr); 501 496 fl4->saddr = saddr; 502 497 fl4->flowi4_mark = mark; 503 498 fl4->flowi4_uid = sock_net_uid(net, NULL); ··· 780 775 void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, 781 776 const struct inet_skb_parm *parm) 782 777 { 778 + DEFINE_RAW_FLEX(struct icmp_bxm, icmp_param, replyopts.opt.__data, 779 + IP_OPTIONS_DATA_FIXED_SIZE); 783 780 struct iphdr *iph; 784 781 int room; 785 - struct icmp_bxm icmp_param; 786 782 struct rtable *rt = skb_rtable(skb_in); 787 783 bool apply_ratelimit = false; 788 784 struct sk_buff *ext_skb; ··· 912 906 iph->tos; 913 907 mark = IP4_REPLY_MARK(net, skb_in->mark); 914 908 915 - if (__ip_options_echo(net, &icmp_param.replyopts.opt.opt, skb_in, 909 + if (__ip_options_echo(net, &icmp_param->replyopts.opt, skb_in, 916 910 &parm->opt)) 917 911 goto out_unlock; 918 912 ··· 921 915 * Prepare data for ICMP header. 922 916 */ 923 917 924 - icmp_param.data.icmph.type = type; 925 - icmp_param.data.icmph.code = code; 926 - icmp_param.data.icmph.un.gateway = info; 927 - icmp_param.data.icmph.checksum = 0; 928 - icmp_param.skb = skb_in; 929 - icmp_param.offset = skb_network_offset(skb_in); 918 + icmp_param->data.icmph.type = type; 919 + icmp_param->data.icmph.code = code; 920 + icmp_param->data.icmph.un.gateway = info; 921 + icmp_param->data.icmph.checksum = 0; 922 + icmp_param->skb = skb_in; 923 + icmp_param->offset = skb_network_offset(skb_in); 930 924 ipcm_init(&ipc); 931 925 ipc.tos = tos; 932 926 ipc.addr = iph->saddr; 933 - ipc.opt = &icmp_param.replyopts.opt; 927 + ipc.opt = &icmp_param->replyopts; 934 928 ipc.sockc.mark = mark; 935 929 936 930 rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, 937 931 inet_dsfield_to_dscp(tos), mark, type, code, 938 - &icmp_param); 932 + icmp_param); 939 933 if (IS_ERR(rt)) 940 934 goto out_unlock; 941 935 ··· 948 942 room = dst_mtu(&rt->dst); 949 943 if (room > 576) 950 944 room = 576; 951 - room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen; 945 + room -= sizeof(struct iphdr) + icmp_param->replyopts.opt.optlen; 952 946 room -= sizeof(struct icmphdr); 953 947 /* Guard against tiny mtu. We need to include at least one 954 948 * IP network header for this message to make any sense. ··· 956 950 if (room <= (int)sizeof(struct iphdr)) 957 951 goto ende; 958 952 959 - ext_skb = icmp_ext_append(net, skb_in, &icmp_param.data.icmph, room, 953 + ext_skb = icmp_ext_append(net, skb_in, &icmp_param->data.icmph, room, 960 954 parm->iif); 961 955 if (ext_skb) 962 - icmp_param.skb = ext_skb; 956 + icmp_param->skb = ext_skb; 963 957 964 - icmp_param.data_len = icmp_param.skb->len - icmp_param.offset; 965 - if (icmp_param.data_len > room) 966 - icmp_param.data_len = room; 967 - icmp_param.head_len = sizeof(struct icmphdr); 958 + icmp_param->data_len = icmp_param->skb->len - icmp_param->offset; 959 + if (icmp_param->data_len > room) 960 + icmp_param->data_len = room; 961 + icmp_param->head_len = sizeof(struct icmphdr); 968 962 969 963 /* if we don't have a source address at this point, fall back to the 970 964 * dummy address instead of sending out a packet with a source address ··· 975 969 976 970 trace_icmp_send(skb_in, type, code); 977 971 978 - icmp_push_reply(sk, &icmp_param, &fl4, &ipc, &rt); 972 + icmp_push_reply(sk, icmp_param, &fl4, &ipc, &rt); 979 973 980 974 if (ext_skb) 981 975 consume_skb(ext_skb); ··· 1212 1206 1213 1207 static enum skb_drop_reason icmp_echo(struct sk_buff *skb) 1214 1208 { 1215 - struct icmp_bxm icmp_param; 1209 + DEFINE_RAW_FLEX(struct icmp_bxm, icmp_param, replyopts.opt.__data, 1210 + IP_OPTIONS_DATA_FIXED_SIZE); 1216 1211 struct net *net; 1217 1212 1218 1213 net = skb_dst_dev_net_rcu(skb); ··· 1221 1214 if (READ_ONCE(net->ipv4.sysctl_icmp_echo_ignore_all)) 1222 1215 return SKB_NOT_DROPPED_YET; 1223 1216 1224 - icmp_param.data.icmph = *icmp_hdr(skb); 1225 - icmp_param.skb = skb; 1226 - icmp_param.offset = 0; 1227 - icmp_param.data_len = skb->len; 1228 - icmp_param.head_len = sizeof(struct icmphdr); 1217 + icmp_param->data.icmph = *icmp_hdr(skb); 1218 + icmp_param->skb = skb; 1219 + icmp_param->offset = 0; 1220 + icmp_param->data_len = skb->len; 1221 + icmp_param->head_len = sizeof(struct icmphdr); 1229 1222 1230 - if (icmp_param.data.icmph.type == ICMP_ECHO) 1231 - icmp_param.data.icmph.type = ICMP_ECHOREPLY; 1232 - else if (!icmp_build_probe(skb, &icmp_param.data.icmph)) 1223 + if (icmp_param->data.icmph.type == ICMP_ECHO) 1224 + icmp_param->data.icmph.type = ICMP_ECHOREPLY; 1225 + else if (!icmp_build_probe(skb, &icmp_param->data.icmph)) 1233 1226 return SKB_NOT_DROPPED_YET; 1234 1227 1235 - icmp_reply(&icmp_param, skb); 1228 + icmp_reply(icmp_param, skb); 1236 1229 return SKB_NOT_DROPPED_YET; 1237 1230 } 1238 1231 ··· 1360 1353 */ 1361 1354 static enum skb_drop_reason icmp_timestamp(struct sk_buff *skb) 1362 1355 { 1363 - struct icmp_bxm icmp_param; 1356 + DEFINE_RAW_FLEX(struct icmp_bxm, icmp_param, replyopts.opt.__data, 1357 + IP_OPTIONS_DATA_FIXED_SIZE); 1364 1358 /* 1365 1359 * Too short. 1366 1360 */ ··· 1371 1363 /* 1372 1364 * Fill in the current time as ms since midnight UT: 1373 1365 */ 1374 - icmp_param.data.times[1] = inet_current_timestamp(); 1375 - icmp_param.data.times[2] = icmp_param.data.times[1]; 1366 + icmp_param->data.times[1] = inet_current_timestamp(); 1367 + icmp_param->data.times[2] = icmp_param->data.times[1]; 1376 1368 1377 - BUG_ON(skb_copy_bits(skb, 0, &icmp_param.data.times[0], 4)); 1369 + BUG_ON(skb_copy_bits(skb, 0, &icmp_param->data.times[0], 4)); 1378 1370 1379 - icmp_param.data.icmph = *icmp_hdr(skb); 1380 - icmp_param.data.icmph.type = ICMP_TIMESTAMPREPLY; 1381 - icmp_param.data.icmph.code = 0; 1382 - icmp_param.skb = skb; 1383 - icmp_param.offset = 0; 1384 - icmp_param.data_len = 0; 1385 - icmp_param.head_len = sizeof(struct icmphdr) + 12; 1386 - icmp_reply(&icmp_param, skb); 1371 + icmp_param->data.icmph = *icmp_hdr(skb); 1372 + icmp_param->data.icmph.type = ICMP_TIMESTAMPREPLY; 1373 + icmp_param->data.icmph.code = 0; 1374 + icmp_param->skb = skb; 1375 + icmp_param->offset = 0; 1376 + icmp_param->data_len = 0; 1377 + icmp_param->head_len = sizeof(struct icmphdr) + 12; 1378 + icmp_reply(icmp_param, skb); 1387 1379 return SKB_NOT_DROPPED_YET; 1388 1380 1389 1381 out_err:
+7 -6
net/ipv4/ip_output.c
··· 1606 1606 const struct ip_reply_arg *arg, 1607 1607 unsigned int len, u64 transmit_time, u32 txhash) 1608 1608 { 1609 - struct ip_options_data replyopts; 1609 + DEFINE_RAW_FLEX(struct ip_options_rcu, replyopts, opt.__data, 1610 + IP_OPTIONS_DATA_FIXED_SIZE); 1610 1611 struct ipcm_cookie ipc; 1611 1612 struct flowi4 fl4; 1612 1613 struct rtable *rt = skb_rtable(skb); ··· 1616 1615 int err; 1617 1616 int oif; 1618 1617 1619 - if (__ip_options_echo(net, &replyopts.opt.opt, skb, sopt)) 1618 + if (__ip_options_echo(net, &replyopts->opt, skb, sopt)) 1620 1619 return; 1621 1620 1622 1621 ipcm_init(&ipc); 1623 1622 ipc.addr = daddr; 1624 1623 ipc.sockc.transmit_time = transmit_time; 1625 1624 1626 - if (replyopts.opt.opt.optlen) { 1627 - ipc.opt = &replyopts.opt; 1625 + if (replyopts->opt.optlen) { 1626 + ipc.opt = replyopts; 1628 1627 1629 - if (replyopts.opt.opt.srr) 1630 - daddr = replyopts.opt.opt.faddr; 1628 + if (replyopts->opt.srr) 1629 + daddr = replyopts->opt.faddr; 1631 1630 } 1632 1631 1633 1632 oif = arg->bound_dev_if;
+4 -3
net/ipv4/ping.c
··· 690 690 691 691 static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) 692 692 { 693 + DEFINE_RAW_FLEX(struct ip_options_rcu, opt_copy, opt.__data, 694 + IP_OPTIONS_DATA_FIXED_SIZE); 693 695 struct net *net = sock_net(sk); 694 696 struct flowi4 fl4; 695 697 struct inet_sock *inet = inet_sk(sk); ··· 699 697 struct icmphdr user_icmph; 700 698 struct pingfakehdr pfh; 701 699 struct rtable *rt = NULL; 702 - struct ip_options_data opt_copy; 703 700 int free = 0; 704 701 __be32 saddr, daddr, faddr; 705 702 u8 scope; ··· 747 746 rcu_read_lock(); 748 747 inet_opt = rcu_dereference(inet->inet_opt); 749 748 if (inet_opt) { 750 - memcpy(&opt_copy, inet_opt, 749 + memcpy(opt_copy, inet_opt, 751 750 sizeof(*inet_opt) + inet_opt->opt.optlen); 752 - ipc.opt = &opt_copy.opt; 751 + ipc.opt = opt_copy; 753 752 } 754 753 rcu_read_unlock(); 755 754 }
+4 -3
net/ipv4/raw.c
··· 481 481 482 482 static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) 483 483 { 484 + DEFINE_RAW_FLEX(struct ip_options_rcu, opt_copy, opt.__data, 485 + IP_OPTIONS_DATA_FIXED_SIZE); 484 486 struct inet_sock *inet = inet_sk(sk); 485 487 struct net *net = sock_net(sk); 486 488 struct ipcm_cookie ipc; ··· 493 491 __be32 daddr; 494 492 __be32 saddr; 495 493 int uc_index, err; 496 - struct ip_options_data opt_copy; 497 494 struct raw_frag_vec rfv; 498 495 int hdrincl; 499 496 ··· 562 561 rcu_read_lock(); 563 562 inet_opt = rcu_dereference(inet->inet_opt); 564 563 if (inet_opt) { 565 - memcpy(&opt_copy, inet_opt, 564 + memcpy(opt_copy, inet_opt, 566 565 sizeof(*inet_opt) + inet_opt->opt.optlen); 567 - ipc.opt = &opt_copy.opt; 566 + ipc.opt = opt_copy; 568 567 } 569 568 rcu_read_unlock(); 570 569 }
+4 -3
net/ipv4/udp.c
··· 1269 1269 1270 1270 int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) 1271 1271 { 1272 + DEFINE_RAW_FLEX(struct ip_options_rcu, opt_copy, opt.__data, 1273 + IP_OPTIONS_DATA_FIXED_SIZE); 1272 1274 struct inet_sock *inet = inet_sk(sk); 1273 1275 struct udp_sock *up = udp_sk(sk); 1274 1276 DECLARE_SOCKADDR(struct sockaddr_in *, usin, msg->msg_name); ··· 1288 1286 int corkreq = udp_test_bit(CORK, sk) || msg->msg_flags & MSG_MORE; 1289 1287 int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); 1290 1288 struct sk_buff *skb; 1291 - struct ip_options_data opt_copy; 1292 1289 int uc_index; 1293 1290 1294 1291 if (len > 0xFFFF) ··· 1369 1368 rcu_read_lock(); 1370 1369 inet_opt = rcu_dereference(inet->inet_opt); 1371 1370 if (inet_opt) { 1372 - memcpy(&opt_copy, inet_opt, 1371 + memcpy(opt_copy, inet_opt, 1373 1372 sizeof(*inet_opt) + inet_opt->opt.optlen); 1374 - ipc.opt = &opt_copy.opt; 1373 + ipc.opt = opt_copy; 1375 1374 } 1376 1375 rcu_read_unlock(); 1377 1376 }