Skip to content

Commit 69b1b21

Browse files
author
Paolo Abeni
committed
Merge tag 'nf-25-07-17' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following batch contains Netfilter fixes for net: 1) Three patches to enhance conntrack selftests for resize and clash resolution, from Florian Westphal. 2) Expand nft_concat_range.sh selftest to improve coverage from error path, from Florian Westphal. 3) Hide clash bit to userspace from netlink dumps until there is a good reason to expose, from Florian Westphal. 4) Revert notification for device registration/unregistration for nftables basechains and flowtables, we decided to go for a better way to handle this through the nfnetlink_hook infrastructure which will come via nf-next, patch from Phil Sutter. 5) Fix crash in conntrack due to race related to SLAB_TYPESAFE_BY_RCU that results in removing a recycled object that is not yet in the hashes. Move IPS_CONFIRM setting after the object is in the hashes. From Florian Westphal. netfilter pull request 25-07-17 * tag 'nf-25-07-17' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nf_conntrack: fix crash due to removal of uninitialised entry Revert "netfilter: nf_tables: Add notifications for hook changes" netfilter: nf_tables: hide clash bit from userspace selftests: netfilter: nft_concat_range.sh: send packets to empty set selftests: netfilter: conntrack_resize.sh: also use udpclash tool selftests: netfilter: add conntrack clash resolution test case selftests: netfilter: conntrack_resize.sh: extend resize test ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 9f735b6 + 2d72afb commit 69b1b21

File tree

15 files changed

+468
-92
lines changed

15 files changed

+468
-92
lines changed

include/net/netfilter/nf_conntrack.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,19 @@ static inline bool nf_ct_is_expired(const struct nf_conn *ct)
306306
/* use after obtaining a reference count */
307307
static inline bool nf_ct_should_gc(const struct nf_conn *ct)
308308
{
309-
return nf_ct_is_expired(ct) && nf_ct_is_confirmed(ct) &&
310-
!nf_ct_is_dying(ct);
309+
if (!nf_ct_is_confirmed(ct))
310+
return false;
311+
312+
/* load ct->timeout after is_confirmed() test.
313+
* Pairs with __nf_conntrack_confirm() which:
314+
* 1. Increases ct->timeout value
315+
* 2. Inserts ct into rcu hlist
316+
* 3. Sets the confirmed bit
317+
* 4. Unlocks the hlist lock
318+
*/
319+
smp_acquire__after_ctrl_dep();
320+
321+
return nf_ct_is_expired(ct) && !nf_ct_is_dying(ct);
311322
}
312323

313324
#define NF_CT_DAY (86400 * HZ)

include/net/netfilter/nf_tables.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,11 +1142,6 @@ int nft_set_catchall_validate(const struct nft_ctx *ctx, struct nft_set *set);
11421142
int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
11431143
void nf_tables_unbind_chain(const struct nft_ctx *ctx, struct nft_chain *chain);
11441144

