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

This patch is the userspace fix of the memory misalignment.

It introduces a v1 ABI with the correct alignment and stays
compatible with unfixed revision 0 kernels.

Signed-off-by: Juliana Rodrigueiro <[email protected]>
---
Note to the maintainer:
    Please feel free to adapt the commit message to your liking.

 extensions/libxt_nfacct.c           | 40 ++++++++++++++++++++---------
 include/linux/netfilter/xt_nfacct.h |  5 ++++
 2 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/extensions/libxt_nfacct.c b/extensions/libxt_nfacct.c
index 2ad59d52..d9c0309a 100644
--- a/extensions/libxt_nfacct.c
+++ b/extensions/libxt_nfacct.c
@@ -70,20 +70,36 @@ static void nfacct_save(const void *ip, const struct 
xt_entry_match *match)
        nfacct_print_name(info, "--");
 }
 
-static struct xtables_match nfacct_match = {
-       .family         = NFPROTO_UNSPEC,
-       .name           = "nfacct",
-       .version        = XTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_nfacct_match_info)),
-       .userspacesize  = offsetof(struct xt_nfacct_match_info, nfacct),
-       .help           = nfacct_help,
-       .x6_parse       = nfacct_parse,
-       .print          = nfacct_print,
-       .save           = nfacct_save,
-       .x6_options     = nfacct_opts,
+static struct xtables_match nfacct_matches[] = {
+       {
+               .family         = NFPROTO_UNSPEC,
+               .revision       = 0,
+               .name           = "nfacct",
+               .version        = XTABLES_VERSION,
+               .size           = XT_ALIGN(sizeof(struct xt_nfacct_match_info)),
+               .userspacesize  = offsetof(struct xt_nfacct_match_info, nfacct),
+               .help           = nfacct_help,
+               .x6_parse       = nfacct_parse,
+               .print          = nfacct_print,
+               .save           = nfacct_save,
+               .x6_options     = nfacct_opts,
+       },
+       {
+               .family         = NFPROTO_UNSPEC,
+               .revision       = 1,
+               .name           = "nfacct",
+               .version        = XTABLES_VERSION,
+               .size           = XT_ALIGN(sizeof(struct 
xt_nfacct_match_info_v1)),
+               .userspacesize  = offsetof(struct xt_nfacct_match_info_v1, 
nfacct),
+               .help           = nfacct_help,
+               .x6_parse       = nfacct_parse,
+               .print          = nfacct_print,
+               .save           = nfacct_save,
+               .x6_options     = nfacct_opts,
+       },
 };
 
 void _init(void)
 {
-       xtables_register_match(&nfacct_match);
+       xtables_register_matches(nfacct_matches, ARRAY_SIZE(nfacct_matches));
 }
diff --git a/include/linux/netfilter/xt_nfacct.h 
b/include/linux/netfilter/xt_nfacct.h
index 59ab00dd..04ec2b04 100644
--- a/include/linux/netfilter/xt_nfacct.h
+++ b/include/linux/netfilter/xt_nfacct.h
@@ -14,4 +14,9 @@ struct xt_nfacct_match_info {
        struct nf_acct  *nfacct;
 };
 
+struct xt_nfacct_match_info_v1 {
+       char            name[NFACCT_NAME_MAX];
+       struct nf_acct  *nfacct __attribute__((aligned(8)));
+};
+
 #endif /* _XT_NFACCT_MATCH_H */
-- 
2.20.1




Reply via email to