aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2014-07-31 14:38:46 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2014-08-08 10:47:23 -0400
commit7926dbfa4bc14e27f4e18a6184a031a1c1e077dc (patch)
tree2a92a55987f95c1cda659732c3792b72bb60e942 /net
parentb88825de8545ad252c31543fef13cadf4de7a2bc (diff)
netfilter: don't use mutex_lock_interruptible()
Eric Dumazet reports that getsockopt() or setsockopt() sometimes returns -EINTR instead of -ENOPROTOOPT, causing headaches to application developers. This patch replaces all the mutex_lock_interruptible() by mutex_lock() in the netfilter tree, as there is no reason we should sleep for a long time there. Reported-by: Eric Dumazet <edumazet@google.com> Suggested-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Acked-by: Julian Anastasov <ja@ssi.bg>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/netfilter/ebtables.c10
-rw-r--r--net/netfilter/core.c11
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c19
-rw-r--r--net/netfilter/nf_sockopt.c8
-rw-r--r--net/netfilter/x_tables.c47
5 files changed, 22 insertions, 73 deletions
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 1059ed3bc255..6d69631b9f4d 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -327,10 +327,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error,
327 char name[EBT_FUNCTION_MAXNAMELEN]; 327 char name[EBT_FUNCTION_MAXNAMELEN];
328 } *e; 328 } *e;
329 329
330 *error = mutex_lock_interruptible(mutex); 330 mutex_lock(mutex);
331 if (*error != 0)
332 return NULL;
333
334 list_for_each_entry(e, head, list) { 331 list_for_each_entry(e, head, list) {
335 if (strcmp(e->name, name) == 0) 332 if (strcmp(e->name, name) == 0)
336 return e; 333 return e;
@@ -1203,10 +1200,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table)
1203 1200
1204 table->private = newinfo; 1201 table->private = newinfo;
1205 rwlock_init(&table->lock); 1202 rwlock_init(&table->lock);
1206 ret = mutex_lock_interruptible(&ebt_mutex); 1203 mutex_lock(&ebt_mutex);
1207 if (ret != 0)
1208 goto free_chainstack;
1209
1210 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { 1204 list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
1211 if (strcmp(t->name, table->name) == 0) { 1205 if (strcmp(t->name, table->name) == 0) {
1212 ret = -EEXIST; 1206 ret = -EEXIST;
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 1fbab0cdd302..a93c97f106d4 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -35,11 +35,7 @@ EXPORT_SYMBOL_GPL(nf_ipv6_ops);
35 35
36int nf_register_afinfo(const struct nf_afinfo *afinfo) 36int nf_register_afinfo(const struct nf_afinfo *afinfo)
37{ 37{
38 int err; 38 mutex_lock(&afinfo_mutex);
39
40 err = mutex_lock_interruptible(&afinfo_mutex);
41 if (err < 0)
42 return err;
43 RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo); 39 RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo);
44 mutex_unlock(&afinfo_mutex); 40 mutex_unlock(&afinfo_mutex);
45 return 0; 41 return 0;
@@ -68,11 +64,8 @@ static DEFINE_MUTEX(nf_hook_mutex);
68int nf_register_hook(struct nf_hook_ops *reg) 64int nf_register_hook(struct nf_hook_ops *reg)
69{ 65{
70 struct nf_hook_ops *elem; 66 struct nf_hook_ops *elem;
71 int err;
72 67
73 err = mutex_lock_interruptible(&nf_hook_mutex); 68 mutex_lock(&nf_hook_mutex);
74 if (err < 0)
75 return err;
76 list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) { 69 list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) {
77 if (reg->priority < elem->priority) 70 if (reg->priority < elem->priority)
78 break; 71 break;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 8416307fdd1d..fd3f444a4f96 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -2271,10 +2271,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2271 cmd == IP_VS_SO_SET_STOPDAEMON) { 2271 cmd == IP_VS_SO_SET_STOPDAEMON) {
2272 struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; 2272 struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg;
2273 2273
2274 if (mutex_lock_interruptible(&ipvs->sync_mutex)) { 2274 mutex_lock(&ipvs->sync_mutex);
2275 ret = -ERESTARTSYS;
2276 goto out_dec;
2277 }
2278 if (cmd == IP_VS_SO_SET_STARTDAEMON) 2275 if (cmd == IP_VS_SO_SET_STARTDAEMON)
2279 ret = start_sync_thread(net, dm->state, dm->mcast_ifn, 2276 ret = start_sync_thread(net, dm->state, dm->mcast_ifn,
2280 dm->syncid); 2277 dm->syncid);
@@ -2284,11 +2281,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len)
2284 goto out_dec; 2281 goto out_dec;
2285 } 2282 }
2286 2283
2287 if (mutex_lock_interruptible(&__ip_vs_mutex)) { 2284 mutex_lock(&__ip_vs_mutex);
2288 ret = -ERESTARTSYS;
2289 goto out_dec;
2290 }
2291
2292 if (cmd == IP_VS_SO_SET_FLUSH) { 2285 if (cmd == IP_VS_SO_SET_FLUSH) {
2293 /* Flush the virtual service */ 2286 /* Flush the virtual service */
2294 ret = ip_vs_flush(net, false); 2287 ret = ip_vs_flush(net, false);
@@ -2573,9 +2566,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2573 struct ip_vs_daemon_user d[2]; 2566 struct ip_vs_daemon_user d[2];
2574 2567
2575 memset(&d, 0, sizeof(d)); 2568 memset(&d, 0, sizeof(d));
2576 if (mutex_lock_interruptible(&ipvs->sync_mutex)) 2569 mutex_lock(&ipvs->sync_mutex);
2577 return -ERESTARTSYS;
2578
2579 if (ipvs->sync_state & IP_VS_STATE_MASTER) { 2570 if (ipvs->sync_state & IP_VS_STATE_MASTER) {
2580 d[0].state = IP_VS_STATE_MASTER; 2571 d[0].state = IP_VS_STATE_MASTER;
2581 strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, 2572 strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn,
@@ -2594,9 +2585,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2594 return ret; 2585 return ret;
2595 } 2586 }
2596 2587
2597 if (mutex_lock_interruptible(&__ip_vs_mutex)) 2588 mutex_lock(&__ip_vs_mutex);
2598 return -ERESTARTSYS;
2599
2600 switch (cmd) { 2589 switch (cmd) {
2601 case IP_VS_SO_GET_VERSION: 2590 case IP_VS_SO_GET_VERSION:
2602 { 2591 {
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c
index f042ae521557..c68c1e58b362 100644
--- a/net/netfilter/nf_sockopt.c
+++ b/net/netfilter/nf_sockopt.c
@@ -26,9 +26,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg)
26 struct nf_sockopt_ops *ops; 26 struct nf_sockopt_ops *ops;
27 int ret = 0; 27 int ret = 0;
28 28
29 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) 29 mutex_lock(&nf_sockopt_mutex);
30 return -EINTR;
31
32 list_for_each_entry(ops, &nf_sockopts, list) { 30 list_for_each_entry(ops, &nf_sockopts, list) {
33 if (ops->pf == reg->pf 31 if (ops->pf == reg->pf
34 && (overlap(ops->set_optmin, ops->set_optmax, 32 && (overlap(ops->set_optmin, ops->set_optmax,
@@ -65,9 +63,7 @@ static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, u_int8_t pf,
65{ 63{
66 struct nf_sockopt_ops *ops; 64 struct nf_sockopt_ops *ops;
67 65
68 if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) 66 mutex_lock(&nf_sockopt_mutex);
69 return ERR_PTR(-EINTR);
70
71 list_for_each_entry(ops, &nf_sockopts, list) { 67 list_for_each_entry(ops, &nf_sockopts, list) {
72 if (ops->pf == pf) { 68 if (ops->pf == pf) {
73 if (!try_module_get(ops->owner)) 69 if (!try_module_get(ops->owner))
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 47b978bc3100..272ae4d6fdf4 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -71,18 +71,14 @@ static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
71static const unsigned int xt_jumpstack_multiplier = 2; 71static const unsigned int xt_jumpstack_multiplier = 2;
72 72
73/* Registration hooks for targets. */ 73/* Registration hooks for targets. */
74int 74int xt_register_target(struct xt_target *target)
75xt_register_target(struct xt_target *target)
76{ 75{
77 u_int8_t af = target->family; 76 u_int8_t af = target->family;
78 int ret;
79 77
80 ret = mutex_lock_interruptible(&xt[af].mutex); 78 mutex_lock(&xt[af].mutex);
81 if (ret != 0)
82 return ret;
83 list_add(&target->list, &xt[af].target); 79 list_add(&target->list, &xt[af].target);
84 mutex_unlock(&xt[af].mutex); 80 mutex_unlock(&xt[af].mutex);
85 return ret; 81 return 0;
86} 82}
87EXPORT_SYMBOL(xt_register_target); 83EXPORT_SYMBOL(xt_register_target);
88 84
@@ -125,20 +121,14 @@ xt_unregister_targets(struct xt_target *target, unsigned int n)
125} 121}
126EXPORT_SYMBOL(xt_unregister_targets); 122EXPORT_SYMBOL(xt_unregister_targets);
127 123
128int 124int xt_register_match(struct xt_match *match)
129xt_register_match(struct xt_match *match)
130{ 125{
131 u_int8_t af = match->family; 126 u_int8_t af = match->family;
132 int ret;
133
134 ret = mutex_lock_interruptible(&xt[af].mutex);
135 if (ret != 0)
136 return ret;
137 127
128 mutex_lock(&xt[af].mutex);
138 list_add(&match->list, &xt[af].match); 129 list_add(&match->list, &xt[af].match);
139 mutex_unlock(&xt[af].mutex); 130 mutex_unlock(&xt[af].mutex);
140 131 return 0;
141 return ret;
142} 132}
143EXPORT_SYMBOL(xt_register_match); 133EXPORT_SYMBOL(xt_register_match);
144 134
@@ -194,9 +184,7 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision)
194 struct xt_match *m; 184 struct xt_match *m;
195 int err = -ENOENT; 185 int err = -ENOENT;
196 186
197 if (mutex_lock_interruptible(&xt[af].mutex) != 0) 187 mutex_lock(&xt[af].mutex);
198 return ERR_PTR(-EINTR);
199
200 list_for_each_entry(m, &xt[af].match, list) { 188 list_for_each_entry(m, &xt[af].match, list) {
201 if (strcmp(m->name, name) == 0) { 189 if (strcmp(m->name, name) == 0) {
202 if (m->revision == revision) { 190 if (m->revision == revision) {
@@ -239,9 +227,7 @@ struct xt_target *xt_find_target(u8 af, const char *name, u8 revision)
239 struct xt_target *t; 227 struct xt_target *t;
240 int err = -ENOENT; 228 int err = -ENOENT;
241 229
242 if (mutex_lock_interruptible(&xt[af].mutex) != 0) 230 mutex_lock(&xt[af].mutex);
243 return ERR_PTR(-EINTR);
244
245 list_for_each_entry(t, &xt[af].target, list) { 231 list_for_each_entry(t, &xt[af].target, list) {
246 if (strcmp(t->name, name) == 0) { 232 if (strcmp(t->name, name) == 0) {
247 if (t->revision == revision) { 233 if (t->revision == revision) {
@@ -323,10 +309,7 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target,
323{ 309{
324 int have_rev, best = -1; 310 int have_rev, best = -1;
325 311
326 if (mutex_lock_interruptible(&xt[af].mutex) != 0) { 312 mutex_lock(&xt[af].mutex);
327 *err = -EINTR;
328 return 1;
329 }
330 if (target == 1) 313 if (target == 1)
331 have_rev = target_revfn(af, name, revision, &best); 314 have_rev = target_revfn(af, name, revision, &best);
332 else 315 else
@@ -732,9 +715,7 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
732{ 715{
733 struct xt_table *t; 716 struct xt_table *t;
734 717
735 if (mutex_lock_interruptible(&xt[af].mutex) != 0) 718 mutex_lock(&xt[af].mutex);
736 return ERR_PTR(-EINTR);
737
738 list_for_each_entry(t, &net->xt.tables[af], list) 719 list_for_each_entry(t, &net->xt.tables[af], list)
739 if (strcmp(t->name, name) == 0 && try_module_get(t->me)) 720 if (strcmp(t->name, name) == 0 && try_module_get(t->me))
740 return t; 721 return t;
@@ -883,10 +864,7 @@ struct xt_table *xt_register_table(struct net *net,
883 goto out; 864 goto out;
884 } 865 }
885 866
886 ret = mutex_lock_interruptible(&xt[table->af].mutex); 867 mutex_lock(&xt[table->af].mutex);
887 if (ret != 0)
888 goto out_free;
889
890 /* Don't autoload: we'd eat our tail... */ 868 /* Don't autoload: we'd eat our tail... */
891 list_for_each_entry(t, &net->xt.tables[table->af], list) { 869 list_for_each_entry(t, &net->xt.tables[table->af], list) {
892 if (strcmp(t->name, table->name) == 0) { 870 if (strcmp(t->name, table->name) == 0) {
@@ -911,9 +889,8 @@ struct xt_table *xt_register_table(struct net *net,
911 mutex_unlock(&xt[table->af].mutex); 889 mutex_unlock(&xt[table->af].mutex);
912 return table; 890 return table;
913 891
914 unlock: 892unlock:
915 mutex_unlock(&xt[table->af].mutex); 893 mutex_unlock(&xt[table->af].mutex);
916out_free:
917 kfree(table); 894 kfree(table);
918out: 895out:
919 return ERR_PTR(ret); 896 return ERR_PTR(ret);