netfilter pull request 23-11-15

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEN9lkrMBJgcdVAPub1V2XiooUIOQFAmVVD/4ACgkQ1V2XiooU
 IOQegA/9FUHHllNsrk0hUWKeH+1P54jExmKlIhSfwUJ3RptehF0ARb3uQb0rVPuM
 DwpaMVZ1lhL3TzcFy1HeCNFU6mKxqKhlvzDYvbRcfbNE96eL7l5RfJwWh0UViwWI
 wUtZhznHE6ygdZJ8TZUA+b5vuZkihO2ZNc7rpuBimCQGEXqZfoOpNFVSoNBsWvL5
 3s/qq7ai6rl34ipVlPpFO7Gk94EHHMwa4BhGfTNVRSrG2B9EcPAMAOKVDBCPrGST
 CdVkkn79ajNUhiKSkD3/JC4fMDavT6ZEIzUMFfwIdF1b7Q+5F64lbZaD5gD2bO30
 QAk7ttgq951XnQpLfXC4H4vHdf65GeeYLPSuLqyo/rnkr/+h+hCgnorBwZrzrG3D
 mbqQtUZOsJjrH6vcExuHwlM1LEOSGbGuI/zjSTEXEJG8M3qngxXCeMQun2fB8IIN
 yTB40SPUhvKlR6JdfJRou/WJj9eKZmyuaWP2MaQT7LFftttt24Ndluoo5KCx92IZ
 9LmCm8h93oWKRFAxk3NQQCZbbW0RW8Af+gbmnRI2TjtyDpNrnzPhR3fjopD9wqJH
 xMuW5xeTjqdjFR7jvAaYPnnFOOk0vA0JlZlBNmmNIqp04+BmD4RTVqmqwzNCjHvm
 KqqWGjKOEYOWN2OJawaqu6V5cU0/untb2OG2b5WAhDycF/CnxA0=
 =lwne
 -----END PGP SIGNATURE-----

Merge tag 'nf-23-11-15' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf

Pablo Neira Ayuso says:

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

The following patchset contains Netfilter fixes for net:

1) Remove unused variable causing compilation warning in nft_set_rbtree,
   from Yang Li. This unused variable is a left over from previous
   merge window.

2) Possible return of uninitialized in nf_conntrack_bridge, from
   Linkui Xiao. This is there since nf_conntrack_bridge is available.

3) Fix incorrect pointer math in nft_byteorder, from Dan Carpenter.
   Problem has been there since 2016.

4) Fix bogus error in destroy set element command. Problem is there
   since this new destroy command was added.

5) Fix race condition in ipset between swap and destroy commands and
   add/del/test control plane. This problem is there since ipset was
   merged.

6) Split async and sync catchall GC in two function to fix unsafe
   iteration over RCU. This is a fix-for-fix that was included in
   the previous pull request.

* tag 'nf-23-11-15' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  netfilter: nf_tables: split async and sync catchall in two functions
  netfilter: ipset: fix race condition between swap/destroy and kernel side add/del/test
  netfilter: nf_tables: bogus ENOENT when destroying element which does not exist
  netfilter: nf_tables: fix pointer math issue in nft_byteorder_eval()
  netfilter: nf_conntrack_bridge: initialize err to 0
  netfilter: nft_set_rbtree: Remove unused variable nft_net
====================

Link: https://lore.kernel.org/r/20231115184514.8965-1-pablo@netfilter.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2023-11-16 11:02:52 +01:00
commit cff088d924
7 changed files with 47 additions and 42 deletions

View File

@ -178,9 +178,9 @@ static inline __be32 nft_reg_load_be32(const u32 *sreg)
return *(__force __be32 *)sreg;
}
static inline void nft_reg_store64(u32 *dreg, u64 val)
static inline void nft_reg_store64(u64 *dreg, u64 val)
{
put_unaligned(val, (u64 *)dreg);
put_unaligned(val, dreg);
}
static inline u64 nft_reg_load64(const u32 *sreg)

View File

@ -37,7 +37,7 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
ktime_t tstamp = skb->tstamp;
struct ip_frag_state state;
struct iphdr *iph;
int err;
int err = 0;
/* for offloaded checksums cleanup checksum before fragmentation */
if (skb->ip_summed == CHECKSUM_PARTIAL &&

View File

@ -61,6 +61,8 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET);
ip_set_dereference((inst)->ip_set_list)[id]
#define ip_set_ref_netlink(inst,id) \
rcu_dereference_raw((inst)->ip_set_list)[id]
#define ip_set_dereference_nfnl(p) \
rcu_dereference_check(p, lockdep_nfnl_is_held(NFNL_SUBSYS_IPSET))
/* The set types are implemented in modules and registered set types
* can be found in ip_set_type_list. Adding/deleting types is
@ -708,15 +710,10 @@ __ip_set_put_netlink(struct ip_set *set)
static struct ip_set *
ip_set_rcu_get(struct net *net, ip_set_id_t index)
{
struct ip_set *set;
struct ip_set_net *inst = ip_set_pernet(net);
rcu_read_lock();
/* ip_set_list itself needs to be protected */
set = rcu_dereference(inst->ip_set_list)[index];
rcu_read_unlock();
return set;
/* ip_set_list and the set pointer need to be protected */
return ip_set_dereference_nfnl(inst->ip_set_list)[index];
}
static inline void
@ -1397,6 +1394,9 @@ static int ip_set_swap(struct sk_buff *skb, const struct nfnl_info *info,
ip_set(inst, to_id) = from;
write_unlock_bh(&ip_set_ref_lock);
/* Make sure all readers of the old set pointers are completed. */
synchronize_rcu();
return 0;
}

