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:
commit
c2c1128902
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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) &&
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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, ®s->data[priv->sreg],
|
found = set->ops->lookup(nft_net(pkt), set, ®s->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(®s->data[priv->dreg],
|
if (set->flags & NFT_SET_MAP)
|
||||||
nft_set_ext_data(ext), set->dlen);
|
nft_data_copy(®s->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] = {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue