diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 14:28:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-04-30 14:28:08 -0400 |
commit | 8728f986fe29d872dc5dc72941088eb9cb8bc723 (patch) | |
tree | b0742c9c396bc8e4fddfbe1da57777270a803970 /net/sunrpc/auth_gss | |
parent | e72859b87f57826f41e07a87bbaed65ed1133f85 (diff) | |
parent | 721ccfb79b6f74f4052de70236d24047e73682d4 (diff) |
Merge tag 'nfs-for-3.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes and cleanups from Trond Myklebust:
- NLM: stable fix for NFSv2/v3 blocking locks
- NFSv4.x: stable fixes for the delegation recall error handling code
- NFSv4.x: Security flavour negotiation fixes and cleanups by Chuck
Lever
- SUNRPC: A number of RPCSEC_GSS fixes and cleanups also from Chuck
- NFSv4.x assorted state management and reboot recovery bugfixes
- NFSv4.1: In cases where we have already looked up a file, and hold a
valid filehandle, use the new open-by-filehandle operation instead of
opening by name.
- Allow the NFSv4.1 callback thread to freeze
- NFSv4.x: ensure that file unlock waits for readahead to complete
- NFSv4.1: ensure that the RPC layer doesn't override the NFS session
table size negotiation by limiting the number of slots.
- NFSv4.x: Fix SETATTR spec compatibility issues
* tag 'nfs-for-3.10-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (67 commits)
NFSv4: Warn once about servers that incorrectly apply open mode to setattr
NFSv4: Servers should only check SETATTR stateid open mode on size change
NFSv4: Don't recheck permissions on open in case of recovery cached open
NFSv4.1: Don't do a delegated open for NFS4_OPEN_CLAIM_DELEG_CUR_FH modes
NFSv4.1: Use the more efficient open_noattr call for open-by-filehandle
NFS: Retry SETCLIENTID with AUTH_SYS instead of AUTH_NONE
NFSv4: Ensure that we clear the NFS_OPEN_STATE flag when appropriate
LOCKD: Ensure that nlmclnt_block resets block->b_status after a server reboot
NFSv4: Ensure the LOCK call cannot use the delegation stateid
NFSv4: Use the open stateid if the delegation has the wrong mode
nfs: Send atime and mtime as a 64bit value
NFSv4: Record the OPEN create mode used in the nfs4_opendata structure
NFSv4.1: Set the RPC_CLNT_CREATE_INFINITE_SLOTS flag for NFSv4.1 transports
SUNRPC: Allow rpc_create() to request that TCP slots be unlimited
SUNRPC: Fix a livelock problem in the xprt->backlog queue
NFSv4: Fix handling of revoked delegations by setattr
NFSv4 release the sequence id in the return on close case
nfs: remove unnecessary check for NULL inode->i_flock from nfs_delegation_claim_locks
NFS: Ensure that NFS file unlock waits for readahead to complete
NFS: Add functionality to allow waiting on all outstanding reads to complete
...
Diffstat (limited to 'net/sunrpc/auth_gss')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 3 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_mech.c | 6 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_mech_switch.c | 119 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/svcauth_gss.c | 4 |
4 files changed, 101 insertions, 31 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 5257d2982ba5..51415b07174e 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -1641,6 +1641,8 @@ static const struct rpc_authops authgss_ops = { | |||
1641 | .pipes_create = gss_pipes_dentries_create, | 1641 | .pipes_create = gss_pipes_dentries_create, |
1642 | .pipes_destroy = gss_pipes_dentries_destroy, | 1642 | .pipes_destroy = gss_pipes_dentries_destroy, |
1643 | .list_pseudoflavors = gss_mech_list_pseudoflavors, | 1643 | .list_pseudoflavors = gss_mech_list_pseudoflavors, |
1644 | .info2flavor = gss_mech_info2flavor, | ||
1645 | .flavor2info = gss_mech_flavor2info, | ||
1644 | }; | 1646 | }; |
1645 | 1647 | ||
1646 | static const struct rpc_credops gss_credops = { | 1648 | static const struct rpc_credops gss_credops = { |
@@ -1733,6 +1735,7 @@ static void __exit exit_rpcsec_gss(void) | |||
1733 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1735 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
1734 | } | 1736 | } |
1735 | 1737 | ||
1738 | MODULE_ALIAS("rpc-auth-6"); | ||
1736 | MODULE_LICENSE("GPL"); | 1739 | MODULE_LICENSE("GPL"); |
1737 | module_param_named(expired_cred_retry_delay, | 1740 | module_param_named(expired_cred_retry_delay, |
1738 | gss_expired_cred_retry_delay, | 1741 | gss_expired_cred_retry_delay, |
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index d3611f11a8df..33255ff889c0 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -729,16 +729,19 @@ static const struct gss_api_ops gss_kerberos_ops = { | |||
729 | static struct pf_desc gss_kerberos_pfs[] = { | 729 | static struct pf_desc gss_kerberos_pfs[] = { |
730 | [0] = { | 730 | [0] = { |
731 | .pseudoflavor = RPC_AUTH_GSS_KRB5, | 731 | .pseudoflavor = RPC_AUTH_GSS_KRB5, |
732 | .qop = GSS_C_QOP_DEFAULT, | ||
732 | .service = RPC_GSS_SVC_NONE, | 733 | .service = RPC_GSS_SVC_NONE, |
733 | .name = "krb5", | 734 | .name = "krb5", |
734 | }, | 735 | }, |
735 | [1] = { | 736 | [1] = { |
736 | .pseudoflavor = RPC_AUTH_GSS_KRB5I, | 737 | .pseudoflavor = RPC_AUTH_GSS_KRB5I, |
738 | .qop = GSS_C_QOP_DEFAULT, | ||
737 | .service = RPC_GSS_SVC_INTEGRITY, | 739 | .service = RPC_GSS_SVC_INTEGRITY, |
738 | .name = "krb5i", | 740 | .name = "krb5i", |
739 | }, | 741 | }, |
740 | [2] = { | 742 | [2] = { |
741 | .pseudoflavor = RPC_AUTH_GSS_KRB5P, | 743 | .pseudoflavor = RPC_AUTH_GSS_KRB5P, |
744 | .qop = GSS_C_QOP_DEFAULT, | ||
742 | .service = RPC_GSS_SVC_PRIVACY, | 745 | .service = RPC_GSS_SVC_PRIVACY, |
743 | .name = "krb5p", | 746 | .name = "krb5p", |
744 | }, | 747 | }, |
@@ -750,11 +753,12 @@ MODULE_ALIAS("rpc-auth-gss-krb5p"); | |||
750 | MODULE_ALIAS("rpc-auth-gss-390003"); | 753 | MODULE_ALIAS("rpc-auth-gss-390003"); |
751 | MODULE_ALIAS("rpc-auth-gss-390004"); | 754 | MODULE_ALIAS("rpc-auth-gss-390004"); |
752 | MODULE_ALIAS("rpc-auth-gss-390005"); | 755 | MODULE_ALIAS("rpc-auth-gss-390005"); |
756 | MODULE_ALIAS("rpc-auth-gss-1.2.840.113554.1.2.2"); | ||
753 | 757 | ||
754 | static struct gss_api_mech gss_kerberos_mech = { | 758 | static struct gss_api_mech gss_kerberos_mech = { |
755 | .gm_name = "krb5", | 759 | .gm_name = "krb5", |
756 | .gm_owner = THIS_MODULE, | 760 | .gm_owner = THIS_MODULE, |
757 | .gm_oid = {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}, | 761 | .gm_oid = { 9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }, |
758 | .gm_ops = &gss_kerberos_ops, | 762 | .gm_ops = &gss_kerberos_ops, |
759 | .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), | 763 | .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs), |
760 | .gm_pfs = gss_kerberos_pfs, | 764 | .gm_pfs = gss_kerberos_pfs, |
diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c index f0f4eee63a35..79881d6e68a1 100644 --- a/net/sunrpc/auth_gss/gss_mech_switch.c +++ b/net/sunrpc/auth_gss/gss_mech_switch.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
38 | #include <linux/module.h> | 38 | #include <linux/module.h> |
39 | #include <linux/oid_registry.h> | ||
39 | #include <linux/sunrpc/msg_prot.h> | 40 | #include <linux/sunrpc/msg_prot.h> |
40 | #include <linux/sunrpc/gss_asn1.h> | 41 | #include <linux/sunrpc/gss_asn1.h> |
41 | #include <linux/sunrpc/auth_gss.h> | 42 | #include <linux/sunrpc/auth_gss.h> |
@@ -102,8 +103,13 @@ out: | |||
102 | return status; | 103 | return status; |
103 | } | 104 | } |
104 | 105 | ||
105 | int | 106 | /** |
106 | gss_mech_register(struct gss_api_mech *gm) | 107 | * gss_mech_register - register a GSS mechanism |
108 | * @gm: GSS mechanism handle | ||
109 | * | ||
110 | * Returns zero if successful, or a negative errno. | ||
111 | */ | ||
112 | int gss_mech_register(struct gss_api_mech *gm) | ||
107 | { | 113 | { |
108 | int status; | 114 | int status; |
109 | 115 | ||
@@ -116,11 +122,14 @@ gss_mech_register(struct gss_api_mech *gm) | |||
116 | dprintk("RPC: registered gss mechanism %s\n", gm->gm_name); | 122 | dprintk("RPC: registered gss mechanism %s\n", gm->gm_name); |
117 | return 0; | 123 | return 0; |
118 | } | 124 | } |
119 | |||
120 | EXPORT_SYMBOL_GPL(gss_mech_register); | 125 | EXPORT_SYMBOL_GPL(gss_mech_register); |
121 | 126 | ||
122 | void | 127 | /** |
123 | gss_mech_unregister(struct gss_api_mech *gm) | 128 | * gss_mech_unregister - release a GSS mechanism |
129 | * @gm: GSS mechanism handle | ||
130 | * | ||
131 | */ | ||
132 | void gss_mech_unregister(struct gss_api_mech *gm) | ||
124 | { | 133 | { |
125 | spin_lock(®istered_mechs_lock); | 134 | spin_lock(®istered_mechs_lock); |
126 | list_del(&gm->gm_list); | 135 | list_del(&gm->gm_list); |
@@ -128,18 +137,14 @@ gss_mech_unregister(struct gss_api_mech *gm) | |||
128 | dprintk("RPC: unregistered gss mechanism %s\n", gm->gm_name); | 137 | dprintk("RPC: unregistered gss mechanism %s\n", gm->gm_name); |
129 | gss_mech_free(gm); | 138 | gss_mech_free(gm); |
130 | } | 139 | } |
131 | |||
132 | EXPORT_SYMBOL_GPL(gss_mech_unregister); | 140 | EXPORT_SYMBOL_GPL(gss_mech_unregister); |
133 | 141 | ||
134 | struct gss_api_mech * | 142 | static struct gss_api_mech *gss_mech_get(struct gss_api_mech *gm) |
135 | gss_mech_get(struct gss_api_mech *gm) | ||
136 | { | 143 | { |
137 | __module_get(gm->gm_owner); | 144 | __module_get(gm->gm_owner); |
138 | return gm; | 145 | return gm; |
139 | } | 146 | } |
140 | 147 | ||
141 | EXPORT_SYMBOL_GPL(gss_mech_get); | ||
142 | |||
143 | static struct gss_api_mech * | 148 | static struct gss_api_mech * |
144 | _gss_mech_get_by_name(const char *name) | 149 | _gss_mech_get_by_name(const char *name) |
145 | { | 150 | { |
@@ -169,12 +174,16 @@ struct gss_api_mech * gss_mech_get_by_name(const char *name) | |||
169 | } | 174 | } |
170 | return gm; | 175 | return gm; |
171 | } | 176 | } |
172 | EXPORT_SYMBOL_GPL(gss_mech_get_by_name); | ||
173 | 177 | ||
174 | struct gss_api_mech * | 178 | static struct gss_api_mech *gss_mech_get_by_OID(struct rpcsec_gss_oid *obj) |
175 | gss_mech_get_by_OID(struct xdr_netobj *obj) | ||
176 | { | 179 | { |
177 | struct gss_api_mech *pos, *gm = NULL; | 180 | struct gss_api_mech *pos, *gm = NULL; |
181 | char buf[32]; | ||
182 | |||
183 | if (sprint_oid(obj->data, obj->len, buf, sizeof(buf)) < 0) | ||
184 | return NULL; | ||
185 | dprintk("RPC: %s(%s)\n", __func__, buf); | ||
186 | request_module("rpc-auth-gss-%s", buf); | ||
178 | 187 | ||
179 | spin_lock(®istered_mechs_lock); | 188 | spin_lock(®istered_mechs_lock); |
180 | list_for_each_entry(pos, ®istered_mechs, gm_list) { | 189 | list_for_each_entry(pos, ®istered_mechs, gm_list) { |
@@ -188,11 +197,8 @@ gss_mech_get_by_OID(struct xdr_netobj *obj) | |||
188 | } | 197 | } |
189 | spin_unlock(®istered_mechs_lock); | 198 | spin_unlock(®istered_mechs_lock); |
190 | return gm; | 199 | return gm; |
191 | |||
192 | } | 200 | } |
193 | 201 | ||
194 | EXPORT_SYMBOL_GPL(gss_mech_get_by_OID); | ||
195 | |||
196 | static inline int | 202 | static inline int |
197 | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) | 203 | mech_supports_pseudoflavor(struct gss_api_mech *gm, u32 pseudoflavor) |
198 | { | 204 | { |
@@ -237,8 +243,6 @@ gss_mech_get_by_pseudoflavor(u32 pseudoflavor) | |||
237 | return gm; | 243 | return gm; |
238 | } | 244 | } |
239 | 245 | ||
240 | EXPORT_SYMBOL_GPL(gss_mech_get_by_pseudoflavor); | ||
241 | |||
242 | /** | 246 | /** |
243 | * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors | 247 | * gss_mech_list_pseudoflavors - Discover registered GSS pseudoflavors |
244 | * @array: array to fill in | 248 | * @array: array to fill in |
@@ -268,19 +272,82 @@ int gss_mech_list_pseudoflavors(rpc_authflavor_t *array_ptr, int size) | |||
268 | return i; | 272 | return i; |
269 | } | 273 | } |
270 | 274 | ||
271 | u32 | 275 | /** |
272 | gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 service) | 276 | * gss_svc_to_pseudoflavor - map a GSS service number to a pseudoflavor |
277 | * @gm: GSS mechanism handle | ||
278 | * @qop: GSS quality-of-protection value | ||
279 | * @service: GSS service value | ||
280 | * | ||
281 | * Returns a matching security flavor, or RPC_AUTH_MAXFLAVOR if none is found. | ||
282 | */ | ||
283 | rpc_authflavor_t gss_svc_to_pseudoflavor(struct gss_api_mech *gm, u32 qop, | ||
284 | u32 service) | ||
273 | { | 285 | { |
274 | int i; | 286 | int i; |
275 | 287 | ||
276 | for (i = 0; i < gm->gm_pf_num; i++) { | 288 | for (i = 0; i < gm->gm_pf_num; i++) { |
277 | if (gm->gm_pfs[i].service == service) { | 289 | if (gm->gm_pfs[i].qop == qop && |
290 | gm->gm_pfs[i].service == service) { | ||
278 | return gm->gm_pfs[i].pseudoflavor; | 291 | return gm->gm_pfs[i].pseudoflavor; |
279 | } | 292 | } |
280 | } | 293 | } |
281 | return RPC_AUTH_MAXFLAVOR; /* illegal value */ | 294 | return RPC_AUTH_MAXFLAVOR; |
295 | } | ||
296 | |||
297 | /** | ||
298 | * gss_mech_info2flavor - look up a pseudoflavor given a GSS tuple | ||
299 | * @info: a GSS mech OID, quality of protection, and service value | ||
300 | * | ||
301 | * Returns a matching pseudoflavor, or RPC_AUTH_MAXFLAVOR if the tuple is | ||
302 | * not supported. | ||
303 | */ | ||
304 | rpc_authflavor_t gss_mech_info2flavor(struct rpcsec_gss_info *info) | ||
305 | { | ||
306 | rpc_authflavor_t pseudoflavor; | ||
307 | struct gss_api_mech *gm; | ||
308 | |||
309 | gm = gss_mech_get_by_OID(&info->oid); | ||
310 | if (gm == NULL) | ||
311 | return RPC_AUTH_MAXFLAVOR; | ||
312 | |||
313 | pseudoflavor = gss_svc_to_pseudoflavor(gm, info->qop, info->service); | ||
314 | |||
315 | gss_mech_put(gm); | ||
316 | return pseudoflavor; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * gss_mech_flavor2info - look up a GSS tuple for a given pseudoflavor | ||
321 | * @pseudoflavor: GSS pseudoflavor to match | ||
322 | * @info: rpcsec_gss_info structure to fill in | ||
323 | * | ||
324 | * Returns zero and fills in "info" if pseudoflavor matches a | ||
325 | * supported mechanism. Otherwise a negative errno is returned. | ||
326 | */ | ||
327 | int gss_mech_flavor2info(rpc_authflavor_t pseudoflavor, | ||
328 | struct rpcsec_gss_info *info) | ||
329 | { | ||
330 | struct gss_api_mech *gm; | ||
331 | int i; | ||
332 | |||
333 | gm = gss_mech_get_by_pseudoflavor(pseudoflavor); | ||
334 | if (gm == NULL) | ||
335 | return -ENOENT; | ||
336 | |||
337 | for (i = 0; i < gm->gm_pf_num; i++) { | ||
338 | if (gm->gm_pfs[i].pseudoflavor == pseudoflavor) { | ||
339 | memcpy(info->oid.data, gm->gm_oid.data, gm->gm_oid.len); | ||
340 | info->oid.len = gm->gm_oid.len; | ||
341 | info->qop = gm->gm_pfs[i].qop; | ||
342 | info->service = gm->gm_pfs[i].service; | ||
343 | gss_mech_put(gm); | ||
344 | return 0; | ||
345 | } | ||
346 | } | ||
347 | |||
348 | gss_mech_put(gm); | ||
349 | return -ENOENT; | ||
282 | } | 350 | } |
283 | EXPORT_SYMBOL_GPL(gss_svc_to_pseudoflavor); | ||
284 | 351 | ||
285 | u32 | 352 | u32 |
286 | gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) | 353 | gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) |
@@ -294,8 +361,6 @@ gss_pseudoflavor_to_service(struct gss_api_mech *gm, u32 pseudoflavor) | |||
294 | return 0; | 361 | return 0; |
295 | } | 362 | } |
296 | 363 | ||
297 | EXPORT_SYMBOL_GPL(gss_pseudoflavor_to_service); | ||
298 | |||
299 | char * | 364 | char * |
300 | gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) | 365 | gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) |
301 | { | 366 | { |
@@ -308,8 +373,6 @@ gss_service_to_auth_domain_name(struct gss_api_mech *gm, u32 service) | |||
308 | return NULL; | 373 | return NULL; |
309 | } | 374 | } |
310 | 375 | ||
311 | EXPORT_SYMBOL_GPL(gss_service_to_auth_domain_name); | ||
312 | |||
313 | void | 376 | void |
314 | gss_mech_put(struct gss_api_mech * gm) | 377 | gss_mech_put(struct gss_api_mech * gm) |
315 | { | 378 | { |
@@ -317,8 +380,6 @@ gss_mech_put(struct gss_api_mech * gm) | |||
317 | module_put(gm->gm_owner); | 380 | module_put(gm->gm_owner); |
318 | } | 381 | } |
319 | 382 | ||
320 | EXPORT_SYMBOL_GPL(gss_mech_put); | ||
321 | |||
322 | /* The mech could probably be determined from the token instead, but it's just | 383 | /* The mech could probably be determined from the token instead, but it's just |
323 | * as easy for now to pass it in. */ | 384 | * as easy for now to pass it in. */ |
324 | int | 385 | int |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 5ead60550895..c3ba570222dc 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1220,7 +1220,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1220 | svcdata->rsci = rsci; | 1220 | svcdata->rsci = rsci; |
1221 | cache_get(&rsci->h); | 1221 | cache_get(&rsci->h); |
1222 | rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor( | 1222 | rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor( |
1223 | rsci->mechctx->mech_type, gc->gc_svc); | 1223 | rsci->mechctx->mech_type, |
1224 | GSS_C_QOP_DEFAULT, | ||
1225 | gc->gc_svc); | ||
1224 | ret = SVC_OK; | 1226 | ret = SVC_OK; |
1225 | goto out; | 1227 | goto out; |
1226 | } | 1228 | } |