diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-03-07 22:50:47 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-03-08 11:51:29 -0500 |
commit | 8b3e07ac908d005bb791410f594cce8744f6806a (patch) | |
tree | 8b1d3cf7295110738dc8a59e3f44f443ded97859 /net | |
parent | 5ece3cafbd88d4da5c734e1810c4a2e6474b57b2 (diff) |
svcrpc: fix rare race on unix_domain creation
Note that "new" here is not yet fully initialized; auth_domain_put
should be called only on auth_domains that have actually been added to
the hash.
Before this fix, two attempts to add the same domain at once could
cause the hlist_del in auth_domain_put to fail.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 30916b06c12b..d100bf2b4e81 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -38,6 +38,14 @@ struct unix_domain { | |||
38 | 38 | ||
39 | extern struct auth_ops svcauth_unix; | 39 | extern struct auth_ops svcauth_unix; |
40 | 40 | ||
41 | static void svcauth_unix_domain_release(struct auth_domain *dom) | ||
42 | { | ||
43 | struct unix_domain *ud = container_of(dom, struct unix_domain, h); | ||
44 | |||
45 | kfree(dom->name); | ||
46 | kfree(ud); | ||
47 | } | ||
48 | |||
41 | struct auth_domain *unix_domain_find(char *name) | 49 | struct auth_domain *unix_domain_find(char *name) |
42 | { | 50 | { |
43 | struct auth_domain *rv; | 51 | struct auth_domain *rv; |
@@ -47,7 +55,7 @@ struct auth_domain *unix_domain_find(char *name) | |||
47 | while(1) { | 55 | while(1) { |
48 | if (rv) { | 56 | if (rv) { |
49 | if (new && rv != &new->h) | 57 | if (new && rv != &new->h) |
50 | auth_domain_put(&new->h); | 58 | svcauth_unix_domain_release(new); |
51 | 59 | ||
52 | if (rv->flavour != &svcauth_unix) { | 60 | if (rv->flavour != &svcauth_unix) { |
53 | auth_domain_put(rv); | 61 | auth_domain_put(rv); |
@@ -74,14 +82,6 @@ struct auth_domain *unix_domain_find(char *name) | |||
74 | } | 82 | } |
75 | EXPORT_SYMBOL_GPL(unix_domain_find); | 83 | EXPORT_SYMBOL_GPL(unix_domain_find); |
76 | 84 | ||
77 | static void svcauth_unix_domain_release(struct auth_domain *dom) | ||
78 | { | ||
79 | struct unix_domain *ud = container_of(dom, struct unix_domain, h); | ||
80 | |||
81 | kfree(dom->name); | ||
82 | kfree(ud); | ||
83 | } | ||
84 | |||
85 | 85 | ||
86 | /************************************************** | 86 | /************************************************** |
87 | * cache for IP address to unix_domain | 87 | * cache for IP address to unix_domain |