Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net, they are:

1) Fix spurious overlap condition in the rbtree tree, from Stefano Brivio.

2) Fix possible uninitialized pointer dereference in nft_lookup.

3) IDLETIMER v1 target matches the Android layout, from
   Maciej Zenczykowski.

4) Dangling pointer in nf_tables_set_alloc_name, from Eric Dumazet.

5) Fix RCU warning splat in ipset find_set_type(), from Amol Grover.

6) Report EOPNOTSUPP on unsupported set flags and object types in sets.

7) Add NFT_SET_CONCAT flag to provide consistent error reporting
   when users defines set with ranges in concatenations in old kernels.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2020-04-07 18:08:06 -07:00
commit c2c1128902
9 changed files with 31 additions and 23 deletions

View File

@ -901,7 +901,7 @@ static inline void nft_set_elem_update_expr(const struct nft_set_ext *ext,
{ {
struct nft_expr *expr; struct nft_expr *expr;
if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) { if (__nft_set_ext_exists(ext, NFT_SET_EXT_EXPR)) {
expr = nft_set_ext_expr(ext); expr = nft_set_ext_expr(ext);
expr->ops->eval(expr, regs, pkt); expr->ops->eval(expr, regs, pkt);
} }

View File

@ -276,6 +276,7 @@ enum nft_rule_compat_attributes {
* @NFT_SET_TIMEOUT: set uses timeouts * @NFT_SET_TIMEOUT: set uses timeouts
* @NFT_SET_EVAL: set can be updated from the evaluation path * @NFT_SET_EVAL: set can be updated from the evaluation path
* @NFT_SET_OBJECT: set contains stateful objects * @NFT_SET_OBJECT: set contains stateful objects
* @NFT_SET_CONCAT: set contains a concatenation
*/ */
enum nft_set_flags { enum nft_set_flags {
NFT_SET_ANONYMOUS = 0x1, NFT_SET_ANONYMOUS = 0x1,
@ -285,6 +286,7 @@ enum nft_set_flags {
NFT_SET_TIMEOUT = 0x10, NFT_SET_TIMEOUT = 0x10,
NFT_SET_EVAL = 0x20, NFT_SET_EVAL = 0x20,
NFT_SET_OBJECT = 0x40, NFT_SET_OBJECT = 0x40,
NFT_SET_CONCAT = 0x80,
}; };
/** /**

View File

@ -48,6 +48,7 @@ struct idletimer_tg_info_v1 {
char label[MAX_IDLETIMER_LABEL_SIZE]; char label[MAX_IDLETIMER_LABEL_SIZE];
__u8 send_nl_msg; /* unused: for compatibility with Android */
__u8 timer_type; __u8 timer_type;
/* for kernel module internal use only */ /* for kernel module internal use only */

View File

@ -86,7 +86,8 @@ find_set_type(const char *name, u8 family, u8 revision)
{ {
struct ip_set_type *type; struct ip_set_type *type;
list_for_each_entry_rcu(type, &ip_set_type_list, list) list_for_each_entry_rcu(type, &ip_set_type_list, list,
lockdep_is_held(&ip_set_type_mutex))
if (STRNCMP(type->name, name) && if (STRNCMP(type->name, name) &&
(type->family == family || (type->family == family ||
type->family == NFPROTO_UNSPEC) && type->family == NFPROTO_UNSPEC) &&

View File

@ -3542,6 +3542,7 @@ cont:
continue; continue;
if (!strcmp(set->name, i->name)) { if (!strcmp(set->name, i->name)) {
kfree(set->name); kfree(set->name);
set->name = NULL;
return -ENFILE; return -ENFILE;
} }
} }
@ -3961,8 +3962,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT | if (flags & ~(NFT_SET_ANONYMOUS | NFT_SET_CONSTANT |
NFT_SET_INTERVAL | NFT_SET_TIMEOUT | NFT_SET_INTERVAL | NFT_SET_TIMEOUT |
NFT_SET_MAP | NFT_SET_EVAL | NFT_SET_MAP | NFT_SET_EVAL |
NFT_SET_OBJECT)) NFT_SET_OBJECT | NFT_SET_CONCAT))
return -EINVAL; return -EOPNOTSUPP;
/* Only one of these operations is supported */ /* Only one of these operations is supported */
if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) == if ((flags & (NFT_SET_MAP | NFT_SET_OBJECT)) ==
(NFT_SET_MAP | NFT_SET_OBJECT)) (NFT_SET_MAP | NFT_SET_OBJECT))
@ -4000,7 +4001,7 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE])); objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE]));
if (objtype == NFT_OBJECT_UNSPEC || if (objtype == NFT_OBJECT_UNSPEC ||
objtype > NFT_OBJECT_MAX) objtype > NFT_OBJECT_MAX)
return -EINVAL; return -EOPNOTSUPP;
} else if (flags & NFT_SET_OBJECT) } else if (flags & NFT_SET_OBJECT)
return -EINVAL; return -EINVAL;
else else

View File

