Blob Blame History Raw
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Thu, 17 Feb 2022 23:41:20 +0100
Subject: netfilter: nf_tables_offload: incorrect flow offload action array
 size
Patch-mainline: v5.17-rc6
Git-commit: b1a5983f56e371046dcf164f90bfaf704d2b89f6
References: bsc#1196299 CVE-2022-25636

immediate verdict expression needs to allocate one slot in the flow offload
action array, however, immediate data expression does not need to do so.

fwd and dup expression need to allocate one slot, this is missing.

Add a new offload_action interface to report if this expression needs to
allocate one slot in the flow offload action array.

SUSE: As the original patch breaks KABI and there aren't neither many nor
      very complicated offload_action methods, an extension of offload_flags
      is used instead to fix the issue.

Fixes: be2861dc36d7 ("netfilter: nft_{fwd,dup}_netdev: add offload support")
Reported-and-tested-by: Nick Gregory <Nick.Gregory@Sophos.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 include/net/netfilter/nf_tables_offload.h |    1 +
 net/netfilter/nf_tables_offload.c         |    8 ++++++++
 net/netfilter/nft_dup_netdev.c            |    1 +
 net/netfilter/nft_fwd_netdev.c            |    1 +
 net/netfilter/nft_immediate.c             |    2 +-
 5 files changed, 12 insertions(+), 1 deletion(-)

--- a/include/net/netfilter/nf_tables_offload.h
+++ b/include/net/netfilter/nf_tables_offload.h
@@ -61,6 +61,7 @@ struct nft_flow_rule {
 };
 
 #define NFT_OFFLOAD_F_ACTION	(1 << 0)
+#define NFT_OFFLOAD_F_VERDICT	(1 << 1)
 
 struct nft_rule;
 struct nft_flow_rule *nft_flow_rule_create(struct net *net, const struct nft_rule *rule);
--- a/net/netfilter/nf_tables_offload.c
+++ b/net/netfilter/nf_tables_offload.c
@@ -3,6 +3,7 @@
 #include <linux/module.h>
 #include <linux/netfilter.h>
 #include <net/flow_offload.h>
+#include <net/netfilter/nf_tables_core.h>
 #include <net/netfilter/nf_tables.h>
 #include <net/netfilter/nf_tables_offload.h>
 #include <net/pkt_cls.h>
@@ -41,6 +42,13 @@ struct nft_flow_rule *nft_flow_rule_crea
 		if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION)
 			num_actions++;
 
+		if (expr->ops->offload_flags & NFT_OFFLOAD_F_VERDICT) {
+			const struct nft_immediate_expr *priv =
+							nft_expr_priv(expr);
+
+			if (priv->dreg == NFT_REG_VERDICT)
+				num_actions++;
+		}
 		expr = nft_expr_next(expr);
 	}
 
--- a/net/netfilter/nft_dup_netdev.c
+++ b/net/netfilter/nft_dup_netdev.c
@@ -75,6 +75,7 @@ static const struct nft_expr_ops nft_dup
 	.init		= nft_dup_netdev_init,
 	.dump		= nft_dup_netdev_dump,
 	.offload	= nft_dup_netdev_offload,
+	.offload_flags	= NFT_OFFLOAD_F_ACTION,
 };
 
 static struct nft_expr_type nft_dup_netdev_type __read_mostly = {
--- a/net/netfilter/nft_fwd_netdev.c
+++ b/net/netfilter/nft_fwd_netdev.c
@@ -218,6 +218,7 @@ static const struct nft_expr_ops nft_fwd
 	.dump		= nft_fwd_netdev_dump,
 	.validate	= nft_fwd_validate,
 	.offload	= nft_fwd_netdev_offload,
+	.offload_flags	= NFT_OFFLOAD_F_ACTION,
 };
 
 static const struct nft_expr_ops *
--- a/net/netfilter/nft_immediate.c
+++ b/net/netfilter/nft_immediate.c
@@ -224,7 +224,7 @@ static const struct nft_expr_ops nft_imm
 	.dump		= nft_immediate_dump,
 	.validate	= nft_immediate_validate,
 	.offload	= nft_immediate_offload,
-	.offload_flags	= NFT_OFFLOAD_F_ACTION,
+	.offload_flags	= NFT_OFFLOAD_F_VERDICT,
 };
 
 struct nft_expr_type nft_imm_type __read_mostly = {