This patch will translate userspace requests in compat format to the normalized format. Testable with e.g. `ip6tables -t filter2 -A INPUT -m limit --limit 1/s`, which will submit a struct xt_entry_match with size 0x3C, and retrieving the ruleset will show that it has been translated into a struct xt_entry_match with the size field containing 0x48. Signed-off-by: Jan Engelhardt <jengelh@xxxxxxxxxx> --- include/linux/netfilter/x_tables.h | 4 ++ net/ipv6/netfilter/ip6_tables.c | 1 + net/netfilter/xt1_support.c | 57 ++++++++++++++++++++++++++++++++++++ net/netfilter/xt1_translat.c | 9 +++++- 4 files changed, 70 insertions(+), 1 deletions(-) diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h index 7e88120..7695750 100644 --- a/include/linux/netfilter/x_tables.h +++ b/include/linux/netfilter/x_tables.h @@ -733,6 +733,10 @@ extern int xts_table_replace(void __user *, unsigned int, struct net *, struct xt2_table *); extern int xts_get_counters(struct xt2_table *, const struct xt_counters __user *, unsigned int); +#ifdef CONFIG_COMPAT +extern int xts_rule_add_cmatch(struct xt2_rule *, + const struct xt_entry_match *); +#endif extern struct xt2_rule *xt2_rule_new(struct xt2_chain *); extern int xt2_rule_add_match(struct xt2_rule *, const char *, uint8_t, diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index b7901e3..b0f04c7 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -83,6 +83,7 @@ do { \ #undef xtsub_replace #ifdef CONFIG_COMPAT +#define XTSUB_DO_COMPAT #define xtsub_entry compat_ip6t_entry #define xtsub_replace compat_ip6t_replace #define XTSUB2(x) ip6t2_compat_ ## x diff --git a/net/netfilter/xt1_support.c b/net/netfilter/xt1_support.c index 380c3da..4508f7d 100644 --- a/net/netfilter/xt1_support.c +++ b/net/netfilter/xt1_support.c @@ -384,4 +384,61 @@ int xts_get_counters(struct xt2_table *table, } EXPORT_SYMBOL_GPL(xts_get_counters); +#ifdef CONFIG_COMPAT +int xts_rule_add_cmatch(struct xt2_rule *rule, const struct xt_entry_match *m) +{ + const uint8_t nfproto = rule->chain->table->nfproto; + const struct xt_match *ext; + unsigned int dsize, required; + void *data; + int ret; + + ext = try_then_request_module(xt_find_match(nfproto, + m->u.user.name, m->u.user.revision), + "%st_%s", xt_prefix[nfproto], m->u.user.name); + if (ext == NULL) + return -ENOENT; + if (IS_ERR(ext)) + return PTR_ERR(ext); + + dsize = m->u.match_size - sizeof(*m); + if ((ext->compatsize == 0 && dsize == XT_ALIGN(ext->matchsize)) || + ext->matchsize == -1) { + /* + * If extension does not have special ->compat_* functions and + * is already padded, proceed. + * ebt_among uses the -1 special case. + */ + ret = xt2_rule_add_oldmatch(rule, m); + goto put_module; + } + required = (ext->compatsize == 0) ? ext->matchsize : ext->compatsize; + if (dsize != COMPAT_XT_ALIGN(required)) { + pr_err("%s_tables: %s.%u match: invalid size " + "(expected) %u != (given by user) %u\n", + xt_prefix[rule->chain->table->nfproto], + ext->name, ext->revision, required, dsize); + ret = -EINVAL; + goto put_module; + } + + data = kzalloc(XT_ALIGN(ext->matchsize), GFP_KERNEL); + if (data == NULL) { + ret = -ENOMEM; + goto put_module; + } + if (ext->compat_from_user == NULL) + memcpy(data, m->data, dsize); + else + ext->compat_from_user(data, m->data); + ret = xt2_rule_add_match(rule, m->u.user.name, m->u.user.revision, + data, XT_ALIGN(ext->matchsize), true); + kfree(data); + put_module: + module_put(ext->me); + return ret; +} +EXPORT_SYMBOL_GPL(xts_rule_add_cmatch); +#endif + MODULE_LICENSE("GPL"); diff --git a/net/netfilter/xt1_translat.c b/net/netfilter/xt1_translat.c index 7719d8b..c7c570e 100644 --- a/net/netfilter/xt1_translat.c +++ b/net/netfilter/xt1_translat.c @@ -16,6 +16,11 @@ #if !defined(XTSUB_NFPROTO_IPV6) # error Need to define XTSUB_NFPROTO_xxx. #endif +#ifdef XTSUB_DO_COMPAT +# define xtsub_rule_add_match xts_rule_add_cmatch +#else +# define xtsub_rule_add_match xt2_rule_add_oldmatch +#endif #ifdef XTSUB_NFPROTO_IPV6 static const struct ip6t_ip6 xtsub_uncond; @@ -187,7 +192,7 @@ XTSUB2(rule_to_xt2)(struct xt2_chain *chain, const struct xtsub_entry *entry, goto out; xt_ematch_foreach(ematch, entry) { - ret = xt2_rule_add_oldmatch(rule, ematch); + ret = xtsub_rule_add_match(rule, ematch); if (ret < 0) goto out; } @@ -598,3 +603,5 @@ XTSUB2(do_replace)(struct net *net, const void __user *user, unsigned int len) xt2_table_destroy(NULL, table); return ret; } + +#undef xtsub_rule_add_match -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html