diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-07-31 14:38:46 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-08-08 10:47:23 -0400 |
commit | 7926dbfa4bc14e27f4e18a6184a031a1c1e077dc (patch) | |
tree | 2a92a55987f95c1cda659732c3792b72bb60e942 /net | |
parent | b88825de8545ad252c31543fef13cadf4de7a2bc (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.c | 10 | ||||
-rw-r--r-- | net/netfilter/core.c | 11 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 19 | ||||
-rw-r--r-- | net/netfilter/nf_sockopt.c | 8 | ||||
-rw-r--r-- | net/netfilter/x_tables.c | 47 |
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 | ||
36 | int nf_register_afinfo(const struct nf_afinfo *afinfo) | 36 | int 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); | |||
68 | int nf_register_hook(struct nf_hook_ops *reg) | 64 | int 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] = { | |||
71 | static const unsigned int xt_jumpstack_multiplier = 2; | 71 | static const unsigned int xt_jumpstack_multiplier = 2; |
72 | 72 | ||
73 | /* Registration hooks for targets. */ | 73 | /* Registration hooks for targets. */ |
74 | int | 74 | int xt_register_target(struct xt_target *target) |
75 | xt_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 | } |
87 | EXPORT_SYMBOL(xt_register_target); | 83 | EXPORT_SYMBOL(xt_register_target); |
88 | 84 | ||
@@ -125,20 +121,14 @@ xt_unregister_targets(struct xt_target *target, unsigned int n) | |||
125 | } | 121 | } |
126 | EXPORT_SYMBOL(xt_unregister_targets); | 122 | EXPORT_SYMBOL(xt_unregister_targets); |
127 | 123 | ||
128 | int | 124 | int xt_register_match(struct xt_match *match) |
129 | xt_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 | } |
143 | EXPORT_SYMBOL(xt_register_match); | 133 | EXPORT_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: | 892 | unlock: |
915 | mutex_unlock(&xt[table->af].mutex); | 893 | mutex_unlock(&xt[table->af].mutex); |
916 | out_free: | ||
917 | kfree(table); | 894 | kfree(table); |
918 | out: | 895 | out: |
919 | return ERR_PTR(ret); | 896 | return ERR_PTR(ret); |