Commit 1e72faed authored by Jakub Kicinski's avatar Jakub Kicinski

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

Pablo Neira Ayuso says:

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

1) Incorrect loop in error path of nft_set_elem_expr_clone(),
   from Colin Ian King.

2) Missing xt_table_get_private_protected() to access table
   private data in x_tables, from Subash Abhinov Kasiviswanathan.

3) Possible oops in ipset hash type resize, from Vasily Averin.

4) Fix shift-out-of-bounds in ipset hash type, also from Vasily.

* git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf:
  netfilter: ipset: fix shift-out-of-bounds in htable_bits()
  netfilter: ipset: fixes possible oops in mtype_resize
  netfilter: x_tables: Update remaining dereference to RCU
  netfilter: nftables: fix incorrect increment of loop counter
====================

Link: https://lore.kernel.org/r/20201218120409.3659-1-pablo@netfilter.orgSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 698285da 5c8193f5
...@@ -1379,7 +1379,7 @@ static int compat_get_entries(struct net *net, ...@@ -1379,7 +1379,7 @@ static int compat_get_entries(struct net *net,
xt_compat_lock(NFPROTO_ARP); xt_compat_lock(NFPROTO_ARP);
t = xt_find_table_lock(net, NFPROTO_ARP, get.name); t = xt_find_table_lock(net, NFPROTO_ARP, get.name);
if (!IS_ERR(t)) { if (!IS_ERR(t)) {
const struct xt_table_info *private = t->private; const struct xt_table_info *private = xt_table_get_private_protected(t);
struct xt_table_info info; struct xt_table_info info;
ret = compat_table_info(private, &info); ret = compat_table_info(private, &info);
......
...@@ -1589,7 +1589,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr, ...@@ -1589,7 +1589,7 @@ compat_get_entries(struct net *net, struct compat_ipt_get_entries __user *uptr,
xt_compat_lock(AF_INET); xt_compat_lock(AF_INET);
t = xt_find_table_lock(net, AF_INET, get.name); t = xt_find_table_lock(net, AF_INET, get.name);
if (!IS_ERR(t)) { if (!IS_ERR(t)) {
const struct xt_table_info *private = t->private; const struct xt_table_info *private = xt_table_get_private_protected(t);
struct xt_table_info info; struct xt_table_info info;
ret = compat_table_info(private, &info); ret = compat_table_info(private, &info);
if (!ret && get.size == info.size) if (!ret && get.size == info.size)
......
...@@ -1598,7 +1598,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr, ...@@ -1598,7 +1598,7 @@ compat_get_entries(struct net *net, struct compat_ip6t_get_entries __user *uptr,
xt_compat_lock(AF_INET6); xt_compat_lock(AF_INET6);
t = xt_find_table_lock(net, AF_INET6, get.name); t = xt_find_table_lock(net, AF_INET6, get.name);
if (!IS_ERR(t)) { if (!IS_ERR(t)) {
const struct xt_table_info *private = t->private; const struct xt_table_info *private = xt_table_get_private_protected(t);
struct xt_table_info info; struct xt_table_info info;
ret = compat_table_info(private, &info); ret = compat_table_info(private, &info);
if (!ret && get.size == info.size) if (!ret && get.size == info.size)
......
...@@ -141,20 +141,6 @@ htable_size(u8 hbits) ...@@ -141,20 +141,6 @@ htable_size(u8 hbits)
return hsize * sizeof(struct hbucket *) + sizeof(struct htable); return hsize * sizeof(struct hbucket *) + sizeof(struct htable);
} }
/* Compute htable_bits from the user input parameter hashsize */
static u8
htable_bits(u32 hashsize)
{
/* Assume that hashsize == 2^htable_bits */
u8 bits = fls(hashsize - 1);
if (jhash_size(bits) != hashsize)
/* Round up to the first 2^n value */
bits = fls(hashsize);
return bits;
}
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
#if IPSET_NET_COUNT > 1 #if IPSET_NET_COUNT > 1
#define __CIDR(cidr, i) (cidr[i]) #define __CIDR(cidr, i) (cidr[i])
...@@ -640,7 +626,7 @@ mtype_resize(struct ip_set *set, bool retried) ...@@ -640,7 +626,7 @@ mtype_resize(struct ip_set *set, bool retried)
struct htype *h = set->data; struct htype *h = set->data;
struct htable *t, *orig; struct htable *t, *orig;
u8 htable_bits; u8 htable_bits;
size_t dsize = set->dsize; size_t hsize, dsize = set->dsize;
#ifdef IP_SET_HASH_WITH_NETS #ifdef IP_SET_HASH_WITH_NETS
u8 flags; u8 flags;
struct mtype_elem *tmp; struct mtype_elem *tmp;
...@@ -664,14 +650,12 @@ mtype_resize(struct ip_set *set, bool retried) ...@@ -664,14 +650,12 @@ mtype_resize(struct ip_set *set, bool retried)
retry: retry:
ret = 0; ret = 0;
htable_bits++; htable_bits++;
if (!htable_bits) { if (!htable_bits)
/* In case we have plenty of memory :-) */ goto hbwarn;
pr_warn("Cannot increase the hashsize of set %s further\n", hsize = htable_size(htable_bits);
set->name); if (!hsize)
ret = -IPSET_ERR_HASH_FULL; goto hbwarn;
goto out; t = ip_set_alloc(hsize);
}
t = ip_set_alloc(htable_size(htable_bits));
if (!t) { if (!t) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
...@@ -813,6 +797,12 @@ mtype_resize(struct ip_set *set, bool retried) ...@@ -813,6 +797,12 @@ mtype_resize(struct ip_set *set, bool retried)
if (ret == -EAGAIN) if (ret == -EAGAIN)
goto retry; goto retry;
goto out; goto out;
hbwarn:
/* In case we have plenty of memory :-) */
pr_warn("Cannot increase the hashsize of set %s further\n", set->name);
ret = -IPSET_ERR_HASH_FULL;
goto out;
} }
/* Get the current number of elements and ext_size in the set */ /* Get the current number of elements and ext_size in the set */
...@@ -1521,7 +1511,11 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, ...@@ -1521,7 +1511,11 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
if (!h) if (!h)
return -ENOMEM; return -ENOMEM;
hbits = htable_bits(hashsize); /* Compute htable_bits from the user input parameter hashsize.
* Assume that hashsize == 2^htable_bits,
* otherwise round up to the first 2^n value.
*/
hbits = fls(hashsize - 1);
hsize = htable_size(hbits); hsize = htable_size(hbits);
if (hsize == 0) { if (hsize == 0) {
kfree(h); kfree(h);
......
...@@ -5254,8 +5254,8 @@ static int nft_set_elem_expr_clone(const struct nft_ctx *ctx, ...@@ -5254,8 +5254,8 @@ static int nft_set_elem_expr_clone(const struct nft_ctx *ctx,
return 0; return 0;
err_expr: err_expr:
for (k = i - 1; k >= 0; k++) for (k = i - 1; k >= 0; k--)
nft_expr_destroy(ctx, expr_array[i]); nft_expr_destroy(ctx, expr_array[k]);
return -ENOMEM; return -ENOMEM;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment