Unverified Commit 56bd74ee authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!12245 v2 netfilter: nf_tables: use timestamp to check for set element timeout

parents 5d655da7 d40a9b6a
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <net/netfilter/nf_flow_table.h>
#include <net/netlink.h>
#include <net/flow_offload.h>
#include <net/netns/generic.h>

#define NFT_MAX_HOOKS	(NF_INET_INGRESS + 1)

@@ -700,10 +701,16 @@ static inline struct nft_expr *nft_set_ext_expr(const struct nft_set_ext *ext)
	return nft_set_ext(ext, NFT_SET_EXT_EXPR);
}

static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext,
					  u64 tstamp)
{
	return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
	       time_is_before_eq_jiffies64(*nft_set_ext_expiration(ext));
	       time_after_eq64(tstamp, *nft_set_ext_expiration(ext));
}

static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
{
	return __nft_set_elem_expired(ext, get_jiffies_64());
}

static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
@@ -1592,9 +1599,22 @@ struct nftables_pernet {
	struct list_head	module_list;
	struct list_head	notify_list;
	struct mutex		commit_mutex;
	u64			tstamp;
	unsigned int		base_seq;
	u8			validate_state;
	unsigned int		gc_seq;
};

extern unsigned int nf_tables_net_id;

static inline struct nftables_pernet *nft_pernet(const struct net *net)
{
	return net_generic(net, nf_tables_net_id);
}

static inline u64 nft_net_tstamp(const struct net *net)
{
	return nft_pernet(net)->tstamp;
}

#endif /* _NET_NF_TABLES_H */
+1 −0
Original line number Diff line number Diff line
@@ -9074,6 +9074,7 @@ static bool nf_tables_valid_genid(struct net *net, u32 genid)
	bool genid_ok;

	mutex_lock(&nft_net->commit_mutex);
	nft_net->tstamp = get_jiffies_64();

	genid_ok = genid == 0 || nft_net->base_seq == genid;
	if (!genid_ok)
+7 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ struct nft_rhash_cmp_arg {
	const struct nft_set		*set;
	const u32			*key;
	u8				genmask;
	u64				tstamp;
};

static inline u32 nft_rhash_key(const void *data, u32 len, u32 seed)
@@ -64,7 +65,7 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
		return 1;
	if (nft_set_elem_is_dead(&he->ext))
		return 1;
	if (nft_set_elem_expired(&he->ext))
	if (__nft_set_elem_expired(&he->ext, x->tstamp))
		return 1;
	if (!nft_set_elem_active(&he->ext, x->genmask))
		return 1;
@@ -88,6 +89,7 @@ static bool nft_rhash_lookup(const struct net *net, const struct nft_set *set,
		.genmask = nft_genmask_cur(net),
		.set	 = set,
		.key	 = key,
		.tstamp  = get_jiffies_64(),
	};

	he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -106,6 +108,7 @@ static void *nft_rhash_get(const struct net *net, const struct nft_set *set,
		.genmask = nft_genmask_cur(net),
		.set	 = set,
		.key	 = elem->key.val.data,
		.tstamp  = get_jiffies_64(),
	};

	he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -129,6 +132,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
		.genmask = NFT_GENMASK_ANY,
		.set	 = set,
		.key	 = key,
		.tstamp  = get_jiffies_64(),
	};

	he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -172,6 +176,7 @@ static int nft_rhash_insert(const struct net *net, const struct nft_set *set,
		.genmask = nft_genmask_next(net),
		.set	 = set,
		.key	 = elem->key.val.data,
		.tstamp	 = nft_net_tstamp(net),
	};
	struct nft_rhash_elem *prev;

@@ -214,6 +219,7 @@ static void *nft_rhash_deactivate(const struct net *net,
		.genmask = nft_genmask_next(net),
		.set	 = set,
		.key	 = elem->key.val.data,
		.tstamp	 = nft_net_tstamp(net),
	};

	rcu_read_lock();
+11 −7
Original line number Diff line number Diff line
@@ -504,6 +504,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
 * @set:	nftables API set representation
 * @data:	Key data to be matched against existing elements
 * @genmask:	If set, check that element is active in given genmask
 * @tstamp:	timestamp to check for expired elements
 *
 * This is essentially the same as the lookup function, except that it matches
 * key data against the uncommitted copy and doesn't use preallocated maps for
@@ -513,7 +514,8 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
 */
static struct nft_pipapo_elem *pipapo_get(const struct net *net,
					  const struct nft_set *set,
					  const u8 *data, u8 genmask)
					  const u8 *data, u8 genmask,
					  u64 tstamp)
{
	struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT);
	struct nft_pipapo *priv = nft_set_priv(set);