1145-
struct nft_hook;
1146-
void nf_tables_chain_device_notify(const struct nft_chain *chain,
1147-
const struct nft_hook *hook,
1148-
const struct net_device *dev, int event);
1149-
11501145
enum nft_chain_types {
11511146
NFT_CHAIN_T_DEFAULT = 0,
11521147
NFT_CHAIN_T_ROUTE,

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,6 @@ enum nf_tables_msg_types {
142142
NFT_MSG_DESTROYOBJ,
143143
NFT_MSG_DESTROYFLOWTABLE,
144144
NFT_MSG_GETSETELEM_RESET,
145-
NFT_MSG_NEWDEV,
146-
NFT_MSG_DELDEV,
147145
NFT_MSG_MAX,
148146
};
149147

@@ -1786,18 +1784,10 @@ enum nft_synproxy_attributes {
17861784
* enum nft_device_attributes - nf_tables device netlink attributes
17871785
*
17881786
* @NFTA_DEVICE_NAME: name of this device (NLA_STRING)
1789-
* @NFTA_DEVICE_TABLE: table containing the flowtable or chain hooking into the device (NLA_STRING)
1790-
* @NFTA_DEVICE_FLOWTABLE: flowtable hooking into the device (NLA_STRING)
1791-
* @NFTA_DEVICE_CHAIN: chain hooking into the device (NLA_STRING)
1792-
* @NFTA_DEVICE_SPEC: hook spec matching the device (NLA_STRING)
17931787
*/
17941788
enum nft_devices_attributes {
17951789
NFTA_DEVICE_UNSPEC,
17961790
NFTA_DEVICE_NAME,
1797-
NFTA_DEVICE_TABLE,
1798-
NFTA_DEVICE_FLOWTABLE,
1799-
NFTA_DEVICE_CHAIN,
1800-
NFTA_DEVICE_SPEC,
18011791
__NFTA_DEVICE_MAX
18021792
};
18031793
#define NFTA_DEVICE_MAX (__NFTA_DEVICE_MAX - 1)

include/uapi/linux/netfilter/nfnetlink.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ enum nfnetlink_groups {
2525
#define NFNLGRP_ACCT_QUOTA NFNLGRP_ACCT_QUOTA
2626
NFNLGRP_NFTRACE,
2727
#define NFNLGRP_NFTRACE NFNLGRP_NFTRACE
28-
NFNLGRP_NFT_DEV,
29-
#define NFNLGRP_NFT_DEV NFNLGRP_NFT_DEV
3028
__NFNLGRP_MAX,
3129
};
3230
#define NFNLGRP_MAX (__NFNLGRP_MAX - 1)

net/netfilter/nf_conntrack_core.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,6 +1124,12 @@ static int nf_ct_resolve_clash_harder(struct sk_buff *skb, u32 repl_idx)
11241124

11251125
hlist_nulls_add_head_rcu(&loser_ct->tuplehash[IP_CT_DIR_REPLY].hnnode,
11261126
&nf_conntrack_hash[repl_idx]);
1127+
/* confirmed bit must be set after hlist add, not before:
1128+
* loser_ct can still be visible to other cpu due to
1129+
* SLAB_TYPESAFE_BY_RCU.
1130+
*/
1131+
smp_mb__before_atomic();
1132+
set_bit(IPS_CONFIRMED_BIT, &loser_ct->status);
11271133

11281134
NF_CT_STAT_INC(net, clash_resolve);
11291135
return NF_ACCEPT;
@@ -1260,8 +1266,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
12601266
* user context, else we insert an already 'dead' hash, blocking
12611267
* further use of that particular connection -JM.
12621268
*/
1263-
ct->status |= IPS_CONFIRMED;
1264-
12651269
if (unlikely(nf_ct_is_dying(ct))) {
12661270
NF_CT_STAT_INC(net, insert_failed);
12671271
goto dying;
@@ -1293,19 +1297,29 @@ __nf_conntrack_confirm(struct sk_buff *skb)
12931297
}
12941298
}
12951299

1296-
/* Timer relative to confirmation time, not original
1300+
/* Timeout is relative to confirmation time, not original
12971301
setting time, otherwise we'd get timer wrap in
12981302
weird delay cases. */
12991303
ct->timeout += nfct_time_stamp;
13001304

13011305
__nf_conntrack_insert_prepare(ct);
13021306

13031307
/* Since the lookup is lockless, hash insertion must be done after
1304-
* starting the timer and setting the CONFIRMED bit. The RCU barriers
1305-
* guarantee that no other CPU can find the conntrack before the above
1306-
* stores are visible.
1308+
* setting ct->timeout. The RCU barriers guarantee that no other CPU
1309+
* can find the conntrack before the above stores are visible.
13071310
*/
13081311
__nf_conntrack_hash_insert(ct, hash, reply_hash);
1312+
1313+
/* IPS_CONFIRMED unset means 'ct not (yet) in hash', conntrack lookups
1314+
* skip entries that lack this bit. This happens when a CPU is looking
1315+
* at a stale entry that is being recycled due to SLAB_TYPESAFE_BY_RCU
1316+
* or when another CPU encounters this entry right after the insertion
1317+
* but before the set-confirm-bit below. This bit must not be set until
1318+
* after __nf_conntrack_hash_insert().
1319+
*/
1320+
smp_mb__before_atomic();
1321+
set_bit(IPS_CONFIRMED_BIT, &ct->status);
1322+
13091323
nf_conntrack_double_unlock(hash, reply_hash);
13101324
local_bh_enable();
13111325

net/netfilter/nf_tables_api.c

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -9686,64 +9686,6 @@ struct nf_hook_ops *nft_hook_find_ops_rcu(const struct nft_hook *hook,
96869686
}
96879687
EXPORT_SYMBOL_GPL(nft_hook_find_ops_rcu);
96889688

9689-
static void
9690-
nf_tables_device_notify(const struct nft_table *table, int attr,
9691-
const char *name, const struct nft_hook *hook,
9692-
const struct net_device *dev, int event)
9693-
{
9694-
struct net *net = dev_net(dev);
9695-
struct nlmsghdr *nlh;
9696-
struct sk_buff *skb;
9697-
u16 flags = 0;
9698-
9699-
if (!nfnetlink_has_listeners(net, NFNLGRP_NFT_DEV))
9700-
return;
9701-
9702-
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
9703-
if (!skb)
9704-
goto err;
9705-
9706-
event = event == NETDEV_REGISTER ? NFT_MSG_NEWDEV : NFT_MSG_DELDEV;
9707-
event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, event);
9708-
nlh = nfnl_msg_put(skb, 0, 0, event, flags, table->family,
9709-
NFNETLINK_V0, nft_base_seq(net));
9710-
if (!nlh)
9711-
goto err;
9712-
9713-
if (nla_put_string(skb, NFTA_DEVICE_TABLE, table->name) ||
9714-
nla_put_string(skb, attr, name) ||
9715-
nla_put(skb, NFTA_DEVICE_SPEC, hook->ifnamelen, hook->ifname) ||
9716-
nla_put_string(skb, NFTA_DEVICE_NAME, dev->name))
9717-
goto err;
9718-
9719-
nlmsg_end(skb, nlh);
9720-
nfnetlink_send(skb, net, 0, NFNLGRP_NFT_DEV,
9721-
nlmsg_report(nlh), GFP_KERNEL);
9722-
return;
9723-
err:
9724-
if (skb)
9725-
kfree_skb(skb);
9726-
nfnetlink_set_err(net, 0, NFNLGRP_NFT_DEV, -ENOBUFS);
9727-
}
9728-
9729-
void
9730-
nf_tables_chain_device_notify(const struct nft_chain *chain,
9731-
const struct nft_hook *hook,
9732-
const struct net_device *dev, int event)
9733-
{
9734-
nf_tables_device_notify(chain->table, NFTA_DEVICE_CHAIN,
9735-
chain->name, hook, dev, event);
9736-
}
9737-
9738-
static void
9739-
nf_tables_flowtable_device_notify(const struct nft_flowtable *ft,
9740-
const struct nft_hook *hook,
9741-
const struct net_device *dev, int event)
9742-
{
9743-
nf_tables_device_notify(ft->table, NFTA_DEVICE_FLOWTABLE,
9744-
ft->name, hook, dev, event);
9745-
}
9746-
97479689
static int nft_flowtable_event(unsigned long event, struct net_device *dev,
97489690
struct nft_flowtable *flowtable, bool changename)
97499691
{
@@ -9791,7 +9733,6 @@ static int nft_flowtable_event(unsigned long event, struct net_device *dev,
97919733
list_add_tail_rcu(&ops->list, &hook->ops_list);
97929734
break;
97939735
}
9794-
nf_tables_flowtable_device_notify(flowtable, hook, dev, event);
97959736
break;
97969737
}
97979738
return 0;

