Skip to content

Commit 6bba484

Browse files
ummakynesgregkh
authored andcommitted
netfilter: conntrack: revert ct extension genid infrastructure
[ Upstream commit 35e21a4 ] This infrastructure is not used anymore after moving ct timeout and helper to use datapath refcount to track object use. Revert commit c56716c ("netfilter: extensions: introduce extension genid count") this patch disables all ct extensions (leading to NULL) for unconfirmed conntracks, when this is only targeted at ct helper and ct timeout. There is also codebase that dereferences the ct extension without checking for NULL which could lead to crash. Fixes: c56716c ("netfilter: extensions: introduce extension genid count") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 8d86b40 commit 6bba484

3 files changed

Lines changed: 2 additions & 103 deletions

File tree

include/net/netfilter/nf_conntrack_extend.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ enum nf_ct_ext_id {
3838
struct nf_ct_ext {
3939
u8 offset[NF_CT_EXT_NUM];
4040
u8 len;
41-
unsigned int gen_id;
4241
char data[] __aligned(8);
4342
};
4443

@@ -52,28 +51,17 @@ static inline bool nf_ct_ext_exist(const struct nf_conn *ct, u8 id)
5251
return (ct->ext && __nf_ct_ext_exist(ct->ext, id));
5352
}
5453

55-
void *__nf_ct_ext_find(const struct nf_ct_ext *ext, u8 id);
56-
5754
static inline void *nf_ct_ext_find(const struct nf_conn *ct, u8 id)
5855
{
5956
struct nf_ct_ext *ext = ct->ext;
6057

6158
if (!ext || !__nf_ct_ext_exist(ext, id))
6259
return NULL;
6360

64-
if (unlikely(ext->gen_id))
65-
return __nf_ct_ext_find(ext, id);
66-
6761
return (void *)ct->ext + ct->ext->offset[id];
6862
}
6963

7064
/* Add this type, returns pointer to data or NULL. */
7165
void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
7266

73-
/* ext genid. if ext->id != ext_genid, extensions cannot be used
74-
* anymore unless conntrack has CONFIRMED bit set.
75-
*/
76-
extern atomic_t nf_conntrack_ext_genid;
77-
void nf_ct_ext_bump_genid(void);
78-
7967
#endif /* _NF_CONNTRACK_EXTEND_H */

net/netfilter/nf_conntrack_core.c

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -836,33 +836,6 @@ static void __nf_conntrack_hash_insert(struct nf_conn *ct,
836836
&nf_conntrack_hash[reply_hash]);
837837
}
838838

839-
static bool nf_ct_ext_valid_pre(const struct nf_ct_ext *ext)
840-
{
841-
/* if ext->gen_id is not equal to nf_conntrack_ext_genid, some extensions
842-
* may contain stale pointers to e.g. helper that has been removed.
843-
*
844-
* The helper can't clear this because the nf_conn object isn't in
845-
* any hash and synchronize_rcu() isn't enough because associated skb
846-
* might sit in a queue.
847-
*/
848-
return !ext || ext->gen_id == atomic_read(&nf_conntrack_ext_genid);
849-
}
850-
851-
static bool nf_ct_ext_valid_post(struct nf_ct_ext *ext)
852-
{
853-
if (!ext)
854-
return true;
855-
856-
if (ext->gen_id != atomic_read(&nf_conntrack_ext_genid))
857-
return false;
858-
859-
/* inserted into conntrack table, nf_ct_iterate_cleanup()
860-
* will find it. Disable nf_ct_ext_find() id check.
861-
*/
862-
WRITE_ONCE(ext->gen_id, 0);
863-
return true;
864-
}
865-
866839
int
867840
nf_conntrack_hash_check_insert(struct nf_conn *ct)
868841
{
@@ -878,9 +851,6 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
878851

879852
zone = nf_ct_zone(ct);
880853

881-
if (!nf_ct_ext_valid_pre(ct->ext))
882-
return -EAGAIN;
883-
884854
local_bh_disable();
885855
do {
886856
sequence = read_seqcount_begin(&nf_conntrack_generation);
@@ -914,18 +884,6 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct)
914884
goto chaintoolong;
915885
}
916886

