Commit 1ecde10d authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by Zheng Zengkai
Browse files

netfilter: nf_tables_offload: incorrect flow offload action array size

mainline inclusion
from mainline-v5.17-rc6
commit b1a5983f
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4VNH7


CVE: 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.

Fixes: be2861dc ("netfilter: nft_{fwd,dup}_netdev: add offload support")
Reported-and-tested-by: default avatarNick Gregory <Nick.Gregory@Sophos.com>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>

conficts:
	net/netfilter/nft_fwd_netdev.c
	include/net/netfilter/nf_tables.h

Signed-off-by: default avatarLu Wei <luwei32@huawei.com>
Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Reviewed-by: default avatarWei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 1a2ea802
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -825,7 +825,7 @@ struct nft_expr_ops {
	int				(*offload)(struct nft_offload_ctx *ctx,
						   struct nft_flow_rule *flow,
						   const struct nft_expr *expr);
	u32				offload_flags;
	bool				(*offload_action)(const struct nft_expr *expr);
	const struct nft_expr_type	*type;
	void				*data;
};
+0 −2
Original line number Diff line number Diff line
@@ -67,8 +67,6 @@ struct nft_flow_rule {
	struct flow_rule	*rule;
};

#define NFT_OFFLOAD_F_ACTION	(1 << 0)

void nft_flow_rule_set_addr_type(struct nft_flow_rule *flow,
				 enum flow_dissector_key_id addr_type);

+2 −1
Original line number Diff line number Diff line
@@ -94,7 +94,8 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net,

	expr = nft_expr_first(rule);
	while (nft_expr_more(rule, expr)) {
		if (expr->ops->offload_flags & NFT_OFFLOAD_F_ACTION)
		if (expr->ops->offload_action &&
		    expr->ops->offload_action(expr))
			num_actions++;

		expr = nft_expr_next(expr);
+6 −0
Original line number Diff line number Diff line
@@ -67,6 +67,11 @@ static int nft_dup_netdev_offload(struct nft_offload_ctx *ctx,
	return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_MIRRED, oif);
}

static bool nft_dup_netdev_offload_action(const struct nft_expr *expr)
{
	return true;
}

static struct nft_expr_type nft_dup_netdev_type;
static const struct nft_expr_ops nft_dup_netdev_ops = {
	.type		= &nft_dup_netdev_type,
@@ -75,6 +80,7 @@ static const struct nft_expr_ops nft_dup_netdev_ops = {
	.init		= nft_dup_netdev_init,
	.dump		= nft_dup_netdev_dump,
	.offload	= nft_dup_netdev_offload,
	.offload_action	= nft_dup_netdev_offload_action,
};

static struct nft_expr_type nft_dup_netdev_type __read_mostly = {
+6 −0
Original line number Diff line number Diff line
@@ -77,6 +77,11 @@ static int nft_fwd_netdev_offload(struct nft_offload_ctx *ctx,
	return nft_fwd_dup_netdev_offload(ctx, flow, FLOW_ACTION_REDIRECT, oif);
}

static bool nft_fwd_netdev_offload_action(const struct nft_expr *expr)
{
	return true;
}

struct nft_fwd_neigh {
	enum nft_registers	sreg_dev:8;
	enum nft_registers	sreg_addr:8;
@@ -219,6 +224,7 @@ static const struct nft_expr_ops nft_fwd_netdev_ops = {
	.dump		= nft_fwd_netdev_dump,
	.validate	= nft_fwd_validate,
	.offload	= nft_fwd_netdev_offload,
	.offload_action	= nft_fwd_netdev_offload_action,
};

static const struct nft_expr_ops *
Loading