netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/3] eval: refactor NAT evaluation functions
@ 2015-01-10 14:59 Patrick McHardy
  2015-01-10 14:59 ` [PATCH 2/3] evaluate: add missing datatype compat checks for statement arguments Patrick McHardy
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Patrick McHardy @ 2015-01-10 14:59 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel

The redir and masq evaluation functions include some useless context
updates and checks.

Refactor the NAT code to have a single instance of address and transport
evaluation functions for simplicity and unified error reporting.

Signed-off-by: Patrick McHardy <kaber@trash.net>
---
 src/evaluate.c | 110 ++++++++++++++++++++++++++++-----------------------------
 1 file changed, 54 insertions(+), 56 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index 43fb968..4cfe749 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1496,32 +1496,61 @@ static int stmt_evaluate_reject(struct eval_ctx *ctx, struct stmt *stmt)
 	return stmt_evaluate_reject_family(ctx, stmt, expr);
 }
 
+static int nat_evaluate_family(struct eval_ctx *ctx, struct stmt *stmt)
+{
+	switch (ctx->pctx.family) {
+	case AF_INET:
+	case AF_INET6:
+		return 0;
+	default:
+		return stmt_error(ctx, stmt,
+				  "NAT is only supported for IPv4/IPv6");
+	}
+}
+
+static int nat_evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt,
+			     struct expr **expr)
+{
+	struct proto_ctx *pctx = &ctx->pctx;
+
+	if (pctx->family == AF_INET)
+		expr_set_context(&ctx->ectx, &ipaddr_type, 4 * BITS_PER_BYTE);
+	else
+		expr_set_context(&ctx->ectx, &ip6addr_type, 16 * BITS_PER_BYTE);
+
+	return expr_evaluate(ctx, expr);
+}
+
+static int nat_evaluate_transport(struct eval_ctx *ctx, struct stmt *stmt,
+				  struct expr **expr)
+{
+	struct proto_ctx *pctx = &ctx->pctx;
+
+	if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL)
+		return stmt_binary_error(ctx, *expr, stmt,
+					 "transport protocol mapping is only "
+					 "valid after transport protocol match");
+
+	expr_set_context(&ctx->ectx, &inet_service_type, 2 * BITS_PER_BYTE);
+	return expr_evaluate(ctx, expr);
+}
+
 static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
 {
 	struct proto_ctx *pctx = &ctx->pctx;
 	int err;
 
+	err = nat_evaluate_family(ctx, stmt);
+	if (err < 0)
+		return err;
+
 	if (stmt->nat.addr != NULL) {
-		if (pctx && (pctx->family == AF_INET))
-			expr_set_context(&ctx->ectx, &ipaddr_type,
-					4 * BITS_PER_BYTE);
-		else
-			expr_set_context(&ctx->ectx, &ip6addr_type,
-					 16 * BITS_PER_BYTE);
-		err = expr_evaluate(ctx, &stmt->nat.addr);
+		err = nat_evaluate_addr(ctx, stmt, &stmt->nat.addr);
 		if (err < 0)
 			return err;
 	}
-
 	if (stmt->nat.proto != NULL) {
-		if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL)
-			return stmt_binary_error(ctx, stmt->nat.proto, stmt,
-						 "transport protocol mapping is only "
-						 "valid after transport protocol match");
-
-		expr_set_context(&ctx->ectx, &inet_service_type,
-				 2 * BITS_PER_BYTE);
-		err = expr_evaluate(ctx, &stmt->nat.proto);
+		err = nat_evaluate_transport(ctx, stmt, &stmt->nat.proto);
 		if (err < 0)
 			return err;
 	}
@@ -1533,62 +1562,31 @@ static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
 static int stmt_evaluate_masq(struct eval_ctx *ctx, struct stmt *stmt)
 {
 	struct proto_ctx *pctx = &ctx->pctx;
+	int err;
 
-	if (!pctx)
-		goto out;
-
-	switch (pctx->family) {
-	case AF_INET:
-		expr_set_context(&ctx->ectx, &ipaddr_type,
-				4 * BITS_PER_BYTE);
-		break;
-	case AF_INET6:
-		expr_set_context(&ctx->ectx, &ip6addr_type,
-				 16 * BITS_PER_BYTE);
-		break;
-	default:
-		return stmt_error(ctx, stmt, "ip and ip6 support only");
-	}
+	err = nat_evaluate_family(ctx, stmt);
+	if (err < 0)
+		return err;
 
-out:
 	stmt->flags |= STMT_F_TERMINAL;
 	return 0;
 }
 
 static int stmt_evaluate_redir(struct eval_ctx *ctx, struct stmt *stmt)
 {
-	int err;
 	struct proto_ctx *pctx = &ctx->pctx;
+	int err;
 
-	if (!pctx)
-		goto out;
-
-	switch (pctx->family) {
-	case AF_INET:
-		expr_set_context(&ctx->ectx, &ipaddr_type,
-				4 * BITS_PER_BYTE);
-		break;
-	case AF_INET6:
-		expr_set_context(&ctx->ectx, &ip6addr_type,
-				 16 * BITS_PER_BYTE);
-		break;
-	default:
-		return stmt_error(ctx, stmt, "ip and ip6 support only");
-	}
+	err = nat_evaluate_family(ctx, stmt);
+	if (err < 0)
+		return err;
 
 	if (stmt->redir.proto != NULL) {
-		if (pctx->protocol[PROTO_BASE_TRANSPORT_HDR].desc == NULL)
-			return stmt_binary_error(ctx, stmt->redir.proto, stmt,
-						 "missing transport protocol match");
-
-		expr_set_context(&ctx->ectx, &inet_service_type,
-				 2 * BITS_PER_BYTE);
-		err = expr_evaluate(ctx, &stmt->redir.proto);
+		err = nat_evaluate_transport(ctx, stmt, &stmt->redir.proto);
 		if (err < 0)
 			return err;
 	}
 
-out:
 	stmt->flags |= STMT_F_TERMINAL;
 	return 0;
 }
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/3] evaluate: add missing datatype compat checks for statement arguments
  2015-01-10 14:59 [PATCH 1/3] eval: refactor NAT evaluation functions Patrick McHardy
@ 2015-01-10 14:59 ` Patrick McHardy
  2015-01-10 14:59 ` [PATCH 3/3] netlink_delinearize: fix error handling for invalid registers Patrick McHardy
  2015-01-10 18:59 ` [PATCH 1/3] eval: refactor NAT evaluation functions Pablo Neira Ayuso
  2 siblings, 0 replies; 4+ messages in thread