@ -29,7 +29,7 @@ void nft_lookup_eval(const struct nft_expr *expr,
{ {
const struct nft_lookup *priv = nft_expr_priv(expr); const struct nft_lookup *priv = nft_expr_priv(expr);
const struct nft_set *set = priv->set; const struct nft_set *set = priv->set;
const struct nft_set_ext *ext; const struct nft_set_ext *ext = NULL;
bool found; bool found;
found = set->ops->lookup(nft_net(pkt), set, &regs->data[priv->sreg], found = set->ops->lookup(nft_net(pkt), set, &regs->data[priv->sreg],
@ -39,11 +39,13 @@ void nft_lookup_eval(const struct nft_expr *expr,
return; return;
} }
if (set->flags & NFT_SET_MAP) if (ext) {
nft_data_copy(&regs->data[priv->dreg], if (set->flags & NFT_SET_MAP)
nft_set_ext_data(ext), set->dlen); nft_data_copy(&regs->data[priv->dreg],
nft_set_ext_data(ext), set->dlen);
nft_set_elem_update_expr(ext, regs, pkt); nft_set_elem_update_expr(ext, regs, pkt);
}
} }
static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = { static const struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {

View File

@ -81,7 +81,6 @@ static bool nft_bitmap_lookup(const struct net *net, const struct nft_set *set,
u32 idx, off; u32 idx, off;
nft_bitmap_location(set, key, &idx, &off); nft_bitmap_location(set, key, &idx, &off);
*ext = NULL;
return nft_bitmap_active(priv->bitmap, idx, off, genmask); return nft_bitmap_active(priv->bitmap, idx, off, genmask);
} }

View File

@ -218,27 +218,26 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
/* Detect overlaps as we descend the tree. Set the flag in these cases: /* Detect overlaps as we descend the tree. Set the flag in these cases:
* *
* a1. |__ _ _? >|__ _ _ (insert start after existing start) * a1. _ _ __>| ?_ _ __| (insert end before existing end)
* a2. _ _ __>| ?_ _ __| (insert end before existing end) * a2. _ _ ___| ?_ _ _>| (insert end after existing end)
* a3. _ _ ___| ?_ _ _>| (insert end after existing end) * a3. _ _ ___? >|_ _ __| (insert start before existing end)
* a4. >|__ _ _ _ _ __| (insert start before existing end)
* *
* and clear it later on, as we eventually reach the points indicated by * and clear it later on, as we eventually reach the points indicated by
* '?' above, in the cases described below. We'll always meet these * '?' above, in the cases described below. We'll always meet these
* later, locally, due to tree ordering, and overlaps for the intervals * later, locally, due to tree ordering, and overlaps for the intervals
* that are the closest together are always evaluated last. * that are the closest together are always evaluated last.
* *
* b1. |__ _ _! >|__ _ _ (insert start after existing end) * b1. _ _ __>| !_ _ __| (insert end before existing start)
* b2. _ _ __>| !_ _ __| (insert end before existing start) * b2. _ _ ___| !_ _ _>| (insert end after existing start)
* b3. !_____>| (insert end after existing start) * b3. _ _ ___! >|_ _ __| (insert start after existing end)
* *
* Case a4. resolves to b1.: * Case a3. resolves to b3.:
* - if the inserted start element is the leftmost, because the '0' * - if the inserted start element is the leftmost, because the '0'
* element in the tree serves as end element * element in the tree serves as end element
* - otherwise, if an existing end is found. Note that end elements are * - otherwise, if an existing end is found. Note that end elements are
* always inserted after corresponding start elements. * always inserted after corresponding start elements.
* *
* For a new, rightmost pair of elements, we'll hit cases b1. and b3., * For a new, rightmost pair of elements, we'll hit cases b3. and b2.,
* in that order. * in that order.
* *
* The flag is also cleared in two special cases: * The flag is also cleared in two special cases:
@ -262,9 +261,9 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
p = &parent->rb_left; p = &parent->rb_left;
if (nft_rbtree_interval_start(new)) { if (nft_rbtree_interval_start(new)) {
overlap = nft_rbtree_interval_start(rbe) && if (nft_rbtree_interval_end(rbe) &&
nft_set_elem_active(&rbe->ext, nft_set_elem_active(&rbe->ext, genmask))
genmask); overlap = false;
} else { } else {
overlap = nft_rbtree_interval_end(rbe) && overlap = nft_rbtree_interval_end(rbe) &&
nft_set_elem_active(&rbe->ext, nft_set_elem_active(&rbe->ext,

View File

@ -346,6 +346,9 @@ static int idletimer_tg_checkentry_v1(const struct xt_tgchk_param *par)
pr_debug("checkentry targinfo%s\n", info->label); pr_debug("checkentry targinfo%s\n", info->label);
if (info->send_nl_msg)
return -EOPNOTSUPP;
ret = idletimer_tg_helper((struct idletimer_tg_info *)info); ret = idletimer_tg_helper((struct idletimer_tg_info *)info);
if(ret < 0) if(ret < 0)
{ {