Skip to content

Commit 63e4b9d

Browse files
author
Paolo Abeni
committed
Merge tag 'nf-24-02-08' 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) Narrow down target/match revision to u8 in nft_compat. 2) Bail out with unused flags in nft_compat. 3) Restrict layer 4 protocol to u16 in nft_compat. 4) Remove static in pipapo get command that slipped through when reducing set memory footprint. 5) Follow up incremental fix for the ipset performance regression, this includes the missing gc cancellation, from Jozsef Kadlecsik. 6) Allow to filter by zone 0 in ctnetlink, do not interpret zone 0 as no filtering, from Felix Huettner. 7) Reject direction for NFT_CT_ID. 8) Use timestamp to check for set element expiration while transaction is handled to prevent garbage collection from removing set elements that were just added by this transaction. Packet path and netlink dump/get path still use current time to check for expiration. 9) Restore NF_REPEAT in nfnetlink_queue, from Florian Westphal. 10) map_index needs to be percpu and per-set, not just percpu. At this time its possible for a pipapo set to fill the all-zero part with ones and take the 'might have bits set' as 'start-from-zero' area. From Florian Westphal. This includes three patches: - Change scratchpad area to a structure that provides space for a per-set-and-cpu toggle and uses it of the percpu one. - Add a new free helper to prepare for the next patch. - Remove the scratch_aligned pointer and makes AVX2 implementation use the exact same memory addresses for read/store of the matching state. netfilter pull request 24-02-08 * tag 'nf-24-02-08' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: netfilter: nft_set_pipapo: remove scratch_aligned pointer netfilter: nft_set_pipapo: add helper to release pcpu scratch area netfilter: nft_set_pipapo: store index in scratch maps netfilter: nft_set_rbtree: skip end interval element from gc netfilter: nfnetlink_queue: un-break NF_REPEAT netfilter: nf_tables: use timestamp to check for set element timeout netfilter: nft_ct: reject direction for ct id netfilter: ctnetlink: fix filtering for zone 0 netfilter: ipset: Missing gc cancellations fixed netfilter: nft_set_pipapo: remove static in nft_pipapo_get() netfilter: nft_compat: restrict match/target protocol to u16 netfilter: nft_compat: reject unused compat flag netfilter: nft_compat: narrow down revision to unsigned 8-bits ==================== Link: https://lore.kernel.org/r/20240208112834.1433-1-pablo@netfilter.org Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents 2fe8a23 + 5a8cdf6 commit 63e4b9d

File tree

15 files changed

+202
-102
lines changed

15 files changed

+202
-102
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -808,10 +808,16 @@ static inline struct nft_set_elem_expr *nft_set_ext_expr(const struct nft_set_ex
808808
return nft_set_ext(ext, NFT_SET_EXT_EXPRESSIONS);
809809
}
810810

811-
static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
811+
static inline bool __nft_set_elem_expired(const struct nft_set_ext *ext,
812+
u64 tstamp)
812813
{
813814
return nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION) &&
814-
time_is_before_eq_jiffies64(*nft_set_ext_expiration(ext));
815+
time_after_eq64(tstamp, *nft_set_ext_expiration(ext));
816+
}
817+
818+
static inline bool nft_set_elem_expired(const struct nft_set_ext *ext)
819+
{
820+
return __nft_set_elem_expired(ext, get_jiffies_64());
815821
}
816822