View File

@ -7263,10 +7263,11 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
if (err < 0) {
NL_SET_BAD_ATTR(extack, attr);
break;
return err;
}
}
return err;
return 0;
}
/*
@ -9679,16 +9680,14 @@ void nft_trans_gc_queue_sync_done(struct nft_trans_gc *trans)
call_rcu(&trans->rcu, nft_trans_gc_trans_free);
}
static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
unsigned int gc_seq,
bool sync)
struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
unsigned int gc_seq)
{
struct nft_set_elem_catchall *catchall, *next;
struct nft_set_elem_catchall *catchall;
const struct nft_set *set = gc->set;
struct nft_elem_priv *elem_priv;
struct nft_set_ext *ext;
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
list_for_each_entry_rcu(catchall, &set->catchall_list, list) {
ext = nft_set_elem_ext(set, catchall->elem);
if (!nft_set_elem_expired(ext))
@ -9698,35 +9697,42 @@ static struct nft_trans_gc *nft_trans_gc_catchall(struct nft_trans_gc *gc,
nft_set_elem_dead(ext);
dead_elem:
if (sync)
gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);
else
gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
gc = nft_trans_gc_queue_async(gc, gc_seq, GFP_ATOMIC);
if (!gc)
return NULL;
elem_priv = catchall->elem;
if (sync) {
nft_setelem_data_deactivate(gc->net, gc->set, elem_priv);
nft_setelem_catchall_destroy(catchall);
}
nft_trans_gc_elem_add(gc, elem_priv);
nft_trans_gc_elem_add(gc, catchall->elem);
}
return gc;
}
struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
unsigned int gc_seq)
{
return nft_trans_gc_catchall(gc, gc_seq, false);
}
struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
{
return nft_trans_gc_catchall(gc, 0, true);
struct nft_set_elem_catchall *catchall, *next;
const struct nft_set *set = gc->set;
struct nft_elem_priv *elem_priv;
struct nft_set_ext *ext;
WARN_ON_ONCE(!lockdep_commit_lock_is_held(gc->net));
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
ext = nft_set_elem_ext(set, catchall->elem);
if (!nft_set_elem_expired(ext))
continue;
gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
if (!gc)
return NULL;
elem_priv = catchall->elem;
nft_setelem_data_deactivate(gc->net, gc->set, elem_priv);
nft_setelem_catchall_destroy(catchall);
nft_trans_gc_elem_add(gc, elem_priv);
}
return gc;
}
static void nf_tables_module_autoload_cleanup(struct net *net)

View File

@ -38,13 +38,14 @@ void nft_byteorder_eval(const struct nft_expr *expr,
switch (priv->size) {
case 8: {
u64 *dst64 = (void *)dst;
u64 src64;
switch (priv->op) {
case NFT_BYTEORDER_NTOH:
for (i = 0; i < priv->len / 8; i++) {
src64 = nft_reg_load64(&src[i]);
nft_reg_store64(&dst[i],
nft_reg_store64(&dst64[i],
be64_to_cpu((__force __be64)src64));
}
break;
@ -52,7 +53,7 @@ void nft_byteorder_eval(const struct nft_expr *expr,
for (i = 0; i < priv->len / 8; i++) {
src64 = (__force __u64)
cpu_to_be64(nft_reg_load64(&src[i]));
nft_reg_store64(&dst[i], src64);
nft_reg_store64(&dst64[i], src64);
}
break;
}

View File

@ -63,7 +63,7 @@ nft_meta_get_eval_time(enum nft_meta_keys key,
{
switch (key) {
case NFT_META_TIME_NS:
nft_reg_store64(dest, ktime_get_real_ns());
nft_reg_store64((u64 *)dest, ktime_get_real_ns());
break;
case NFT_META_TIME_DAY:
nft_reg_store8(dest, nft_meta_weekday());

View File

@ -624,14 +624,12 @@ static void nft_rbtree_gc(struct nft_set *set)
{
struct nft_rbtree *priv = nft_set_priv(set);
struct nft_rbtree_elem *rbe, *rbe_end = NULL;
struct nftables_pernet *nft_net;
struct rb_node *node, *next;
struct nft_trans_gc *gc;
struct net *net;
set = nft_set_container_of(priv);
net = read_pnet(&set->net);
nft_net = nft_pernet(net);
gc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);
if (!gc)