Commit 6daf1414 authored by Gustavo A. R. Silva's avatar Gustavo A. R. Silva Committed by Pablo Neira Ayuso

netfilter: Replace zero-length array with flexible-array member

The current codebase makes use of the zero-length array language
extension to the C90 standard, but the preferred mechanism to declare
variable-length types such as these ones is a flexible array member[1][2],
introduced in C99:

struct foo {
        int stuff;
        struct boo array[];
};

By making use of the mechanism above, we will get a compiler warning
in case the flexible array does not occur last in the structure, which
will help us prevent some kind of undefined behavior bugs from being
inadvertently introduced[3] to the codebase from now on.

Also, notice that, dynamic memory allocations won't be affected by
this change:

"Flexible array members have incomplete type, and so the sizeof operator
may not be applied. As a quirk of the original implementation of
zero-length arrays, sizeof evaluates to zero."[1]

Lastly, fix checkpatch.pl warning
WARNING: __aligned(size) is preferred over __attribute__((aligned(size)))
in net/bridge/netfilter/ebtables.c

This issue was found with the help of Coccinelle.

[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] https://github.com/KSPP/linux/issues/21
[3] commit 76497732 ("cxgb3/l2t: Fix undefined behaviour")
Signed-off-by: default avatarGustavo A. R. Silva <gustavo@embeddedor.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent eb9d7af3
...@@ -98,7 +98,7 @@ struct ip_set_counter { ...@@ -98,7 +98,7 @@ struct ip_set_counter {
struct ip_set_comment_rcu { struct ip_set_comment_rcu {
struct rcu_head rcu; struct rcu_head rcu;
char str[0]; char str[];
}; };
struct ip_set_comment { struct ip_set_comment {
......
...@@ -264,7 +264,7 @@ struct xt_table_info { ...@@ -264,7 +264,7 @@ struct xt_table_info {
unsigned int stacksize; unsigned int stacksize;
void ***jumpstack; void ***jumpstack;
unsigned char entries[0] __aligned(8); unsigned char entries[] __aligned(8);
}; };
int xt_register_target(struct xt_target *target); int xt_register_target(struct xt_target *target);
...@@ -464,7 +464,7 @@ struct compat_xt_entry_match { ...@@ -464,7 +464,7 @@ struct compat_xt_entry_match {
} kernel; } kernel;
u_int16_t match_size; u_int16_t match_size;
} u; } u;
unsigned char data[0]; unsigned char data[];
}; };
struct compat_xt_entry_target { struct compat_xt_entry_target {
...@@ -480,7 +480,7 @@ struct compat_xt_entry_target { ...@@ -480,7 +480,7 @@ struct compat_xt_entry_target {
} kernel; } kernel;
u_int16_t target_size; u_int16_t target_size;
} u; } u;
unsigned char data[0]; unsigned char data[];
}; };
/* FIXME: this works only on 32 bit tasks /* FIXME: this works only on 32 bit tasks
...@@ -494,7 +494,7 @@ struct compat_xt_counters { ...@@ -494,7 +494,7 @@ struct compat_xt_counters {
struct compat_xt_counters_info { struct compat_xt_counters_info {
char name[XT_TABLE_MAXNAMELEN]; char name[XT_TABLE_MAXNAMELEN];
compat_uint_t num_counters; compat_uint_t num_counters;
struct compat_xt_counters counters[0]; struct compat_xt_counters counters[];
}; };
struct _compat_xt_align { struct _compat_xt_align {
......
...@@ -67,7 +67,7 @@ struct compat_arpt_entry { ...@@ -67,7 +67,7 @@ struct compat_arpt_entry {
__u16 next_offset; __u16 next_offset;
compat_uint_t comefrom; compat_uint_t comefrom;
struct compat_xt_counters counters; struct compat_xt_counters counters;
unsigned char elems[0]; unsigned char elems[];
}; };
static inline struct xt_entry_target * static inline struct xt_entry_target *
......
...@@ -85,7 +85,7 @@ struct ebt_table_info { ...@@ -85,7 +85,7 @@ struct ebt_table_info {
/* room to maintain the stack used for jumping from and into udc */ /* room to maintain the stack used for jumping from and into udc */
struct ebt_chainstack **chainstack; struct ebt_chainstack **chainstack;
char *entries; char *entries;
struct ebt_counter counters[0] ____cacheline_aligned; struct ebt_counter counters[] ____cacheline_aligned;
}; };
struct ebt_table { struct ebt_table {
......
...@@ -76,7 +76,7 @@ struct compat_ipt_entry { ...@@ -76,7 +76,7 @@ struct compat_ipt_entry {
__u16 next_offset; __u16 next_offset;
compat_uint_t comefrom; compat_uint_t comefrom;
struct compat_xt_counters counters; struct compat_xt_counters counters;
unsigned char elems[0]; unsigned char elems[];
}; };
/* Helper functions */ /* Helper functions */
......
...@@ -43,7 +43,7 @@ struct compat_ip6t_entry { ...@@ -43,7 +43,7 @@ struct compat_ip6t_entry {
__u16 next_offset; __u16 next_offset;
compat_uint_t comefrom; compat_uint_t comefrom;
struct compat_xt_counters counters; struct compat_xt_counters counters;
unsigned char elems[0]; unsigned char elems[];
}; };
static inline struct xt_entry_target * static inline struct xt_entry_target *
......
...@@ -45,7 +45,7 @@ enum nf_ct_ext_id { ...@@ -45,7 +45,7 @@ enum nf_ct_ext_id {
struct nf_ct_ext { struct nf_ct_ext {
u8 offset[NF_CT_EXT_NUM]; u8 offset[NF_CT_EXT_NUM];
u8 len; u8 len;
char data[0]; char data[];
}; };
static inline bool __nf_ct_ext_exist(const struct nf_ct_ext *ext, u8 id) static inline bool __nf_ct_ext_exist(const struct nf_ct_ext *ext, u8 id)
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
struct nf_ct_timeout { struct nf_ct_timeout {
__u16 l3num; __u16 l3num;
const struct nf_conntrack_l4proto *l4proto; const struct nf_conntrack_l4proto *l4proto;
char data[0]; char data[];
}; };
struct ctnl_timeout { struct ctnl_timeout {
......
...@@ -224,7 +224,7 @@ int nft_validate_register_store(const struct nft_ctx *ctx, ...@@ -224,7 +224,7 @@ int nft_validate_register_store(const struct nft_ctx *ctx,
*/ */
struct nft_userdata { struct nft_userdata {
u8 len; u8 len;
unsigned char data[0]; unsigned char data[];
}; };
/** /**
...@@ -565,7 +565,7 @@ struct nft_set_ext_tmpl { ...@@ -565,7 +565,7 @@ struct nft_set_ext_tmpl {
struct nft_set_ext { struct nft_set_ext {
u8 genmask; u8 genmask;
u8 offset[NFT_SET_EXT_NUM]; u8 offset[NFT_SET_EXT_NUM];
char data[0]; char data[];
}; };
static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl) static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl)
...@@ -1375,7 +1375,7 @@ struct nft_trans { ...@@ -1375,7 +1375,7 @@ struct nft_trans {
int msg_type; int msg_type;
bool put_net; bool put_net;
struct nft_ctx ctx; struct nft_ctx ctx;
char data[0]; char data[];
}; };
struct nft_trans_rule { struct nft_trans_rule {
......
...@@ -40,7 +40,7 @@ struct ebt_mac_wormhash_tuple { ...@@ -40,7 +40,7 @@ struct ebt_mac_wormhash_tuple {
struct ebt_mac_wormhash { struct ebt_mac_wormhash {
int table[257]; int table[257];
int poolsize; int poolsize;
struct ebt_mac_wormhash_tuple pool[0]; struct ebt_mac_wormhash_tuple pool[];
}; };
#define ebt_mac_wormhash_size(x) ((x) ? sizeof(struct ebt_mac_wormhash) \ #define ebt_mac_wormhash_size(x) ((x) ? sizeof(struct ebt_mac_wormhash) \
......
...@@ -1561,7 +1561,7 @@ struct compat_ebt_entry_mwt { ...@@ -1561,7 +1561,7 @@ struct compat_ebt_entry_mwt {
compat_uptr_t ptr; compat_uptr_t ptr;
} u; } u;
compat_uint_t match_size; compat_uint_t match_size;
compat_uint_t data[0] __attribute__ ((aligned (__alignof__(struct compat_ebt_replace)))); compat_uint_t data[] __aligned(__alignof__(struct compat_ebt_replace));
}; };
/* account for possible padding between match_size and ->data */ /* account for possible padding between match_size and ->data */
......
...@@ -1057,7 +1057,7 @@ struct compat_arpt_replace { ...@@ -1057,7 +1057,7 @@ struct compat_arpt_replace {
u32 underflow[NF_ARP_NUMHOOKS]; u32 underflow[NF_ARP_NUMHOOKS];
u32 num_counters; u32 num_counters;
compat_uptr_t counters; compat_uptr_t counters;
struct compat_arpt_entry entries[0]; struct compat_arpt_entry entries[];
}; };
static inline void compat_release_entry(struct compat_arpt_entry *e) static inline void compat_release_entry(struct compat_arpt_entry *e)
...@@ -1383,7 +1383,7 @@ static int compat_copy_entries_to_user(unsigned int total_size, ...@@ -1383,7 +1383,7 @@ static int compat_copy_entries_to_user(unsigned int total_size,
struct compat_arpt_get_entries { struct compat_arpt_get_entries {
char name[XT_TABLE_MAXNAMELEN]; char name[XT_TABLE_MAXNAMELEN];
compat_uint_t size; compat_uint_t size;
struct compat_arpt_entry entrytable[0]; struct compat_arpt_entry entrytable[];
}; };
static int compat_get_entries(struct net *net, static int compat_get_entries(struct net *net,
......
...@@ -1211,7 +1211,7 @@ struct compat_ipt_replace { ...@@ -1211,7 +1211,7 @@ struct compat_ipt_replace {
u32 underflow[NF_INET_NUMHOOKS]; u32 underflow[NF_INET_NUMHOOKS];
u32 num_counters; u32 num_counters;
compat_uptr_t counters; /* struct xt_counters * */ compat_uptr_t counters; /* struct xt_counters * */
struct compat_ipt_entry entries[0]; struct compat_ipt_entry entries[];
}; };
static int static int
...@@ -1562,7 +1562,7 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user, ...@@ -1562,7 +1562,7 @@ compat_do_ipt_set_ctl(struct sock *sk, int cmd, void __user *user,
struct compat_ipt_get_entries { struct compat_ipt_get_entries {
char name[XT_TABLE_MAXNAMELEN]; char name[XT_TABLE_MAXNAMELEN];
compat_uint_t size; compat_uint_t size;
struct compat_ipt_entry entrytable[0]; struct compat_ipt_entry entrytable[];
}; };
static int static int
......
...@@ -1227,7 +1227,7 @@ struct compat_ip6t_replace { ...@@ -1227,7 +1227,7 @@ struct compat_ip6t_replace {
u32 underflow[NF_INET_NUMHOOKS]; u32 underflow[NF_INET_NUMHOOKS];
u32 num_counters; u32 num_counters;
compat_uptr_t counters; /* struct xt_counters * */ compat_uptr_t counters; /* struct xt_counters * */
struct compat_ip6t_entry entries[0]; struct compat_ip6t_entry entries[];
}; };
static int static int
...@@ -1571,7 +1571,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user, ...@@ -1571,7 +1571,7 @@ compat_do_ip6t_set_ctl(struct sock *sk, int cmd, void __user *user,
struct compat_ip6t_get_entries { struct compat_ip6t_get_entries {
char name[XT_TABLE_MAXNAMELEN]; char name[XT_TABLE_MAXNAMELEN];
compat_uint_t size; compat_uint_t size;
struct compat_ip6t_entry entrytable[0]; struct compat_ip6t_entry entrytable[];
}; };
static int static int
......
...@@ -46,7 +46,7 @@ struct bitmap_ip { ...@@ -46,7 +46,7 @@ struct bitmap_ip {
u8 netmask; /* subnet netmask */ u8 netmask; /* subnet netmask */
struct timer_list gc; /* garbage collection */ struct timer_list gc; /* garbage collection */
struct ip_set *set; /* attached to this ip_set */ struct ip_set *set; /* attached to this ip_set */
unsigned char extensions[0] /* data extensions */ unsigned char extensions[] /* data extensions */
__aligned(__alignof__(u64)); __aligned(__alignof__(u64));
}; };
......
...@@ -49,7 +49,7 @@ struct bitmap_ipmac { ...@@ -49,7 +49,7 @@ struct bitmap_ipmac {
size_t memsize; /* members size */ size_t memsize; /* members size */
struct timer_list gc; /* garbage collector */ struct timer_list gc; /* garbage collector */
struct ip_set *set; /* attached to this ip_set */ struct ip_set *set; /* attached to this ip_set */
unsigned char extensions[0] /* MAC + data extensions */ unsigned char extensions[] /* MAC + data extensions */
__aligned(__alignof__(u64)); __aligned(__alignof__(u64));
}; };
......
...@@ -37,7 +37,7 @@ struct bitmap_port { ...@@ -37,7 +37,7 @@ struct bitmap_port {
size_t memsize; /* members size */ size_t memsize; /* members size */
struct timer_list gc; /* garbage collection */ struct timer_list gc; /* garbage collection */
struct ip_set *set; /* attached to this ip_set */ struct ip_set *set; /* attached to this ip_set */
unsigned char extensions[0] /* data extensions */ unsigned char extensions[] /* data extensions */
__aligned(__alignof__(u64)); __aligned(__alignof__(u64));
}; };
......
...@@ -76,7 +76,7 @@ struct hbucket { ...@@ -76,7 +76,7 @@ struct hbucket {
DECLARE_BITMAP(used, AHASH_MAX_TUNED); DECLARE_BITMAP(used, AHASH_MAX_TUNED);
u8 size; /* size of the array */ u8 size; /* size of the array */
u8 pos; /* position of the first free entry */ u8 pos; /* position of the first free entry */
unsigned char value[0] /* the array of the values */ unsigned char value[] /* the array of the values */
__aligned(__alignof__(u64)); __aligned(__alignof__(u64));
}; };
...@@ -109,7 +109,7 @@ struct htable { ...@@ -109,7 +109,7 @@ struct htable {
u8 htable_bits; /* size of hash table == 2^htable_bits */ u8 htable_bits; /* size of hash table == 2^htable_bits */
u32 maxelem; /* Maxelem per region */ u32 maxelem; /* Maxelem per region */
struct ip_set_region *hregion; /* Region locks and ext sizes */ struct ip_set_region *hregion; /* Region locks and ext sizes */
struct hbucket __rcu *bucket[0]; /* hashtable buckets */ struct hbucket __rcu *bucket[]; /* hashtable buckets */
}; };
#define hbucket(h, i) ((h)->bucket[i]) #define hbucket(h, i) ((h)->bucket[i])
......
...@@ -33,7 +33,7 @@ struct nf_acct { ...@@ -33,7 +33,7 @@ struct nf_acct {
refcount_t refcnt; refcount_t refcnt;
char name[NFACCT_NAME_MAX]; char name[NFACCT_NAME_MAX];
struct rcu_head rcu_head; struct rcu_head rcu_head;
char data[0]; char data[];
}; };
struct nfacct_filter { struct nfacct_filter {
......
...@@ -433,7 +433,7 @@ struct nft_pipapo_match { ...@@ -433,7 +433,7 @@ struct nft_pipapo_match {
unsigned long * __percpu *scratch; unsigned long * __percpu *scratch;
size_t bsize_max; size_t bsize_max;
struct rcu_head rcu; struct rcu_head rcu;
struct nft_pipapo_field f[0]; struct nft_pipapo_field f[];
}; };
/* Current working bitmap index, toggled between field matches */ /* Current working bitmap index, toggled between field matches */
......
...@@ -132,7 +132,7 @@ struct xt_hashlimit_htable { ...@@ -132,7 +132,7 @@ struct xt_hashlimit_htable {
const char *name; const char *name;
struct net *net; struct net *net;
struct hlist_head hash[0]; /* hashtable itself */ struct hlist_head hash[]; /* hashtable itself */
}; };
static int static int
......
...@@ -71,7 +71,7 @@ struct recent_entry { ...@@ -71,7 +71,7 @@ struct recent_entry {
u_int8_t ttl; u_int8_t ttl;
u_int8_t index; u_int8_t index;
u_int16_t nstamps; u_int16_t nstamps;
unsigned long stamps[0]; unsigned long stamps[];
}; };
struct recent_table { struct recent_table {
...@@ -82,7 +82,7 @@ struct recent_table { ...@@ -82,7 +82,7 @@ struct recent_table {
unsigned int entries; unsigned int entries;
u8 nstamps_max_mask; u8 nstamps_max_mask;
struct list_head lru_list; struct list_head lru_list;
struct list_head iphash[0]; struct list_head iphash[];
}; };
struct recent_net { struct recent_net {
......
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