[iptables PATCH 3/4] nft: Increase rule parser strictness

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Catch more unexpected conditions.

Signed-off-by: Phil Sutter <phil@xxxxxx>
---
 iptables/nft-arp.c    |  2 ++
 iptables/nft-bridge.c |  4 ++++
 iptables/nft-ipv4.c   |  4 +++-
 iptables/nft-ipv6.c   |  4 +++-
 iptables/nft-shared.c | 35 +++++++++++++++++++++++++----------
 5 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index edf179521e355..210f43d2cefbe 100644
--- a/iptables/nft-arp.c
+++ b/iptables/nft-arp.c
@@ -288,6 +288,8 @@ static void nft_arp_parse_payload(struct nft_xt_ctx *ctx,
 
 			if (inv)
 				fw->arp.invflags |= IPT_INV_DSTIP;
+		} else {
+			ctx->errmsg = "unknown payload offset";
 		}
 		break;
 	}
diff --git a/iptables/nft-bridge.c b/iptables/nft-bridge.c
index e223d19765f90..83cbe31559d4b 100644
--- a/iptables/nft-bridge.c
+++ b/iptables/nft-bridge.c
@@ -287,6 +287,10 @@ static void nft_bridge_parse_payload(struct nft_xt_ctx *ctx,
 			fw->invflags |= EBT_IPROTO;
 		fw->bitmask &= ~EBT_NOPROTO;
 		break;
+	default:
+		DEBUGP("unknown payload offset %d\n", reg->payload.offset);
+		ctx->errmsg = "unknown payload offset";
+		break;
 	}
 }
 
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 42167351710e6..dcc4a8edfc87f 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -207,10 +207,12 @@ static void nft_ipv4_parse_payload(struct nft_xt_ctx *ctx,
 			cs->fw.ip.invflags |= IPT_INV_FRAG;
 		break;
 	case offsetof(struct iphdr, ttl):
-		nft_parse_hl(ctx, e, cs);
+		if (nft_parse_hl(ctx, e, cs) < 0)
+			ctx->errmsg = "invalid ttl field match";
 		break;
 	default:
 		DEBUGP("unknown payload offset %d\n", sreg->payload.offset);
+		ctx->errmsg = "unknown payload offset";
 		break;
 	}
 }
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 3a373b7eb2cfe..e98921856c75d 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -173,10 +173,12 @@ static void nft_ipv6_parse_payload(struct nft_xt_ctx *ctx,
 		if (inv)
 			cs->fw6.ipv6.invflags |= IP6T_INV_PROTO;
 	case offsetof(struct ip6_hdr, ip6_hlim):
-		nft_parse_hl(ctx, e, cs);
+		if (nft_parse_hl(ctx, e, cs) < 0)
+			ctx->errmsg = "invalid ttl field match";
 		break;
 	default:
 		DEBUGP("unknown payload offset %d\n", reg->payload.offset);
+		ctx->errmsg = "unknown payload offset";
 		break;
 	}
 }
diff --git a/iptables/nft-shared.c b/iptables/nft-shared.c
index d4b21921077d9..c13fc307e7a89 100644
--- a/iptables/nft-shared.c
+++ b/iptables/nft-shared.c
@@ -444,8 +444,10 @@ static void nft_parse_target(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 	size_t size;
 
 	target = xtables_find_target(targname, XTF_TRY_LOAD);
-	if (target == NULL)
+	if (target == NULL) {
+		ctx->errmsg = "target extension not found";
 		return;
+	}
 
 	size = XT_ALIGN(sizeof(struct xt_entry_target)) + tg_len;
 
@@ -482,8 +484,10 @@ static void nft_parse_match(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 	}
 
 	match = xtables_find_match(mt_name, XTF_TRY_LOAD, matches);
-	if (match == NULL)
+	if (match == NULL) {
+		ctx->errmsg = "match extension not found";
 		return;
+	}
 
 	m = xtables_calloc(1, sizeof(struct xt_entry_match) + mt_len);
 	memcpy(&m->data, mt_info, mt_len);
@@ -690,9 +694,10 @@ static struct xt_tcp *nft_tcp_match(struct nft_xt_ctx *ctx,
 
 	if (!tcp) {
 		match = nft_create_match(ctx, cs, "tcp");
-		if (!match)
+		if (!match) {
+			ctx->errmsg = "tcp match extension not found";
 			return NULL;
-
+		}
 		tcp = (void*)match->m->data;
 		ctx->tcpudp.tcp = tcp;
 	}
@@ -904,6 +909,8 @@ static void nft_parse_th_port(struct nft_xt_ctx *ctx,
 	case IPPROTO_TCP:
 		nft_parse_tcp(ctx, cs, sport, dport, op);
 		break;
+	default:
+		ctx->errmsg = "unknown layer 4 protocol for TH match";
 	}
 }
 
@@ -957,8 +964,8 @@ static void nft_parse_transport(struct nft_xt_ctx *ctx,
 		proto = ctx->cs->fw6.ipv6.proto;
 		break;
 	default:
-		proto = 0;
-		break;
+		ctx->errmsg = "invalid family for TH match";
+		return;
 	}
 
 	nftnl_expr_get(e, NFTNL_EXPR_CMP_DATA, &len);
@@ -1129,8 +1136,10 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 		if (!dreg)
 			return;
 
-		if (len > sizeof(dreg->immediate.data))
+		if (len > sizeof(dreg->immediate.data)) {
+			ctx->errmsg = "oversized immediate data";
 			return;
+		}
 
 		memcpy(dreg->immediate.data, imm_data, len);
 		dreg->immediate.len = len;
@@ -1163,8 +1172,10 @@ static void nft_parse_immediate(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 	}
 
 	cs->target = xtables_find_target(cs->jumpto, XTF_TRY_LOAD);
-	if (!cs->target)
+	if (!cs->target) {
+		ctx->errmsg = "verdict extension not found";
 		return;
+	}
 
 	size = XT_ALIGN(sizeof(struct xt_entry_target)) + cs->target->size;
 	t = xtables_calloc(1, size);
@@ -1197,8 +1208,10 @@ static void nft_parse_limit(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 	}
 
 	match = xtables_find_match("limit", XTF_TRY_LOAD, matches);
-	if (match == NULL)
+	if (match == NULL) {
+		ctx->errmsg = "limit match extension not found";
 		return;
+	}
 
 	size = XT_ALIGN(sizeof(struct xt_entry_match)) + match->size;
 	match->m = xtables_calloc(1, size);
@@ -1245,8 +1258,10 @@ static void nft_parse_log(struct nft_xt_ctx *ctx, struct nftnl_expr *e)
 			 nftnl_expr_get_str(e, NFTNL_EXPR_LOG_PREFIX));
 
 	target = xtables_find_target("NFLOG", XTF_TRY_LOAD);
-	if (target == NULL)
+	if (target == NULL) {
+		ctx->errmsg = "NFLOG target extension not found";
 		return;
+	}
 
 	target_size = XT_ALIGN(sizeof(struct xt_entry_target)) +
 		      XT_ALIGN(sizeof(struct xt_nflog_info_nft));
-- 
2.38.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux