Skip to content

Commit 8f1f7ee

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains a rather large update with Netfilter fixes, specifically targeted to incorrect RCU usage in several spots and the userspace conntrack helper infrastructure (nfnetlink_cthelper), more specifically they are: 1) expect_class_max is incorrect set via cthelper, as in kernel semantics mandate that this represents the array of expectation classes minus 1. Patch from Liping Zhang. 2) Expectation policy updates via cthelper are currently broken for several reasons: This code allows illegal changes in the policy such as changing the number of expeciation classes, it is leaking the updated policy and such update occurs with no RCU protection at all. Fix this by adding a new nfnl_cthelper_update_policy() that describes what is really legal on the update path. 3) Fix several memory leaks in cthelper, from Jeffy Chen. 4) synchronize_rcu() is missing in the removal path of several modules, this may lead to races since CPU may still be running on code that has just gone. Also from Liping Zhang. 5) Don't use the helper hashtable from cthelper, it is not safe to walk over those bits without the helper mutex. Fix this by introducing a new independent list for userspace helpers. From Liping Zhang. 6) nf_ct_extend_unregister() needs synchronize_rcu() to make sure no packets are walking on any conntrack extension that is gone after module removal, again from Liping. 7) nf_nat_snmp may crash if we fail to unregister the helper due to accidental leftover code, from Gao Feng. 8) Fix leak in nfnetlink_queue with secctx support, from Liping Zhang. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 358e78b + 77c1c03 commit 8f1f7ee

8 files changed

+206
-130
lines changed

net/ipv4/netfilter/nf_nat_snmp_basic.c

+2-18
Original file line numberDiff line numberDiff line change
@@ -1260,16 +1260,6 @@ static const struct nf_conntrack_expect_policy snmp_exp_policy = {
12601260
.timeout = 180,
12611261
};
12621262

1263-
static struct nf_conntrack_helper snmp_helper __read_mostly = {
1264-
.me = THIS_MODULE,
1265-
.help = help,
1266-
.expect_policy = &snmp_exp_policy,
1267-
.name = "snmp",
1268-
.tuple.src.l3num = AF_INET,
1269-
.tuple.src.u.udp.port = cpu_to_be16(SNMP_PORT),
1270-
.tuple.dst.protonum = IPPROTO_UDP,
1271-
};
1272-
12731263
static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
12741264
.me = THIS_MODULE,
12751265
.help = help,
@@ -1288,22 +1278,16 @@ static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
12881278

12891279
static int __init nf_nat_snmp_basic_init(void)
12901280
{
1291-
int ret = 0;
1292-
12931281
BUG_ON(nf_nat_snmp_hook != NULL);
12941282
RCU_INIT_POINTER(nf_nat_snmp_hook, help);
12951283

1296-
ret = nf_conntrack_helper_register(&snmp_trap_helper);
1297-
if (ret < 0) {
1298-
nf_conntrack_helper_unregister(&snmp_helper);
1299-
return ret;
1300-
}
1301-
return ret;
1284+
return nf_conntrack_helper_register(&snmp_trap_helper);
13021285
}
13031286

13041287
static void __exit nf_nat_snmp_basic_fini(void)
13051288
{
13061289
RCU_INIT_POINTER(nf_nat_snmp_hook, NULL);
1290+
synchronize_rcu();
13071291
nf_conntrack_helper_unregister(&snmp_trap_helper);
13081292
}
13091293

net/netfilter/nf_conntrack_ecache.c

+2
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ void nf_conntrack_unregister_notifier(struct net *net,
290290
BUG_ON(notify != new);
291291
RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL);
292292
mutex_unlock(&nf_ct_ecache_mutex);
293+
/* synchronize_rcu() is called from ctnetlink_exit. */
293294
}
294295
EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
295296

@@ -326,6 +327,7 @@ void nf_ct_expect_unregister_notifier(struct net *net,
326327
BUG_ON(notify != new);
327328
RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL);
328329
mutex_unlock(&nf_ct_ecache_mutex);
330+
/* synchronize_rcu() is called from ctnetlink_exit. */
329331
}
330332
EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
331333

net/netfilter/nf_conntrack_extend.c

+10-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id,
5353

5454
rcu_read_lock();
5555
t = rcu_dereference(nf_ct_ext_types[id]);
56-
BUG_ON(t == NULL);
56+
if (!t) {
57+
rcu_read_unlock();
58+
return NULL;
59+
}
60+
5761
off = ALIGN(sizeof(struct nf_ct_ext), t->align);
5862
len = off + t->len + var_alloc_len;
5963
alloc_size = t->alloc_size + var_alloc_len;
@@ -88,7 +92,10 @@ void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id,
8892

8993
rcu_read_lock();
9094
t = rcu_dereference(nf_ct_ext_types[id]);
91-
BUG_ON(t == NULL);
95+
if (!t) {
96+
rcu_read_unlock();
97+
return NULL;
98+
}
9299

93100
newoff = ALIGN(old->len, t->align);
94101
newlen = newoff + t->len + var_alloc_len;
@@ -175,6 +182,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
175182
RCU_INIT_POINTER(nf_ct_ext_types[type->id], NULL);
176183
update_alloc_size(type);
177184
mutex_unlock(&nf_ct_ext_type_mutex);
178-
rcu_barrier(); /* Wait for completion of call_rcu()'s */
185+
synchronize_rcu();
179186
}
180187
EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);

net/netfilter/nf_conntrack_netlink.c

+1
Original file line numberDiff line numberDiff line change
@@ -3442,6 +3442,7 @@ static void __exit ctnetlink_exit(void)
34423442
#ifdef CONFIG_NETFILTER_NETLINK_GLUE_CT
34433443
RCU_INIT_POINTER(nfnl_ct_hook, NULL);
34443444
#endif
3445+
synchronize_rcu();
34453446
}
34463447

34473448
module_init(ctnetlink_init);

net/netfilter/nf_nat_core.c

+2
Original file line numberDiff line numberDiff line change
@@ -903,6 +903,8 @@ static void __exit nf_nat_cleanup(void)
903903
#ifdef CONFIG_XFRM
904904
RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL);
905905
#endif
906+
synchronize_rcu();
907+
906908
for (i = 0; i < NFPROTO_NUMPROTO; i++)
907909
kfree(nf_nat_l4protos[i]);
908910

0 commit comments

Comments
 (0)