From 9075c3aa983d96c4331cb28fab5f30afd52bbb21 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Thu, 15 Dec 2022 15:08:01 +0100 Subject: nft: Increase rule parser strictness Catch more unexpected conditions. Signed-off-by: Phil Sutter --- 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(-) (limited to 'iptables') 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)); -- cgit v1.2.3