@@ -566,7 +568,7 @@ static struct nft_pipapo_elem *pipapo_get(const struct net *net,
			goto out;

		if (last) {
			if (nft_set_elem_expired(&f->mt[b].e->ext))
			if (__nft_set_elem_expired(&f->mt[b].e->ext, tstamp))
				goto next_match;
			if ((genmask &&
			     !nft_set_elem_active(&f->mt[b].e->ext, genmask)))
@@ -603,7 +605,7 @@ static void *nft_pipapo_get(const struct net *net, const struct nft_set *set,
			    const struct nft_set_elem *elem, unsigned int flags)
{
	return pipapo_get(net, set, (const u8 *)elem->key.val.data,
			  nft_genmask_cur(net));
			  nft_genmask_cur(net), get_jiffies_64());
}

/**
@@ -1197,6 +1199,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
	struct nft_pipapo *priv = nft_set_priv(set);
	struct nft_pipapo_match *m = priv->clone;
	u8 genmask = nft_genmask_next(net);
	u64 tstamp = nft_net_tstamp(net);
	struct nft_pipapo_field *f;
	const u8 *start_p, *end_p;
	int i, bsize_max, err = 0;
@@ -1206,7 +1209,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,
	else
		end = start;

	dup = pipapo_get(net, set, start, genmask);
	dup = pipapo_get(net, set, start, genmask, tstamp);
	if (!IS_ERR(dup)) {
		/* Check if we already have the same exact entry */
		const struct nft_data *dup_key, *dup_end;
@@ -1228,7 +1231,7 @@ static int nft_pipapo_insert(const struct net *net, const struct nft_set *set,

	if (PTR_ERR(dup) == -ENOENT) {
		/* Look for partially overlapping entries */
		dup = pipapo_get(net, set, end, nft_genmask_next(net));
		dup = pipapo_get(net, set, end, nft_genmask_next(net), tstamp);
	}

	if (PTR_ERR(dup) != -ENOENT) {
@@ -1580,6 +1583,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
	struct nft_set *set = (struct nft_set *) _set;
	struct nft_pipapo *priv = nft_set_priv(set);
	struct net *net = read_pnet(&set->net);
	u64 tstamp = nft_net_tstamp(net);
	int rules_f0, first_rule = 0;
	struct nft_trans_gc *gc;

@@ -1613,7 +1617,7 @@ static void pipapo_gc(const struct nft_set *_set, struct nft_pipapo_match *m)
		/* synchronous gc never fails, there is no need to set on
		 * NFT_SET_ELEM_DEAD_BIT.
		 */
		if (nft_set_elem_expired(&e->ext)) {
		if (__nft_set_elem_expired(&e->ext, tstamp)) {
			priv->dirty = true;

			gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
@@ -1772,7 +1776,7 @@ static void *pipapo_deactivate(const struct net *net, const struct nft_set *set,
{
	struct nft_pipapo_elem *e;

	e = pipapo_get(net, set, data, nft_genmask_next(net));
	e = pipapo_get(net, set, data, nft_genmask_next(net), nft_net_tstamp(net));
	if (IS_ERR(e))
		return NULL;

+4 −2
Original line number Diff line number Diff line
@@ -314,6 +314,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
	struct rb_node *node, *next, *parent, **p, *first = NULL;
	struct nft_rbtree *priv = nft_set_priv(set);
	u8 genmask = nft_genmask_next(net);
	u64 tstamp = nft_net_tstamp(net);
	int d, err;

	/* Descend the tree to search for an existing element greater than the
@@ -359,7 +360,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
			continue;

		/* perform garbage collection to avoid bogus overlap reports. */
		if (nft_set_elem_expired(&rbe->ext)) {
		if (__nft_set_elem_expired(&rbe->ext, tstamp)) {
			err = nft_rbtree_gc_elem(set, priv, rbe);
			if (err < 0)
				return err;
@@ -533,6 +534,7 @@ static void *nft_rbtree_deactivate(const struct net *net,
	const struct rb_node *parent = priv->root.rb_node;
	struct nft_rbtree_elem *rbe, *this = elem->priv;
	u8 genmask = nft_genmask_next(net);
	u64 tstamp = nft_net_tstamp(net);
	int d;

	while (parent != NULL) {
@@ -553,7 +555,7 @@ static void *nft_rbtree_deactivate(const struct net *net,
				   nft_rbtree_interval_end(this)) {
				parent = parent->rb_right;
				continue;
			} else if (nft_set_elem_expired(&rbe->ext)) {
			} else if (__nft_set_elem_expired(&rbe->ext, tstamp)) {
				break;
			} else if (!nft_set_elem_active(&rbe->ext, genmask)) {
				parent = parent->rb_left;