817823
static inline struct nft_set_ext *nft_set_elem_ext(const struct nft_set *set,
@@ -1779,6 +1785,7 @@ struct nftables_pernet {
17791785
struct list_head notify_list;
17801786
struct mutex commit_mutex;
17811787
u64 table_handle;
1788+
u64 tstamp;
17821789
unsigned int base_seq;
17831790
unsigned int gc_seq;
17841791
u8 validate_state;
@@ -1791,6 +1798,11 @@ static inline struct nftables_pernet *nft_pernet(const struct net *net)
17911798
return net_generic(net, nf_tables_net_id);
17921799
}
17931800

1801+
static inline u64 nft_net_tstamp(const struct net *net)
1802+
{
1803+
return nft_pernet(net)->tstamp;
1804+
}
1805+
17941806
#define __NFT_REDUCE_READONLY 1UL
17951807
#define NFT_REDUCE_READONLY (void *)__NFT_REDUCE_READONLY
17961808

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,9 +285,11 @@ enum nft_rule_attributes {
285285
/**
286286
* enum nft_rule_compat_flags - nf_tables rule compat flags
287287
*
288+
* @NFT_RULE_COMPAT_F_UNUSED: unused
288289
* @NFT_RULE_COMPAT_F_INV: invert the check result
289290
*/
290291
enum nft_rule_compat_flags {
292+
NFT_RULE_COMPAT_F_UNUSED = (1 << 0),
291293
NFT_RULE_COMPAT_F_INV = (1 << 1),
292294
NFT_RULE_COMPAT_F_MASK = NFT_RULE_COMPAT_F_INV,
293295
};

net/netfilter/ipset/ip_set_core.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,6 +1154,7 @@ static int ip_set_create(struct sk_buff *skb, const struct nfnl_info *info,
11541154
return ret;
11551155

11561156
cleanup:
1157+
set->variant->cancel_gc(set);
11571158
set->variant->destroy(set);
11581159
put_out:
11591160
module_put(set->type->me);
@@ -2378,6 +2379,7 @@ ip_set_net_exit(struct net *net)
23782379
set = ip_set(inst, i);
23792380
if (set) {
23802381
ip_set(inst, i) = NULL;
2382+
set->variant->cancel_gc(set);
23812383
ip_set_destroy_set(set);
23822384
}
23832385
}

net/netfilter/ipset/ip_set_hash_gen.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ mtype_ahash_destroy(struct ip_set *set, struct htable *t, bool ext_destroy)
432432
u32 i;
433433

434434
for (i = 0; i < jhash_size(t->htable_bits); i++) {
435-
n = __ipset_dereference(hbucket(t, i));
435+
n = (__force struct hbucket *)hbucket(t, i);
436436
if (!n)
437437
continue;
438438
if (set->extensions & IPSET_EXT_DESTROY && ext_destroy)
@@ -452,7 +452,7 @@ mtype_destroy(struct ip_set *set)
452452
struct htype *h = set->data;
453453
struct list_head *l, *lt;
454454

455-
mtype_ahash_destroy(set, ipset_dereference_nfnl(h->table), true);
455+
mtype_ahash_destroy(set, (__force struct htable *)h->table, true);
456456
list_for_each_safe(l, lt, &h->ad) {
457457
list_del(l);
458458
kfree(l);

net/netfilter/nf_conntrack_netlink.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -876,6 +876,7 @@ struct ctnetlink_filter_u32 {
876876

877877
struct ctnetlink_filter {
878878
u8 family;
879+
bool zone_filter;
879880

880881
u_int32_t orig_flags;
881882
u_int32_t reply_flags;
@@ -992,9 +993,12 @@ ctnetlink_alloc_filter(const struct nlattr * const cda[], u8 family)
992993
if (err)
993994
goto err_filter;
994995

995-
err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
996-
if (err < 0)
997-
goto err_filter;
996+
if (cda[CTA_ZONE]) {
997+
err = ctnetlink_parse_zone(cda[CTA_ZONE], &filter->zone);
998+
if (err < 0)
999+
goto err_filter;
1000+
filter->zone_filter = true;
1001+
}
9981002

9991003
if (!cda[CTA_FILTER])
10001004
return filter;
@@ -1148,7 +1152,7 @@ static int ctnetlink_filter_match(struct nf_conn *ct, void *data)
11481152
if (filter->family && nf_ct_l3num(ct) != filter->family)
11491153
goto ignore_entry;
11501154

1151-
if (filter->zone.id != NF_CT_DEFAULT_ZONE_ID &&
1155+
if (filter->zone_filter &&
11521156
!nf_ct_zone_equal_any(ct, &filter->zone))
11531157
goto ignore_entry;
11541158

net/netfilter/nf_tables_api.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9827,6 +9827,7 @@ struct nft_trans_gc *nft_trans_gc_catchall_async(struct nft_trans_gc *gc,
98279827
struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
98289828
{
98299829
struct nft_set_elem_catchall *catchall, *next;
9830+
u64 tstamp = nft_net_tstamp(gc->net);
98309831
const struct nft_set *set = gc->set;
98319832
struct nft_elem_priv *elem_priv;
98329833
struct nft_set_ext *ext;
@@ -9836,7 +9837,7 @@ struct nft_trans_gc *nft_trans_gc_catchall_sync(struct nft_trans_gc *gc)
98369837
list_for_each_entry_safe(catchall, next, &set->catchall_list, list) {
98379838
ext = nft_set_elem_ext(set, catchall->elem);
98389839

9839-
if (!nft_set_elem_expired(ext))
9840+
if (!__nft_set_elem_expired(ext, tstamp))
98409841
continue;
98419842

98429843
gc = nft_trans_gc_queue_sync(gc, GFP_KERNEL);
@@ -10622,6 +10623,7 @@ static bool nf_tables_valid_genid(struct net *net, u32 genid)
1062210623
bool genid_ok;
1062310624

1062410625
mutex_lock(&nft_net->commit_mutex);
10626+
nft_net->tstamp = get_jiffies_64();
1062510627

1062610628
genid_ok = genid == 0 || nft_net->base_seq == genid;
1062710629
if (!genid_ok)

net/netfilter/nfnetlink_queue.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,18 +232,25 @@ static void nfqnl_reinject(struct nf_queue_entry *entry, unsigned int verdict)
232232
if (verdict == NF_ACCEPT ||
233233
verdict == NF_REPEAT ||
234234
verdict == NF_STOP) {
235+
unsigned int ct_verdict = verdict;
236+
235237
rcu_read_lock();
236238
ct_hook = rcu_dereference(nf_ct_hook);
237239
if (ct_hook)
238-
verdict = ct_hook->update(entry->state.net, entry->skb);
240+
ct_verdict = ct_hook->update(entry->state.net, entry->skb);
239241
rcu_read_unlock();
240242

241-
switch (verdict & NF_VERDICT_MASK) {
243+
switch (ct_verdict & NF_VERDICT_MASK) {
244+
case NF_ACCEPT:
245+
/* follow userspace verdict, could be REPEAT */
246+
break;
242247
case NF_STOLEN:
243248
nf_queue_entry_free(entry);
244249
return;
250+
default:
251+
verdict = ct_verdict & NF_VERDICT_MASK;
252+
break;
245253
}
246-
247254
}
248255
nf_reinject(entry, verdict);
249256
}

net/netfilter/nft_compat.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ static void nft_target_eval_bridge(const struct nft_expr *expr,
135135

136136
static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = {
137137
[NFTA_TARGET_NAME] = { .type = NLA_NUL_STRING },
138-
[NFTA_TARGET_REV] = { .type = NLA_U32 },
138+
[NFTA_TARGET_REV] = NLA_POLICY_MAX(NLA_BE32, 255),
139139
[NFTA_TARGET_INFO] = { .type = NLA_BINARY },
140140
};
141141

@@ -200,6 +200,7 @@ static const struct nla_policy nft_rule_compat_policy[NFTA_RULE_COMPAT_MAX + 1]
200200
static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
201201
{
202202
struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1];
203+
u32 l4proto;
203204
u32 flags;
204205
int err;
205206

@@ -212,12 +213,18 @@ static int nft_parse_compat(const struct nlattr *attr, u16 *proto, bool *inv)
212213
return -EINVAL;
213214

214215
flags = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_FLAGS]));
215-
if (flags & ~NFT_RULE_COMPAT_F_MASK)
216+
if (flags & NFT_RULE_COMPAT_F_UNUSED ||
217+
flags & ~NFT_RULE_COMPAT_F_MASK)
216218
return -EINVAL;
217219
if (flags & NFT_RULE_COMPAT_F_INV)
218220
*inv = true;
219221

220-
*proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
222+
l4proto = ntohl(nla_get_be32(tb[NFTA_RULE_COMPAT_PROTO]));
223+
if (l4proto > U16_MAX)
224+
return -EINVAL;
225+
226+
*proto = l4proto;
227+
221228
return 0;
222229
}
223230

@@ -419,7 +426,7 @@ static void nft_match_eval(const struct nft_expr *expr,
419426

420427
static const struct nla_policy nft_match_policy[NFTA_MATCH_MAX + 1] = {
421428
[NFTA_MATCH_NAME] = { .type = NLA_NUL_STRING },
422-
[NFTA_MATCH_REV] = { .type = NLA_U32 },
429+
[NFTA_MATCH_REV] = NLA_POLICY_MAX(NLA_BE32, 255),
423430
[NFTA_MATCH_INFO] = { .type = NLA_BINARY },
424431
};
425432

@@ -724,7 +731,7 @@ static int nfnl_compat_get_rcu(struct sk_buff *skb,
724731
static const struct nla_policy nfnl_compat_policy_get[NFTA_COMPAT_MAX+1] = {
725732
[NFTA_COMPAT_NAME] = { .type = NLA_NUL_STRING,
726733
.len = NFT_COMPAT_NAME_MAX-1 },
727-
[NFTA_COMPAT_REV] = { .type = NLA_U32 },
734+
[NFTA_COMPAT_REV] = NLA_POLICY_MAX(NLA_BE32, 255),
728735
[NFTA_COMPAT_TYPE] = { .type = NLA_U32 },
729736
};
730737

net/netfilter/nft_ct.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
476476
break;
477477
#endif
478478
case NFT_CT_ID:
479+
if (tb[NFTA_CT_DIRECTION])
480+
return -EINVAL;
481+
479482
len = sizeof(u32);
480483
break;
481484
default:

net/netfilter/nft_set_hash.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct nft_rhash_cmp_arg {
3636
const struct nft_set *set;
3737
const u32 *key;
3838
u8 genmask;
39+
u64 tstamp;
3940
};
4041

4142
static inline u32 nft_rhash_key(const void *data, u32 len, u32 seed)
@@ -62,7 +63,7 @@ static inline int nft_rhash_cmp(struct rhashtable_compare_arg *arg,
6263
return 1;
6364
if (nft_set_elem_is_dead(&he->ext))
6465
return 1;
65-
if (nft_set_elem_expired(&he->ext))
66+
if (__nft_set_elem_expired(&he->ext, x->tstamp))
6667
return 1;
6768
if (!nft_set_elem_active(&he->ext, x->genmask))
6869
return 1;
@@ -87,6 +88,7 @@ bool nft_rhash_lookup(const struct net *net, const struct nft_set *set,
8788
.genmask = nft_genmask_cur(net),
8889
.set = set,
8990
.key = key,
91+
.tstamp = get_jiffies_64(),
9092
};
9193

9294
he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -106,6 +108,7 @@ nft_rhash_get(const struct net *net, const struct nft_set *set,
106108
.genmask = nft_genmask_cur(net),
107109
.set = set,
108110
.key = elem->key.val.data,
111+
.tstamp = get_jiffies_64(),
109112
};
110113

111114
he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -131,6 +134,7 @@ static bool nft_rhash_update(struct nft_set *set, const u32 *key,
131134
.genmask = NFT_GENMASK_ANY,
132135
.set = set,
133136
.key = key,
137+
.tstamp = get_jiffies_64(),
134138
};
135139

136140
he = rhashtable_lookup(&priv->ht, &arg, nft_rhash_params);
@@ -175,6 +179,7 @@ static int nft_rhash_insert(const struct net *net, const struct nft_set *set,
175179
.genmask = nft_genmask_next(net),
176180
.set = set,
177181
.key = elem->key.val.data,
182+
.tstamp = nft_net_tstamp(net),
178183
};
179184
struct nft_rhash_elem *prev;
180185

@@ -216,6 +221,7 @@ nft_rhash_deactivate(const struct net *net, const struct nft_set *set,
216221
.genmask = nft_genmask_next(net),
217222
.set = set,
218223
.key = elem->key.val.data,
224+
.tstamp = nft_net_tstamp(net),
219225
};
220226

221227
rcu_read_lock();

0 commit comments

Comments
 (0)