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

netfilter: xt_nfacct: Fix alignment mismatch in xt_nfacct_match_info

When running a 64-bit kernel with a 32-bit iptables binary, the size of
the xt_nfacct_match_info struct diverges.

kernel: sizeof(struct xt_nfacct_match_info) : 40
iptables: sizeof(struct xt_nfacct_match_info)) : 36

Trying to append nfacct related rules results in an unhelpful message.
Although it is suggested to look for more information in dmesg, nothing
can be found there.

# iptables -A <chain> -m nfacct --nfacct-name <acct-object>
iptables: Invalid argument. Run `dmesg' for more information.

This patch fixes the memory misalignment by enforcing 8-byte alignment
within the struct's first revision. This solution is often used in many
other uapi netfilter headers.

Signed-off-by: Juliana Rodrigueiro <juliana.rodrigueiro@intra2net.com>
Acked-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Juliana Rodrigueiro and committed by
Pablo Neira Ayuso
89a26cd4 14c41586

+30 -11
+5
include/uapi/linux/netfilter/xt_nfacct.h
··· 11 11 struct nf_acct *nfacct; 12 12 }; 13 13 14 + struct xt_nfacct_match_info_v1 { 15 + char name[NFACCT_NAME_MAX]; 16 + struct nf_acct *nfacct __attribute__((aligned(8))); 17 + }; 18 + 14 19 #endif /* _XT_NFACCT_MATCH_H */
+25 -11
net/netfilter/xt_nfacct.c
··· 54 54 nfnl_acct_put(info->nfacct); 55 55 } 56 56 57 - static struct xt_match nfacct_mt_reg __read_mostly = { 58 - .name = "nfacct", 59 - .family = NFPROTO_UNSPEC, 60 - .checkentry = nfacct_mt_checkentry, 61 - .match = nfacct_mt, 62 - .destroy = nfacct_mt_destroy, 63 - .matchsize = sizeof(struct xt_nfacct_match_info), 64 - .usersize = offsetof(struct xt_nfacct_match_info, nfacct), 65 - .me = THIS_MODULE, 57 + static struct xt_match nfacct_mt_reg[] __read_mostly = { 58 + { 59 + .name = "nfacct", 60 + .revision = 0, 61 + .family = NFPROTO_UNSPEC, 62 + .checkentry = nfacct_mt_checkentry, 63 + .match = nfacct_mt, 64 + .destroy = nfacct_mt_destroy, 65 + .matchsize = sizeof(struct xt_nfacct_match_info), 66 + .usersize = offsetof(struct xt_nfacct_match_info, nfacct), 67 + .me = THIS_MODULE, 68 + }, 69 + { 70 + .name = "nfacct", 71 + .revision = 1, 72 + .family = NFPROTO_UNSPEC, 73 + .checkentry = nfacct_mt_checkentry, 74 + .match = nfacct_mt, 75 + .destroy = nfacct_mt_destroy, 76 + .matchsize = sizeof(struct xt_nfacct_match_info_v1), 77 + .usersize = offsetof(struct xt_nfacct_match_info_v1, nfacct), 78 + .me = THIS_MODULE, 79 + }, 66 80 }; 67 81 68 82 static int __init nfacct_mt_init(void) 69 83 { 70 - return xt_register_match(&nfacct_mt_reg); 84 + return xt_register_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg)); 71 85 } 72 86 73 87 static void __exit nfacct_mt_exit(void) 74 88 { 75 - xt_unregister_match(&nfacct_mt_reg); 89 + xt_unregister_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg)); 76 90 } 77 91 78 92 module_init(nfacct_mt_init);