917-
/* If genid has changed, we can't insert anymore because ct
918-
* extensions could have stale pointers and nf_ct_iterate_destroy
919-
* might have completed its table scan already.
920-
*
921-
* Increment of the ext genid right after this check is fine:
922-
* nf_ct_iterate_destroy blocks until locks are released.
923-
*/
924-
if (!nf_ct_ext_valid_post(ct->ext)) {
925-
err = -EAGAIN;
926-
goto out;
927-
}
928-
929887
smp_wmb();
930888
/* The caller holds a reference to this object */
931889
refcount_set(&ct->ct_general.use, 2);
@@ -1207,11 +1165,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
12071165
return NF_DROP;
12081166
}
12091167

1210-
if (!nf_ct_ext_valid_pre(ct->ext)) {
1211-
NF_CT_STAT_INC(net, insert_failed);
1212-
goto dying;
1213-
}
1214-
12151168
/* We have to check the DYING flag after unlink to prevent
12161169
* a race against nf_ct_get_next_corpse() possibly called from
12171170
* user context, else we insert an already 'dead' hash, blocking
@@ -1274,16 +1227,6 @@ __nf_conntrack_confirm(struct sk_buff *skb)
12741227
nf_conntrack_double_unlock(hash, reply_hash);
12751228
local_bh_enable();
12761229

1277-
/* ext area is still valid (rcu read lock is held,
1278-
* but will go out of scope soon, we need to remove
1279-
* this conntrack again.
1280-
*/
1281-
if (!nf_ct_ext_valid_post(ct->ext)) {
1282-
nf_ct_kill(ct);
1283-
NF_CT_STAT_INC_ATOMIC(net, drop);
1284-
return NF_DROP;
1285-
}
1286-
12871230
help = nfct_help(ct);
12881231
if (help && help->helper)
12891232
nf_conntrack_event_cache(IPCT_HELPER, ct);
@@ -2493,13 +2436,11 @@ nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data), void *data)
24932436
*/
24942437
synchronize_net();
24952438

2496-
nf_ct_ext_bump_genid();
24972439
iter_data.data = data;
24982440
nf_ct_iterate_cleanup(iter, &iter_data);
24992441

25002442
/* Another cpu might be in a rcu read section with
2501-
* rcu protected pointer cleared in iter callback
2502-
* or hidden via nf_ct_ext_bump_genid() above.
2443+
* rcu protected pointer cleared in iter callback.
25032444
*
25042445
* Wait until those are done.
25052446
*/

net/netfilter/nf_conntrack_extend.c

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727

2828
#define NF_CT_EXT_PREALLOC 128u /* conntrack events are on by default */
2929

30-
atomic_t nf_conntrack_ext_genid __read_mostly = ATOMIC_INIT(1);
31-
3230
static const u8 nf_ct_ext_type_len[NF_CT_EXT_NUM] = {
3331
[NF_CT_EXT_HELPER] = sizeof(struct nf_conn_help),
3432
#if IS_ENABLED(CONFIG_NF_NAT)
@@ -118,10 +116,8 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
118116
if (!new)
119117
return NULL;
120118

121-
if (!ct->ext) {
119+
if (!ct->ext)
122120
memset(new->offset, 0, sizeof(new->offset));
123-
new->gen_id = atomic_read(&nf_conntrack_ext_genid);
124-
}
125121

126122
new->offset[id] = newoff;
127123
new->len = newlen;
@@ -131,29 +127,3 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
131127
return (void *)new + newoff;
132128
}
133129
EXPORT_SYMBOL(nf_ct_ext_add);
134-
135-
/* Use nf_ct_ext_find wrapper. This is only useful for unconfirmed entries. */
136-
void *__nf_ct_ext_find(const struct nf_ct_ext *ext, u8 id)
137-
{
138-
unsigned int gen_id = atomic_read(&nf_conntrack_ext_genid);
139-
unsigned int this_id = READ_ONCE(ext->gen_id);
140-
141-
if (!__nf_ct_ext_exist(ext, id))
142-
return NULL;
143-
144-
if (this_id == 0 || ext->gen_id == gen_id)
145-
return (void *)ext + ext->offset[id];
146-
147-
return NULL;
148-
}
149-
EXPORT_SYMBOL(__nf_ct_ext_find);
150-
151-
void nf_ct_ext_bump_genid(void)
152-
{
153-
unsigned int value = atomic_inc_return(&nf_conntrack_ext_genid);
154-
155-
if (value == UINT_MAX)
156-
atomic_set(&nf_conntrack_ext_genid, 1);
157-
158-
msleep(HZ);
159-
}

0 commit comments

Comments
 (0)