netfilter: nft_set_pipapo: prepare pipapo_get helper for on-demand clone
The helper uses priv->clone unconditionally which will fail once we do the clone conditionally on first insert or removal. 'nft get element' from userspace needs to use priv->match since this runs from rcu read side lock section. Prepare for this by passing the match backend data as argument. Signed-off-by: Florian Westphal <fw@strlen.de> Reviewed-by: Stefano Brivio <sbrivio@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
c5444786d0
commit
a238106703
|
@ -504,6 +504,7 @@ out:
|
|||
* pipapo_get() - Get matching element reference given key data
|
||||
* @net: Network namespace
|
||||
* @set: nftables API set representation
|
||||
* @m: storage containing active/existing elements
|
||||
* @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
|
||||
|
@ -517,17 +518,15 @@ out:
|
|||
*/
|
||||
static struct nft_pipapo_elem *pipapo_get(const struct net *net,
|
||||
const struct nft_set *set,
|
||||
const struct nft_pipapo_match *m,
|
||||
const u8 *data, u8 genmask,
|
||||
u64 tstamp, gfp_t gfp)
|
||||
{
|
||||
struct nft_pipapo_elem *ret = ERR_PTR(-ENOENT);
|
||||
struct nft_pipapo *priv = nft_set_priv(set);
|
||||
unsigned long *res_map, *fill_map = NULL;
|
||||
const struct nft_pipapo_match *m;
|
||||
const struct nft_pipapo_field *f;
|
||||
int i;
|
||||
|
||||
m = priv->clone;
|
||||
if (m->bsize_max == 0)
|
||||
return ret;
|
||||
|
||||
|
@ -612,9 +611,11 @@ static struct nft_elem_priv *
|
|||
nft_pipapo_get(const struct net *net, const struct nft_set *set,
|
||||
const struct nft_set_elem *elem, unsigned int flags)
|
||||
{
|
||||
struct nft_pipapo *priv = nft_set_priv(set);
|
||||
struct nft_pipapo_match *m = rcu_dereference(priv->match);
|
||||
struct nft_pipapo_elem *e;
|
||||
|
||||
e = pipapo_get(net, set, (const u8 *)elem->key.val.data,
|
||||
e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data,
|
||||
nft_genmask_cur(net), get_jiffies_64(),
|
||||
GFP_ATOMIC);
|
||||
if (IS_ERR(e))
|
||||
|
@ -1288,7 +1289,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, tstamp, GFP_KERNEL);
|
||||
dup = pipapo_get(net, set, m, start, genmask, tstamp, GFP_KERNEL);
|
||||
if (!IS_ERR(dup)) {
|
||||
/* Check if we already have the same exact entry */
|
||||
const struct nft_data *dup_key, *dup_end;
|
||||
|
@ -1310,7 +1311,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), tstamp,
|
||||
dup = pipapo_get(net, set, m, end, nft_genmask_next(net), tstamp,
|
||||
GFP_KERNEL);
|
||||
}
|
||||
|
||||
|
@ -1862,9 +1863,11 @@ static struct nft_elem_priv *
|
|||
nft_pipapo_deactivate(const struct net *net, const struct nft_set *set,
|
||||
const struct nft_set_elem *elem)
|
||||
{
|
||||
const struct nft_pipapo *priv = nft_set_priv(set);
|
||||
struct nft_pipapo_match *m = priv->clone;
|
||||
struct nft_pipapo_elem *e;
|
||||
|
||||
e = pipapo_get(net, set, (const u8 *)elem->key.val.data,
|
||||
e = pipapo_get(net, set, m, (const u8 *)elem->key.val.data,
|
||||
nft_genmask_next(net), nft_net_tstamp(net), GFP_KERNEL);
|
||||
if (IS_ERR(e))
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in New Issue