summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhil Sutter <phil@nwl.cc>2022-12-15 15:08:01 +0100
committerPhil Sutter <phil@nwl.cc>2022-12-20 21:49:38 +0100
commit9075c3aa983d96c4331cb28fab5f30afd52bbb21 (patch)
tree05160cf21b97dae51290a77922c087cb1b49e6f2
parentf2c5e52863ea48838e9b9246ed94419053673b88 (diff)
nft: Increase rule parser strictness
Catch more unexpected conditions. Signed-off-by: Phil Sutter <phil@nwl.cc>
-rw-r--r--iptables/nft-arp.c2
-rw-r--r--iptables/nft-bridge.c4
-rw-r--r--iptables/nft-ipv4.c4
-rw-r--r--iptables/nft-ipv6.c4
-rw-r--r--iptables/nft-shared.c35
5 files changed, 37 insertions, 12 deletions
diff --git a/iptables/nft-arp.c b/iptables/nft-arp.c
index edf17952..210f43d2 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 e223d197..83cbe315 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 42167351..dcc4a8ed 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 3a373b7e..e9892185 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 d4b21921..c13fc307 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));