net/netfilter/nf_tables_trace.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,9 @@ static int nf_trace_fill_ct_info(struct sk_buff *nlskb,
127127
if (nla_put_be32(nlskb, NFTA_TRACE_CT_ID, (__force __be32)id))
128128
return -1;
129129

130+
/* Kernel implementation detail, withhold this from userspace for now */
131+
status &= ~IPS_NAT_CLASH;
132+
130133
if (status && nla_put_be32(nlskb, NFTA_TRACE_CT_STATUS, htonl(status)))
131134
return -1;
132135
}

net/netfilter/nfnetlink.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = {
8686
[NFNLGRP_NFTABLES] = NFNL_SUBSYS_NFTABLES,
8787
[NFNLGRP_ACCT_QUOTA] = NFNL_SUBSYS_ACCT,
8888
[NFNLGRP_NFTRACE] = NFNL_SUBSYS_NFTABLES,
89-
[NFNLGRP_NFT_DEV] = NFNL_SUBSYS_NFTABLES,
9089
};
9190

9291
static struct nfnl_net *nfnl_pernet(struct net *net)

net/netfilter/nft_chain_filter.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,6 @@ static int nft_netdev_event(unsigned long event, struct net_device *dev,
363363
list_add_tail_rcu(&ops->list, &hook->ops_list);
364364
break;
365365
}
366-
nf_tables_chain_device_notify(&basechain->chain,
367-
hook, dev, event);
368366
break;
369367
}
370368
return 0;

tools/testing/selftests/net/netfilter/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ conntrack_dump_flush
55
conntrack_reverse_clash
66
sctp_collision
77
nf_queue
8+
udpclash

0 commit comments

Comments
 (0)