From: Patrick McHardy @ 2015-01-10 14:59 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel

Add a helper function to evaluate expressions used as arguments for
statements and report datatype mismatches.

Fixes acceptance of mismatching expressions like:

$ nft filter output meta mark set ip daddr
<cmdline>:1:29-36: Error: datatype mismatch: expected packet mark. expression has type IPv4 address
filter output meta mark set ip daddr
              ~~~~~~~~~~~~~~^^^^^^^^

Signed-off-by: Patrick McHardy <kaber@trash.net>
---
 src/evaluate.c | 66 ++++++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 43 insertions(+), 23 deletions(-)

diff --git a/src/evaluate.c b/src/evaluate.c
index 4cfe749..0a1422a 100644
--- a/src/evaluate.c
+++ b/src/evaluate.c
@@ -1112,6 +1112,22 @@ static int stmt_evaluate_expr(struct eval_ctx *ctx, struct stmt *stmt)
 	return expr_evaluate(ctx, &stmt->expr);
 }
 
+static int stmt_evaluate_arg(struct eval_ctx *ctx, struct stmt *stmt,
+			     const struct datatype *dtype, unsigned int len,
+			     struct expr **expr)
+{
+	expr_set_context(&ctx->ectx, dtype, len);
+	if (expr_evaluate(ctx, expr) < 0)
+		return -1;
+
+	if (!datatype_equal((*expr)->dtype, dtype))
+		return stmt_binary_error(ctx, *expr, stmt,
+					 "datatype mismatch: expected %s. "
+					 "expression has type %s",
+					 dtype->desc, (*expr)->dtype->desc);
+	return 0;
+}
+
 static int stmt_evaluate_verdict(struct eval_ctx *ctx, struct stmt *stmt)
 {
 	expr_set_context(&ctx->ectx, &verdict_type, 0);
@@ -1133,11 +1149,18 @@ static int stmt_evaluate_verdict(struct eval_ctx *ctx, struct stmt *stmt)
 
 static int stmt_evaluate_meta(struct eval_ctx *ctx, struct stmt *stmt)
 {
-	expr_set_context(&ctx->ectx, stmt->meta.tmpl->dtype,
-			 stmt->meta.tmpl->len);
-	if (expr_evaluate(ctx, &stmt->meta.expr) < 0)
-		return -1;
-	return 0;
+	return stmt_evaluate_arg(ctx, stmt,
+				 stmt->meta.tmpl->dtype,
+				 stmt->meta.tmpl->len,
+				 &stmt->meta.expr);
+}
+
+static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
+{
+	return stmt_evaluate_arg(ctx, stmt,
+				 stmt->ct.tmpl->dtype,
+				 stmt->ct.tmpl->len,
+				 &stmt->ct.expr);
 }
 
 static int reject_payload_gen_dependency_tcp(struct eval_ctx *ctx,
@@ -1512,13 +1535,18 @@ static int nat_evaluate_addr(struct eval_ctx *ctx, struct stmt *stmt,
 			     struct expr **expr)
 {
 	struct proto_ctx *pctx = &ctx->pctx;
+	const struct datatype *dtype;
+	unsigned int len;
 
-	if (pctx->family == AF_INET)
-		expr_set_context(&ctx->ectx, &ipaddr_type, 4 * BITS_PER_BYTE);
-	else
-		expr_set_context(&ctx->ectx, &ip6addr_type, 16 * BITS_PER_BYTE);
+	if (pctx->family == AF_INET) {
+		dtype = &ipaddr_type;
+		len   = 4 * BITS_PER_BYTE;
+	} else {
+		dtype = &ip6addr_type;
+		len   = 16 * BITS_PER_BYTE;
+	}
 
-	return expr_evaluate(ctx, expr);
+	return stmt_evaluate_arg(ctx, stmt, dtype, len, expr);
 }
 
 static int nat_evaluate_transport(struct eval_ctx *ctx, struct stmt *stmt,
@@ -1531,8 +1559,9 @@ static int nat_evaluate_transport(struct eval_ctx *ctx, struct stmt *stmt,
 					 "transport protocol mapping is only "
 					 "valid after transport protocol match");
 
-	expr_set_context(&ctx->ectx, &inet_service_type, 2 * BITS_PER_BYTE);
-	return expr_evaluate(ctx, expr);
+	return stmt_evaluate_arg(ctx, stmt,
+				 &inet_service_type, 2 * BITS_PER_BYTE,
+				 expr);
 }
 
 static int stmt_evaluate_nat(struct eval_ctx *ctx, struct stmt *stmt)
@@ -1591,15 +1620,6 @@ static int stmt_evaluate_redir(struct eval_ctx *ctx, struct stmt *stmt)
 	return 0;
 }
 
-static int stmt_evaluate_ct(struct eval_ctx *ctx, struct stmt *stmt)
-{
-	expr_set_context(&ctx->ectx, stmt->ct.tmpl->dtype,
-			 stmt->ct.tmpl->len);
-	if (expr_evaluate(ctx, &stmt->ct.expr) < 0)
-		return -1;
-	return 0;
-}
-
 static int stmt_evaluate_queue(struct eval_ctx *ctx, struct stmt *stmt)
 {
 	if (stmt->queue.queue != NULL) {
@@ -1645,6 +1665,8 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
 		return stmt_evaluate_verdict(ctx, stmt);
 	case STMT_META:
 		return stmt_evaluate_meta(ctx, stmt);
+	case STMT_CT:
+		return stmt_evaluate_ct(ctx, stmt);
 	case STMT_LOG:
 		return stmt_evaluate_log(ctx, stmt);
 	case STMT_REJECT:
@@ -1657,8 +1679,6 @@ int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
 		return stmt_evaluate_redir(ctx, stmt);
 	case STMT_QUEUE:
 		return stmt_evaluate_queue(ctx, stmt);
-	case STMT_CT:
-		return stmt_evaluate_ct(ctx, stmt);
 	default:
 		BUG("unknown statement type %s\n", stmt->ops->name);
 	}
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/3] netlink_delinearize: fix error handling for invalid registers
  2015-01-10 14:59 [PATCH 1/3] eval: refactor NAT evaluation functions Patrick McHardy
  2015-01-10 14:59 ` [PATCH 2/3] evaluate: add missing datatype compat checks for statement arguments Patrick McHardy
@ 2015-01-10 14:59 ` Patrick McHardy
  2015-01-10 18:59 ` [PATCH 1/3] eval: refactor NAT evaluation functions Pablo Neira Ayuso
  2 siblings, 0 replies; 4+ messages in thread
From: Patrick McHardy @ 2015-01-10 14:59 UTC (permalink / raw)
  To: pablo; +Cc: netfilter-devel

netlink_delinearize is prepared to deal with malformed expressions from
the kernel that it doesn't understand. However since expressions are now
cloned unconditionally by netlink_get_register(), we crash before such
errors can be detected for invalid inputs.

Fix by only cloning non-NULL expressions.

Signed-off-by: Patrick McHardy <kaber@trash.net>
---
 src/netlink_delinearize.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
index e9a04dd..79d5af6 100644
--- a/src/netlink_delinearize.c
+++ b/src/netlink_delinearize.c
@@ -75,7 +75,10 @@ static struct expr *netlink_get_register(struct netlink_parse_ctx *ctx,
 	}
 
 	expr = ctx->registers[reg];
-	return expr_clone(expr);
+	if (expr != NULL)
+		expr = expr_clone(expr);
+
+	return expr;
 }
 
 static void netlink_release_registers(struct netlink_parse_ctx *ctx)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/3] eval: refactor NAT evaluation functions
  2015-01-10 14:59 [PATCH 1/3] eval: refactor NAT evaluation functions Patrick McHardy
  2015-01-10 14:59 ` [PATCH 2/3] evaluate: add missing datatype compat checks for statement arguments Patrick McHardy
  2015-01-10 14:59 ` [PATCH 3/3] netlink_delinearize: fix error handling for invalid registers Patrick McHardy
@ 2015-01-10 18:59 ` Pablo Neira Ayuso
  2 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2015-01-10 18:59 UTC (permalink / raw)
  To: Patrick McHardy; +Cc: netfilter-devel

On Sat, Jan 10, 2015 at 02:59:13PM +0000, Patrick McHardy wrote:
> The redir and masq evaluation functions include some useless context
> updates and checks.
> 
> Refactor the NAT code to have a single instance of address and transport
> evaluation functions for simplicity and unified error reporting.

Thanks a lot for revisiting these changes Patrick!

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-01-10 18:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-10 14:59 [PATCH 1/3] eval: refactor NAT evaluation functions Patrick McHardy
2015-01-10 14:59 ` [PATCH 2/3] evaluate: add missing datatype compat checks for statement arguments Patrick McHardy
2015-01-10 14:59 ` [PATCH 3/3] netlink_delinearize: fix error handling for invalid registers Patrick McHardy
2015-01-10 18:59 ` [PATCH 1/3] eval: refactor NAT evaluation functions Pablo Neira Ayuso

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).