Commit 0e60ebe0 authored by Eric Dumazet's avatar Eric Dumazet Committed by Patrick McHardy

netfilter: add __rcu annotations

Add some __rcu annotations and use helpers to reduce number of sparse
warnings (CONFIG_SPARSE_RCU_POINTER=y)
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
parent 9811600f
...@@ -265,7 +265,7 @@ struct nf_afinfo { ...@@ -265,7 +265,7 @@ struct nf_afinfo {
int route_key_size; int route_key_size;
}; };
extern const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO]; extern const struct nf_afinfo __rcu *nf_afinfo[NFPROTO_NUMPROTO];
static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family) static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family)
{ {
return rcu_dereference(nf_afinfo[family]); return rcu_dereference(nf_afinfo[family]);
...@@ -355,9 +355,9 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family) ...@@ -355,9 +355,9 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
#endif /*CONFIG_NETFILTER*/ #endif /*CONFIG_NETFILTER*/
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); extern void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu;
extern void nf_ct_attach(struct sk_buff *, struct sk_buff *); extern void nf_ct_attach(struct sk_buff *, struct sk_buff *);
extern void (*nf_ct_destroy)(struct nf_conntrack *); extern void (*nf_ct_destroy)(struct nf_conntrack *) __rcu;
#else #else
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {} static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
#endif #endif
......
...@@ -67,7 +67,7 @@ struct nf_ct_event_notifier { ...@@ -67,7 +67,7 @@ struct nf_ct_event_notifier {
int (*fcn)(unsigned int events, struct nf_ct_event *item); int (*fcn)(unsigned int events, struct nf_ct_event *item);
}; };
extern struct nf_ct_event_notifier *nf_conntrack_event_cb; extern struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb); 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_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
...@@ -167,7 +167,7 @@ struct nf_exp_event_notifier { ...@@ -167,7 +167,7 @@ struct nf_exp_event_notifier {
int (*fcn)(unsigned int events, struct nf_exp_event *item); int (*fcn)(unsigned int events, struct nf_exp_event *item);
}; };
extern struct nf_exp_event_notifier *nf_expect_event_cb; extern struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb); 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); extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
......
...@@ -73,7 +73,7 @@ struct nf_conntrack_l3proto { ...@@ -73,7 +73,7 @@ struct nf_conntrack_l3proto {
struct module *me; struct module *me;
}; };
extern struct nf_conntrack_l3proto *nf_ct_l3protos[AF_MAX]; extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX];
/* Protocol registration. */ /* Protocol registration. */
extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto);
......
...@@ -212,7 +212,7 @@ EXPORT_SYMBOL(skb_make_writable); ...@@ -212,7 +212,7 @@ EXPORT_SYMBOL(skb_make_writable);
/* This does not belong here, but locally generated errors need it if connection /* This does not belong here, but locally generated errors need it if connection
tracking in use: without this, connection may not be in hash table, and hence tracking in use: without this, connection may not be in hash table, and hence
manufactured ICMP or RST packets will not be associated with it. */ manufactured ICMP or RST packets will not be associated with it. */
void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *); void (*ip_ct_attach)(struct sk_buff *, struct sk_buff *) __rcu __read_mostly;
EXPORT_SYMBOL(ip_ct_attach); EXPORT_SYMBOL(ip_ct_attach);
void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
...@@ -229,7 +229,7 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) ...@@ -229,7 +229,7 @@ void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb)
} }
EXPORT_SYMBOL(nf_ct_attach); EXPORT_SYMBOL(nf_ct_attach);
void (*nf_ct_destroy)(struct nf_conntrack *); void (*nf_ct_destroy)(struct nf_conntrack *) __rcu __read_mostly;
EXPORT_SYMBOL(nf_ct_destroy); EXPORT_SYMBOL(nf_ct_destroy);
void nf_conntrack_destroy(struct nf_conntrack *nfct) void nf_conntrack_destroy(struct nf_conntrack *nfct)
......
...@@ -482,7 +482,7 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq) ...@@ -482,7 +482,7 @@ static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
struct hlist_node *n; struct hlist_node *n;
for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
n = rcu_dereference(net->ct.expect_hash[st->bucket].first); n = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
if (n) if (n)
return n; return n;
} }
...@@ -495,11 +495,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq, ...@@ -495,11 +495,11 @@ static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
struct net *net = seq_file_net(seq); struct net *net = seq_file_net(seq);
struct ct_expect_iter_state *st = seq->private; struct ct_expect_iter_state *st = seq->private;
head = rcu_dereference(head->next); head = rcu_dereference(hlist_next_rcu(head));
while (head == NULL) { while (head == NULL) {
if (++st->bucket >= nf_ct_expect_hsize) if (++st->bucket >= nf_ct_expect_hsize)
return NULL; return NULL;
head = rcu_dereference(net->ct.expect_hash[st->bucket].first); head = rcu_dereference(hlist_first_rcu(&net->ct.expect_hash[st->bucket]));
} }
return head; return head;
} }
......
...@@ -166,6 +166,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto ...@@ -166,6 +166,7 @@ static void nf_ct_l3proto_unregister_sysctl(struct nf_conntrack_l3proto *l3proto
int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
{ {
int ret = 0; int ret = 0;
struct nf_conntrack_l3proto *old;
if (proto->l3proto >= AF_MAX) if (proto->l3proto >= AF_MAX)
return -EBUSY; return -EBUSY;
...@@ -174,7 +175,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto) ...@@ -174,7 +175,9 @@ int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto)
return -EINVAL; return -EINVAL;
mutex_lock(&nf_ct_proto_mutex); mutex_lock(&nf_ct_proto_mutex);
if (nf_ct_l3protos[proto->l3proto] != &nf_conntrack_l3proto_generic) { old = rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
lockdep_is_held(&nf_ct_proto_mutex));
if (old != &nf_conntrack_l3proto_generic) {
ret = -EBUSY; ret = -EBUSY;
goto out_unlock; goto out_unlock;
} }
...@@ -201,7 +204,9 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto) ...@@ -201,7 +204,9 @@ void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto)
BUG_ON(proto->l3proto >= AF_MAX); BUG_ON(proto->l3proto >= AF_MAX);
mutex_lock(&nf_ct_proto_mutex); mutex_lock(&nf_ct_proto_mutex);
BUG_ON(nf_ct_l3protos[proto->l3proto] != proto); BUG_ON(rcu_dereference_protected(nf_ct_l3protos[proto->l3proto],
lockdep_is_held(&nf_ct_proto_mutex)
) != proto);
rcu_assign_pointer(nf_ct_l3protos[proto->l3proto], rcu_assign_pointer(nf_ct_l3protos[proto->l3proto],
&nf_conntrack_l3proto_generic); &nf_conntrack_l3proto_generic);
nf_ct_l3proto_unregister_sysctl(proto); nf_ct_l3proto_unregister_sysctl(proto);
...@@ -299,8 +304,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto) ...@@ -299,8 +304,10 @@ int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *l4proto)
smp_wmb(); smp_wmb();
nf_ct_protos[l4proto->l3proto] = proto_array; nf_ct_protos[l4proto->l3proto] = proto_array;
} else if (nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != } else if (rcu_dereference_protected(
&nf_conntrack_l4proto_generic) { nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
lockdep_is_held(&nf_ct_proto_mutex)
) != &nf_conntrack_l4proto_generic) {
ret = -EBUSY; ret = -EBUSY;
goto out_unlock; goto out_unlock;
} }
...@@ -331,7 +338,10 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto) ...@@ -331,7 +338,10 @@ void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *l4proto)
BUG_ON(l4proto->l3proto >= PF_MAX); BUG_ON(l4proto->l3proto >= PF_MAX);
mutex_lock(&nf_ct_proto_mutex); mutex_lock(&nf_ct_proto_mutex);
BUG_ON(nf_ct_protos[l4proto->l3proto][l4proto->l4proto] != l4proto); BUG_ON(rcu_dereference_protected(
nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
lockdep_is_held(&nf_ct_proto_mutex)
) != l4proto);
rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto], rcu_assign_pointer(nf_ct_protos[l4proto->l3proto][l4proto->l4proto],
&nf_conntrack_l4proto_generic); &nf_conntrack_l4proto_generic);
nf_ct_l4proto_unregister_sysctl(l4proto); nf_ct_l4proto_unregister_sysctl(l4proto);
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_acct.h> #include <net/netfilter/nf_conntrack_acct.h>
#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_zones.h>
#include <linux/rculist_nulls.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -56,7 +57,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq) ...@@ -56,7 +57,7 @@ static struct hlist_nulls_node *ct_get_first(struct seq_file *seq)
for (st->bucket = 0; for (st->bucket = 0;
st->bucket < net->ct.htable_size; st->bucket < net->ct.htable_size;
st->bucket++) { st->bucket++) {
n = rcu_dereference(net->ct.hash[st->bucket].first); n = rcu_dereference(hlist_nulls_first_rcu(&net->ct.hash[st->bucket]));
if (!is_a_nulls(n)) if (!is_a_nulls(n))
return n; return n;
} }
...@@ -69,13 +70,15 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq, ...@@ -69,13 +70,15 @@ static struct hlist_nulls_node *ct_get_next(struct seq_file *seq,
struct net *net = seq_file_net(seq); struct net *net = seq_file_net(seq);
struct ct_iter_state *st = seq->private; struct ct_iter_state *st = seq->private;
head = rcu_dereference(head->next); head = rcu_dereference(hlist_nulls_next_rcu(head));
while (is_a_nulls(head)) { while (is_a_nulls(head)) {
if (likely(get_nulls_value(head) == st->bucket)) { if (likely(get_nulls_value(head) == st->bucket)) {
if (++st->bucket >= net->ct.htable_size) if (++st->bucket >= net->ct.htable_size)
return NULL; return NULL;
} }
head = rcu_dereference(net->ct.hash[st->bucket].first); head = rcu_dereference(
hlist_nulls_first_rcu(
&net->ct.hash[st->bucket]));
} }
return head; return head;
} }
......
...@@ -161,7 +161,8 @@ static int seq_show(struct seq_file *s, void *v) ...@@ -161,7 +161,8 @@ static int seq_show(struct seq_file *s, void *v)
struct nf_logger *t; struct nf_logger *t;
int ret; int ret;
logger = nf_loggers[*pos]; logger = rcu_dereference_protected(nf_loggers[*pos],
lockdep_is_held(&nf_log_mutex));
if (!logger) if (!logger)
ret = seq_printf(s, "%2lld NONE (", *pos); ret = seq_printf(s, "%2lld NONE (", *pos);
...@@ -249,7 +250,8 @@ static int nf_log_proc_dostring(ctl_table *table, int write, ...@@ -249,7 +250,8 @@ static int nf_log_proc_dostring(ctl_table *table, int write,
mutex_unlock(&nf_log_mutex); mutex_unlock(&nf_log_mutex);
} else { } else {
mutex_lock(&nf_log_mutex); mutex_lock(&nf_log_mutex);
logger = nf_loggers[tindex]; logger = rcu_dereference_protected(nf_loggers[tindex],
lockdep_is_held(&nf_log_mutex));
if (!logger) if (!logger)
table->data = "NONE"; table->data = "NONE";
else else
......
...@@ -27,14 +27,17 @@ static DEFINE_MUTEX(queue_handler_mutex); ...@@ -27,14 +27,17 @@ static DEFINE_MUTEX(queue_handler_mutex);
int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) int nf_register_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
{ {
int ret; int ret;
const struct nf_queue_handler *old;
if (pf >= ARRAY_SIZE(queue_handler)) if (pf >= ARRAY_SIZE(queue_handler))
return -EINVAL; return -EINVAL;
mutex_lock(&queue_handler_mutex); mutex_lock(&queue_handler_mutex);
if (queue_handler[pf] == qh) old = rcu_dereference_protected(queue_handler[pf],
lockdep_is_held(&queue_handler_mutex));
if (old == qh)
ret = -EEXIST; ret = -EEXIST;
else if (queue_handler[pf]) else if (old)
ret = -EBUSY; ret = -EBUSY;
else { else {
rcu_assign_pointer(queue_handler[pf], qh); rcu_assign_pointer(queue_handler[pf], qh);
...@@ -49,11 +52,15 @@ EXPORT_SYMBOL(nf_register_queue_handler); ...@@ -49,11 +52,15 @@ EXPORT_SYMBOL(nf_register_queue_handler);
/* The caller must flush their queue before this */ /* The caller must flush their queue before this */
int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh) int nf_unregister_queue_handler(u_int8_t pf, const struct nf_queue_handler *qh)
{ {
const struct nf_queue_handler *old;
if (pf >= ARRAY_SIZE(queue_handler)) if (pf >= ARRAY_SIZE(queue_handler))
return -EINVAL; return -EINVAL;
mutex_lock(&queue_handler_mutex); mutex_lock(&queue_handler_mutex);
if (queue_handler[pf] && queue_handler[pf] != qh) { old = rcu_dereference_protected(queue_handler[pf],
lockdep_is_held(&queue_handler_mutex));
if (old && old != qh) {
mutex_unlock(&queue_handler_mutex); mutex_unlock(&queue_handler_mutex);
return -EINVAL; return -EINVAL;
} }
...@@ -73,7 +80,10 @@ void nf_unregister_queue_handlers(const struct nf_queue_handler *qh) ...@@ -73,7 +80,10 @@ void nf_unregister_queue_handlers(const struct nf_queue_handler *qh)
mutex_lock(&queue_handler_mutex); mutex_lock(&queue_handler_mutex);
for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) { for (pf = 0; pf < ARRAY_SIZE(queue_handler); pf++) {
if (queue_handler[pf] == qh) if (rcu_dereference_protected(
queue_handler[pf],
lockdep_is_held(&queue_handler_mutex)
) == qh)
rcu_assign_pointer(queue_handler[pf], NULL); rcu_assign_pointer(queue_handler[pf], NULL);
} }
mutex_unlock(&queue_handler_mutex); mutex_unlock(&queue_handler_mutex);
......
...@@ -874,19 +874,19 @@ static struct hlist_node *get_first(struct iter_state *st) ...@@ -874,19 +874,19 @@ static struct hlist_node *get_first(struct iter_state *st)
for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) { for (st->bucket = 0; st->bucket < INSTANCE_BUCKETS; st->bucket++) {
if (!hlist_empty(&instance_table[st->bucket])) if (!hlist_empty(&instance_table[st->bucket]))
return rcu_dereference_bh(instance_table[st->bucket].first); return rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
} }
return NULL; return NULL;
} }
static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h) static struct hlist_node *get_next(struct iter_state *st, struct hlist_node *h)
{ {
h = rcu_dereference_bh(h->next); h = rcu_dereference_bh(hlist_next_rcu(h));
while (!h) { while (!h) {
if (++st->bucket >= INSTANCE_BUCKETS) if (++st->bucket >= INSTANCE_BUCKETS)
return NULL; return NULL;
h = rcu_dereference_bh(instance_table[st->bucket].first); h = rcu_dereference_bh(hlist_first_rcu(&instance_table[st->bucket]));
} }
return h; return h;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment