netfilter: conntrack: replace notify chain by function pointer
This patch removes the notify chain infrastructure and replace it by a simple function pointer. This issue has been mentioned in the mailing list several times: the use of the notify chain adds too much overhead for something that is only used by ctnetlink. This patch also changes nfnetlink_send(). It seems that gfp_any() returns GFP_KERNEL for user-context request, like those via ctnetlink, inside the RCU read-side section which is not valid. Using GFP_KERNEL is also evil since netlink may schedule(), this leads to "scheduling while atomic" bug reports. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
@@ -6,7 +6,6 @@
|
||||
#define _NF_CONNTRACK_ECACHE_H
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netfilter/nf_conntrack_expect.h>
|
||||
@@ -69,9 +68,13 @@ struct nf_ct_event {
|
||||
int report;
|
||||
};
|
||||
|
||||
extern struct atomic_notifier_head nf_conntrack_chain;
|
||||
extern int nf_conntrack_register_notifier(struct notifier_block *nb);
|
||||
extern int nf_conntrack_unregister_notifier(struct notifier_block *nb);
|
||||
struct nf_ct_event_notifier {
|
||||
int (*fcn)(unsigned int events, struct nf_ct_event *item);
|
||||
};
|
||||
|
||||
extern struct nf_ct_event_notifier *nf_conntrack_event_cb;
|
||||
extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
|
||||
extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
|
||||
|
||||
extern void nf_ct_deliver_cached_events(const struct nf_conn *ct);
|
||||
extern void __nf_ct_event_cache_init(struct nf_conn *ct);
|
||||
@@ -97,13 +100,23 @@ nf_conntrack_event_report(enum ip_conntrack_events event,
|
||||
u32 pid,
|
||||
int report)
|
||||
{
|
||||
struct nf_ct_event item = {
|
||||
.ct = ct,
|
||||
.pid = pid,
|
||||
.report = report
|
||||
};
|
||||
if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct))
|
||||
atomic_notifier_call_chain(&nf_conntrack_chain, event, &item);
|
||||
struct nf_ct_event_notifier *notify;
|
||||
|
||||
rcu_read_lock();
|
||||
notify = rcu_dereference(nf_conntrack_event_cb);
|
||||
if (notify == NULL)
|
||||
goto out_unlock;
|
||||
|
||||
if (nf_ct_is_confirmed(ct) && !nf_ct_is_dying(ct)) {
|
||||
struct nf_ct_event item = {
|
||||
.ct = ct,
|
||||
.pid = pid,
|
||||
.report = report
|
||||
};
|
||||
notify->fcn(event, &item);
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline void
|
||||
@@ -118,9 +131,13 @@ struct nf_exp_event {
|
||||
int report;
|
||||
};
|
||||
|
||||
extern struct atomic_notifier_head nf_ct_expect_chain;
|
||||
extern int nf_ct_expect_register_notifier(struct notifier_block *nb);
|
||||
extern int nf_ct_expect_unregister_notifier(struct notifier_block *nb);
|
||||
struct nf_exp_event_notifier {
|
||||
int (*fcn)(unsigned int events, struct nf_exp_event *item);
|
||||
};
|
||||
|
||||
extern struct nf_exp_event_notifier *nf_expect_event_cb;
|
||||
extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
|
||||
extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
|
||||
|
||||
static inline void
|
||||
nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
|
||||
@@ -128,12 +145,23 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
|
||||
u32 pid,
|
||||
int report)
|
||||
{
|
||||
struct nf_exp_event item = {
|
||||
.exp = exp,
|
||||
.pid = pid,
|
||||
.report = report
|
||||
};
|
||||
atomic_notifier_call_chain(&nf_ct_expect_chain, event, &item);
|
||||
struct nf_exp_event_notifier *notify;
|
||||
|
||||
rcu_read_lock();
|
||||
notify = rcu_dereference(nf_expect_event_cb);
|
||||
if (notify == NULL)
|
||||
goto out_unlock;
|
||||
|
||||
{
|
||||
struct nf_exp_event item = {
|
||||
.exp = exp,
|
||||
.pid = pid,
|
||||
.report = report
|
||||
};
|
||||
notify->fcn(event, &item);
|
||||
}
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
Reference in New Issue
Block a user