mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-23 12:43:55 +08:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Fix gcc-10 compilation warning in nf_conntrack, from Arnd Bergmann. 2) Add NF_FLOW_HW_PENDING to avoid races between stats and deletion commands, from Paul Blakey. 3) Remove WQ_MEM_RECLAIM from the offload workqueue, from Roi Dayan. 4) Infinite loop when removing nf_conntrack module, from Florian Westphal. 5) Set NF_FLOW_TEARDOWN bit on expiration to avoid races when refreshing the timeout from the software path. 6) Missing nft_set_elem_expired() check in the rbtree, from Phil Sutter. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1b54f4fa4d
@ -87,7 +87,7 @@ struct nf_conn {
|
||||
struct hlist_node nat_bysource;
|
||||
#endif
|
||||
/* all members below initialized via memset */
|
||||
u8 __nfct_init_offset[0];
|
||||
struct { } __nfct_init_offset;
|
||||
|
||||
/* If we were expected by an expectation, this will be it */
|
||||
struct nf_conn *master;
|
||||
|
@ -127,6 +127,7 @@ enum nf_flow_flags {
|
||||
NF_FLOW_HW_DYING,
|
||||
NF_FLOW_HW_DEAD,
|
||||
NF_FLOW_HW_REFRESH,
|
||||
NF_FLOW_HW_PENDING,
|
||||
};
|
||||
|
||||
enum flow_offload_type {
|
||||
|
@ -1519,9 +1519,9 @@ __nf_conntrack_alloc(struct net *net,
|
||||
ct->status = 0;
|
||||
ct->timeout = 0;
|
||||
write_pnet(&ct->ct_net, net);
|
||||
memset(&ct->__nfct_init_offset[0], 0,
|
||||
memset(&ct->__nfct_init_offset, 0,
|
||||
offsetof(struct nf_conn, proto) -
|
||||
offsetof(struct nf_conn, __nfct_init_offset[0]));
|
||||
offsetof(struct nf_conn, __nfct_init_offset));
|
||||
|
||||
nf_ct_zone_add(ct, zone);
|
||||
|
||||
@ -2139,8 +2139,19 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data),
|
||||
nf_conntrack_lock(lockp);
|
||||
if (*bucket < nf_conntrack_htable_size) {
|
||||
hlist_nulls_for_each_entry(h, n, &nf_conntrack_hash[*bucket], hnnode) {
|
||||
if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
|
||||
if (NF_CT_DIRECTION(h) != IP_CT_DIR_REPLY)
|
||||
continue;
|
||||
/* All nf_conn objects are added to hash table twice, one
|
||||
* for original direction tuple, once for the reply tuple.
|
||||
*
|
||||
* Exception: In the IPS_NAT_CLASH case, only the reply
|
||||
* tuple is added (the original tuple already existed for
|
||||
* a different object).
|
||||
*
|
||||
* We only need to call the iterator once for each
|
||||
* conntrack, so we just use the 'reply' direction
|
||||
* tuple while iterating.
|
||||
*/
|
||||
ct = nf_ct_tuplehash_to_ctrack(h);
|
||||
if (iter(ct, data))
|
||||
goto found;
|
||||
|
@ -284,7 +284,7 @@ static void flow_offload_del(struct nf_flowtable *flow_table,
|
||||
|
||||
if (nf_flow_has_expired(flow))
|
||||
flow_offload_fixup_ct(flow->ct);
|
||||
else if (test_bit(NF_FLOW_TEARDOWN, &flow->flags))
|
||||
else
|
||||
flow_offload_fixup_ct_timeout(flow->ct);
|
||||
|
||||
flow_offload_free(flow);
|
||||
@ -361,8 +361,10 @@ static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
|
||||
{
|
||||
struct nf_flowtable *flow_table = data;
|
||||
|
||||
if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct) ||
|
||||
test_bit(NF_FLOW_TEARDOWN, &flow->flags)) {
|
||||
if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct))
|
||||
set_bit(NF_FLOW_TEARDOWN, &flow->flags);
|
||||
|
||||
if (test_bit(NF_FLOW_TEARDOWN, &flow->flags)) {
|
||||
if (test_bit(NF_FLOW_HW, &flow->flags)) {
|
||||
if (!test_bit(NF_FLOW_HW_DYING, &flow->flags))
|
||||
nf_flow_offload_del(flow_table, flow);
|
||||
|
@ -817,6 +817,7 @@ static void flow_offload_work_handler(struct work_struct *work)
|
||||
WARN_ON_ONCE(1);
|
||||
}
|
||||
|
||||
clear_bit(NF_FLOW_HW_PENDING, &offload->flow->flags);
|
||||
kfree(offload);
|
||||
}
|
||||
|
||||
@ -831,10 +832,15 @@ nf_flow_offload_work_alloc(struct nf_flowtable *flowtable,
|
||||
{
|
||||
struct flow_offload_work *offload;
|
||||
|
||||
offload = kmalloc(sizeof(struct flow_offload_work), GFP_ATOMIC);
|
||||
if (!offload)
|
||||
if (test_and_set_bit(NF_FLOW_HW_PENDING, &flow->flags))
|
||||
return NULL;
|
||||
|
||||
offload = kmalloc(sizeof(struct flow_offload_work), GFP_ATOMIC);
|
||||
if (!offload) {
|
||||
clear_bit(NF_FLOW_HW_PENDING, &flow->flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
offload->cmd = cmd;
|
||||
offload->flow = flow;
|
||||
offload->priority = flowtable->priority;
|
||||
@ -1056,7 +1062,7 @@ static struct flow_indr_block_entry block_ing_entry = {
|
||||
int nf_flow_table_offload_init(void)
|
||||
{
|
||||
nf_flow_offload_wq = alloc_workqueue("nf_flow_table_offload",
|
||||
WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
|
||||
WQ_UNBOUND, 0);
|
||||
if (!nf_flow_offload_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -79,6 +79,10 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
|
||||
parent = rcu_dereference_raw(parent->rb_left);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nft_set_elem_expired(&rbe->ext))
|
||||
return false;
|
||||
|
||||
if (nft_rbtree_interval_end(rbe)) {
|
||||
if (nft_set_is_anonymous(set))
|
||||
return false;
|
||||
@ -94,6 +98,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
|
||||
|
||||
if (set->flags & NFT_SET_INTERVAL && interval != NULL &&
|
||||
nft_set_elem_active(&interval->ext, genmask) &&
|
||||
!nft_set_elem_expired(&interval->ext) &&
|
||||
nft_rbtree_interval_start(interval)) {
|
||||
*ext = &interval->ext;
|
||||
return true;
|
||||
@ -154,6 +159,9 @@ static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nft_set_elem_expired(&rbe->ext))
|
||||
return false;
|
||||
|
||||
if (!nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) ||
|
||||
(*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END) ==
|
||||
(flags & NFT_SET_ELEM_INTERVAL_END)) {
|
||||
@ -170,6 +178,7 @@ static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
|
||||
|
||||
if (set->flags & NFT_SET_INTERVAL && interval != NULL &&
|
||||
nft_set_elem_active(&interval->ext, genmask) &&
|
||||
!nft_set_elem_expired(&interval->ext) &&
|
||||
((!nft_rbtree_interval_end(interval) &&
|
||||
!(flags & NFT_SET_ELEM_INTERVAL_END)) ||
|
||||
(nft_rbtree_interval_end(interval) &&
|
||||
@ -418,6 +427,8 @@ static void nft_rbtree_walk(const struct nft_ctx *ctx,
|
||||
|
||||
if (iter->count < iter->skip)
|
||||
goto cont;
|
||||
if (nft_set_elem_expired(&rbe->ext))
|
||||
goto cont;
|
||||
if (!nft_set_elem_active(&rbe->ext, iter->genmask))
|
||||
goto cont;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user