All of lore.kernel.org
 help / color / mirror / Atom feed
From: pablo@netfilter.org
To: netfilter-devel@vger.kernel.org
Cc: kaber@trash.net, tomasz.bursztyka@linux.intel.com
Subject: [PATCH 6/7] netfilter: nf_tables: support 32bits-64bits x_tables compat
Date: Thu, 10 Jan 2013 16:28:40 +0100	[thread overview]
Message-ID: <1357831721-10182-6-git-send-email-pablo@netfilter.org> (raw)
In-Reply-To: <1357831721-10182-1-git-send-email-pablo@netfilter.org>

From: Pablo Neira Ayuso <pablo@netfilter.org>

This patch adds support for existing compat infrastructure in
matches/targets.

This adds a new callback compat_to_blob that uses memcpy
instead of copy_to_user.

The standard target has no compat_to_blob since user-space
is using the native immediate expression to issue verdicts.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 include/linux/netfilter/x_tables.h |    2 +
 net/ipv4/netfilter/ipt_ULOG.c      |   14 ++++++
 net/netfilter/nft_compat.c         |   83 ++++++++++++++++++++++++++++++++----
 net/netfilter/xt_limit.c           |   16 +++++++
 4 files changed, 107 insertions(+), 8 deletions(-)

diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 8d674a7..f2cc078 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -307,6 +307,7 @@ struct xt_match {
 	/* Called when userspace align differs from kernel space one */
 	void (*compat_from_user)(void *dst, const void *src);
 	int (*compat_to_user)(void __user *dst, const void *src);
+	void (*compat_to_blob)(void *dst, const void *src);
 #endif
 	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
 	struct module *me;
@@ -347,6 +348,7 @@ struct xt_target {
 	/* Called when userspace align differs from kernel space one */
 	void (*compat_from_user)(void *dst, const void *src);
 	int (*compat_to_user)(void __user *dst, const void *src);
+	void (*compat_to_blob)(void *dst, const void *src);
 #endif
 	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
 	struct module *me;
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index b5ef3cb..6941581 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -356,6 +356,19 @@ static int ulog_tg_compat_to_user(void __user *dst, const void *src)
 	memcpy(cl.prefix, l->prefix, sizeof(cl.prefix));
 	return copy_to_user(dst, &cl, sizeof(cl)) ? -EFAULT : 0;
 }
+
+static void ulog_tg_compat_to_blob(void *dst, const void *src)
+{
+	const struct ipt_ulog_info *l = src;
+	struct compat_ipt_ulog_info cl = {
+		.nl_group	= l->nl_group,
+		.copy_range	= l->copy_range,
+		.qthreshold	= l->qthreshold,
+	};
+
+	memcpy(cl.prefix, l->prefix, sizeof(cl.prefix));
+	memcpy(dst, &cl, sizeof(cl));
+}
 #endif /* CONFIG_COMPAT */
 
 static struct xt_target ulog_tg_reg __read_mostly = {
@@ -368,6 +381,7 @@ static struct xt_target ulog_tg_reg __read_mostly = {
 	.compatsize	= sizeof(struct compat_ipt_ulog_info),
 	.compat_from_user = ulog_tg_compat_from_user,
 	.compat_to_user	= ulog_tg_compat_to_user,
+	.compat_to_blob	= ulog_tg_compat_to_blob,
 #endif
 	.me		= THIS_MODULE,
 };
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c
index 9f84e23..3cd6fd6 100644
--- a/net/netfilter/nft_compat.c
+++ b/net/netfilter/nft_compat.c
@@ -1,5 +1,5 @@
 /*
- * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -82,6 +82,19 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par,
 	par->family	= ctx->afi->family;
 }
 
+static void target_compat_from_user(struct xt_target *t, void *in, void *out)
+{
+	int pad;
+
+	if (t->compat_from_user) {
+		t->compat_from_user(out, in);
+		pad = XT_ALIGN(t->targetsize) - t->targetsize;
+		if (pad > 0)
+			memset(out + t->targetsize, 0, pad);
+	} else
+		memcpy(out, in, XT_ALIGN(t->targetsize));
+}
+
 static int
 nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 		const struct nlattr * const tb[])
@@ -92,8 +105,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	size_t size = XT_ALIGN(nla_len(tb[NFTA_TARGET_INFO]));
 	int ret;
 
-	memcpy(info, nla_data(tb[NFTA_TARGET_INFO]),
-	       XT_ALIGN(target->targetsize));
+	target_compat_from_user(target, nla_data(tb[NFTA_TARGET_INFO]), info);
 
 	nft_target_set_tgchk_param(&par, ctx, target, info);
 
@@ -122,6 +134,26 @@ nft_target_destroy(const struct nft_expr *expr)
 	module_put(target->me);
 }
 
+static int
+target_dump_info(struct sk_buff *skb, const struct xt_target *t, const void *in)
+{
+	void *out;
+	int ret;
+
+	if (t->compat_to_blob) {
+		out = kmalloc(XT_ALIGN(t->targetsize), GFP_ATOMIC);
+		if (out == NULL)
+			return -ENOMEM;
+
+		t->compat_to_blob(out, in);
+		ret = nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(t->targetsize), out);
+		kfree(out);
+	} else
+		ret = nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(t->targetsize), in);
+
+	return ret;
+}
+
 static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
 	const struct xt_target *target = expr->ops->data;
@@ -129,7 +161,7 @@ static int nft_target_dump(struct sk_buff *skb, const struct nft_expr *expr)
 
 	if (nla_put_string(skb, NFTA_TARGET_NAME, target->name) ||
 	    nla_put_be32(skb, NFTA_TARGET_REV, htonl(target->revision)) ||
-	    nla_put(skb, NFTA_TARGET_INFO, XT_ALIGN(target->targetsize), info))
+	    target_dump_info(skb, target, info))
 		goto nla_put_failure;
 
 	return 0;
@@ -214,6 +246,19 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx,
 	par->family	= ctx->afi->family;
 }
 
+static void match_compat_from_user(struct xt_match *m, void *in, void *out)
+{
+	int pad;
+
+	if (m->compat_from_user) {
+		m->compat_from_user(out, in);
+		pad = XT_ALIGN(m->matchsize) - m->matchsize;
+		if (pad > 0)
+			memset(out + m->matchsize, 0, pad);
+	} else
+		memcpy(out, in, XT_ALIGN(m->matchsize));
+}
+
 static int
 nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 		const struct nlattr * const tb[])
@@ -224,7 +269,7 @@ nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 	size_t size = XT_ALIGN(nla_len(tb[NFTA_MATCH_INFO]));
 	int ret;
 
-	memcpy(info, nla_data(tb[NFTA_MATCH_INFO]), XT_ALIGN(match->matchsize));
+	match_compat_from_user(match, nla_data(tb[NFTA_MATCH_INFO]), info);
 
 	nft_match_set_mtchk_param(&par, ctx, match, info);
 
@@ -247,6 +292,26 @@ nft_match_destroy(const struct nft_expr *expr)
 	module_put(match->me);
 }
 
+static int
+match_dump_info(struct sk_buff *skb, const struct xt_match *m, const void *in)
+{
+	void *out;
+	int ret;
+
+	if (m->compat_to_blob) {
+		out = kmalloc(XT_ALIGN(m->matchsize), GFP_ATOMIC);
+		if (out == NULL)
+			return -ENOMEM;
+
+		m->compat_to_blob(out, in);
+		ret = nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(m->matchsize), out);
+		kfree(out);
+	} else
+		ret = nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(m->matchsize), in);
+
+	return ret;
+}
+
 static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
 {
 	void *info = nft_expr_priv(expr);
@@ -254,7 +319,7 @@ static int nft_match_dump(struct sk_buff *skb, const struct nft_expr *expr)
 
 	if (nla_put_string(skb, NFTA_MATCH_NAME, match->name) ||
 	    nla_put_be32(skb, NFTA_MATCH_REV, htonl(match->revision)) ||
-	    nla_put(skb, NFTA_MATCH_INFO, XT_ALIGN(match->matchsize), info))
+	    match_dump_info(skb, match, info))
 		goto nla_put_failure;
 
 	return 0;
@@ -449,7 +514,8 @@ nft_match_select_ops(const struct nft_ctx *ctx,
 		return ERR_PTR(-ENOMEM);
 
 	nft_match->ops.type = &nft_match_type;
-	nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize));
+	nft_match->ops.size = NFT_EXPR_SIZE(XT_ALIGN(match->matchsize) +
+					    xt_compat_match_offset(match));
 	nft_match->ops.eval = nft_match_eval;
 	nft_match->ops.init = nft_match_init;
 	nft_match->ops.destroy = nft_match_destroy;
@@ -519,7 +585,8 @@ nft_target_select_ops(const struct nft_ctx *ctx,
 		return ERR_PTR(-ENOMEM);
 
 	nft_target->ops.type = &nft_target_type;
-	nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
+	nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize) +
+					     xt_compat_target_offset(target));
 	nft_target->ops.eval = nft_target_eval;
 	nft_target->ops.init = nft_target_init;
 	nft_target->ops.destroy = nft_target_destroy;
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 5c22ce8..4a19bd4 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -177,6 +177,21 @@ static int limit_mt_compat_to_user(void __user *dst, const void *src)
 	};
 	return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0;
 }
+
+static void limit_mt_compat_to_blob(void *dst, const void *src)
+{
+	const struct xt_rateinfo *m = src;
+	struct compat_xt_rateinfo cm = {
+		.avg		= m->avg,
+		.burst		= m->burst,
+		.prev		= m->prev,
+		.credit		= m->credit,
+		.credit_cap	= m->credit_cap,
+		.cost		= m->cost,
+		.master		= m->prev >> 32,
+	};
+	memcpy(dst, &cm, sizeof(cm));
+}
 #endif /* CONFIG_COMPAT */
 
 static struct xt_match limit_mt_reg __read_mostly = {
@@ -191,6 +206,7 @@ static struct xt_match limit_mt_reg __read_mostly = {
 	.compatsize       = sizeof(struct compat_xt_rateinfo),
 	.compat_from_user = limit_mt_compat_from_user,
 	.compat_to_user   = limit_mt_compat_to_user,
+	.compat_to_blob   = limit_mt_compat_to_blob,
 #endif
 	.me               = THIS_MODULE,
 };
-- 
1.7.10.4


  parent reply	other threads:[~2013-01-10 15:29 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-10 15:28 [PATCH 1/7] netfilter: nf_tables: nft_compat: release cached matches/targets pablo
2013-01-10 15:28 ` [PATCH 2/7] netfilter: nf_tables: move filter chain definition to layer 3 modules pablo
2013-01-10 16:02   ` Patrick McHardy
2013-01-10 15:28 ` [PATCH 3/7] netfilter: nf_tables: remove hook definitions from struct nft_af_info pablo
2013-01-10 16:04   ` Patrick McHardy
2013-01-10 16:19     ` Pablo Neira Ayuso
2013-01-10 15:28 ` [PATCH 4/7] netfilter: nf_tables: move specific layer 3 compat code to nf_tables_ipv[4|6] pablo
2013-01-10 16:09   ` Patrick McHardy
2013-01-10 16:20     ` Pablo Neira Ayuso
2013-01-10 15:28 ` [PATCH 5/7] netfilter: nf_tables: x_tables support as a compile time option pablo
2013-01-10 15:28 ` pablo [this message]
2013-01-10 16:12   ` [PATCH 6/7] netfilter: nf_tables: support 32bits-64bits x_tables compat Patrick McHardy
2013-01-10 15:28 ` [PATCH 7/7] netfilter: nf_tables: fix alias for xtables over nftables module pablo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1357831721-10182-6-git-send-email-pablo@netfilter.org \
    --to=pablo@netfilter.org \
    --cc=kaber@trash.net \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=tomasz.bursztyka@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.