mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
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:
commit
cff088d924
@ -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)
|
||||
|
@ -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 &&
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user