diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 92 |
1 files changed, 56 insertions, 36 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e18b3b46c001..e13b7ccee98d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2547,7 +2547,7 @@ static int nfs4_lookup_root_sec(struct nfs_server *server, struct nfs_fh *fhandl | |||
2547 | 2547 | ||
2548 | auth = rpcauth_create(flavor, server->client); | 2548 | auth = rpcauth_create(flavor, server->client); |
2549 | if (IS_ERR(auth)) { | 2549 | if (IS_ERR(auth)) { |
2550 | ret = -EIO; | 2550 | ret = -EACCES; |
2551 | goto out; | 2551 | goto out; |
2552 | } | 2552 | } |
2553 | ret = nfs4_lookup_root(server, fhandle, info); | 2553 | ret = nfs4_lookup_root(server, fhandle, info); |
@@ -2555,27 +2555,36 @@ out: | |||
2555 | return ret; | 2555 | return ret; |
2556 | } | 2556 | } |
2557 | 2557 | ||
2558 | /* | ||
2559 | * Retry pseudoroot lookup with various security flavors. We do this when: | ||
2560 | * | ||
2561 | * NFSv4.0: the PUTROOTFH operation returns NFS4ERR_WRONGSEC | ||
2562 | * NFSv4.1: the server does not support the SECINFO_NO_NAME operation | ||
2563 | * | ||
2564 | * Returns zero on success, or a negative NFS4ERR value, or a | ||
2565 | * negative errno value. | ||
2566 | */ | ||
2558 | static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | 2567 | static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, |
2559 | struct nfs_fsinfo *info) | 2568 | struct nfs_fsinfo *info) |
2560 | { | 2569 | { |
2561 | int i, len, status = 0; | 2570 | /* Per 3530bis 15.33.5 */ |
2562 | rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS]; | 2571 | static const rpc_authflavor_t flav_array[] = { |
2563 | 2572 | RPC_AUTH_GSS_KRB5P, | |
2564 | len = rpcauth_list_flavors(flav_array, ARRAY_SIZE(flav_array)); | 2573 | RPC_AUTH_GSS_KRB5I, |
2565 | if (len < 0) | 2574 | RPC_AUTH_GSS_KRB5, |
2566 | return len; | 2575 | RPC_AUTH_UNIX, /* courtesy */ |
2567 | 2576 | RPC_AUTH_NULL, | |
2568 | for (i = 0; i < len; i++) { | 2577 | }; |
2569 | /* AUTH_UNIX is the default flavor if none was specified, | 2578 | int status = -EPERM; |
2570 | * thus has already been tried. */ | 2579 | size_t i; |
2571 | if (flav_array[i] == RPC_AUTH_UNIX) | ||
2572 | continue; | ||
2573 | 2580 | ||
2581 | for (i = 0; i < ARRAY_SIZE(flav_array); i++) { | ||
2574 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); | 2582 | status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]); |
2575 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) | 2583 | if (status == -NFS4ERR_WRONGSEC || status == -EACCES) |
2576 | continue; | 2584 | continue; |
2577 | break; | 2585 | break; |
2578 | } | 2586 | } |
2587 | |||
2579 | /* | 2588 | /* |
2580 | * -EACCESS could mean that the user doesn't have correct permissions | 2589 | * -EACCESS could mean that the user doesn't have correct permissions |
2581 | * to access the mount. It could also mean that we tried to mount | 2590 | * to access the mount. It could also mean that we tried to mount |
@@ -2588,24 +2597,36 @@ static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2588 | return status; | 2597 | return status; |
2589 | } | 2598 | } |
2590 | 2599 | ||
2591 | /* | 2600 | static int nfs4_do_find_root_sec(struct nfs_server *server, |
2592 | * get the file handle for the "/" directory on the server | 2601 | struct nfs_fh *fhandle, struct nfs_fsinfo *info) |
2602 | { | ||
2603 | int mv = server->nfs_client->cl_minorversion; | ||
2604 | return nfs_v4_minor_ops[mv]->find_root_sec(server, fhandle, info); | ||
2605 | } | ||
2606 | |||
2607 | /** | ||
2608 | * nfs4_proc_get_rootfh - get file handle for server's pseudoroot | ||
2609 | * @server: initialized nfs_server handle | ||
2610 | * @fhandle: we fill in the pseudo-fs root file handle | ||
2611 | * @info: we fill in an FSINFO struct | ||
2612 | * | ||
2613 | * Returns zero on success, or a negative errno. | ||
2593 | */ | 2614 | */ |
2594 | int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, | 2615 | int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, |
2595 | struct nfs_fsinfo *info) | 2616 | struct nfs_fsinfo *info) |
2596 | { | 2617 | { |
2597 | int minor_version = server->nfs_client->cl_minorversion; | 2618 | int status; |
2598 | int status = nfs4_lookup_root(server, fhandle, info); | 2619 | |
2599 | if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR)) | 2620 | status = nfs4_lookup_root(server, fhandle, info); |
2600 | /* | 2621 | if ((status == -NFS4ERR_WRONGSEC) && |
2601 | * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM | 2622 | !(server->flags & NFS_MOUNT_SECFLAVOUR)) |
2602 | * by nfs4_map_errors() as this function exits. | 2623 | status = nfs4_do_find_root_sec(server, fhandle, info); |
2603 | */ | 2624 | |
2604 | status = nfs_v4_minor_ops[minor_version]->find_root_sec(server, fhandle, info); | ||
2605 | if (status == 0) | 2625 | if (status == 0) |
2606 | status = nfs4_server_capabilities(server, fhandle); | 2626 | status = nfs4_server_capabilities(server, fhandle); |
2607 | if (status == 0) | 2627 | if (status == 0) |
2608 | status = nfs4_do_fsinfo(server, fhandle, info); | 2628 | status = nfs4_do_fsinfo(server, fhandle, info); |
2629 | |||
2609 | return nfs4_map_errors(status); | 2630 | return nfs4_map_errors(status); |
2610 | } | 2631 | } |
2611 | 2632 | ||
@@ -3484,12 +3505,21 @@ static int _nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, | |||
3484 | static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) | 3505 | static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
3485 | { | 3506 | { |
3486 | struct nfs4_exception exception = { }; | 3507 | struct nfs4_exception exception = { }; |
3508 | unsigned long now = jiffies; | ||
3487 | int err; | 3509 | int err; |
3488 | 3510 | ||
3489 | do { | 3511 | do { |
3490 | err = nfs4_handle_exception(server, | 3512 | err = _nfs4_do_fsinfo(server, fhandle, fsinfo); |
3491 | _nfs4_do_fsinfo(server, fhandle, fsinfo), | 3513 | if (err == 0) { |
3492 | &exception); | 3514 | struct nfs_client *clp = server->nfs_client; |
3515 | |||
3516 | spin_lock(&clp->cl_lock); | ||
3517 | clp->cl_lease_time = fsinfo->lease_time * HZ; | ||
3518 | clp->cl_last_renewal = now; | ||
3519 | spin_unlock(&clp->cl_lock); | ||
3520 | break; | ||
3521 | } | ||
3522 | err = nfs4_handle_exception(server, err, &exception); | ||
3493 | } while (exception.retry); | 3523 | } while (exception.retry); |
3494 | return err; | 3524 | return err; |
3495 | } | 3525 | } |
@@ -4330,27 +4360,17 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp, | |||
4330 | struct nfs4_setclientid_res *arg, | 4360 | struct nfs4_setclientid_res *arg, |
4331 | struct rpc_cred *cred) | 4361 | struct rpc_cred *cred) |
4332 | { | 4362 | { |
4333 | struct nfs_fsinfo fsinfo; | ||
4334 | struct rpc_message msg = { | 4363 | struct rpc_message msg = { |
4335 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM], | 4364 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETCLIENTID_CONFIRM], |
4336 | .rpc_argp = arg, | 4365 | .rpc_argp = arg, |
4337 | .rpc_resp = &fsinfo, | ||
4338 | .rpc_cred = cred, | 4366 | .rpc_cred = cred, |
4339 | }; | 4367 | }; |
4340 | unsigned long now; | ||
4341 | int status; | 4368 | int status; |
4342 | 4369 | ||
4343 | dprintk("NFS call setclientid_confirm auth=%s, (client ID %llx)\n", | 4370 | dprintk("NFS call setclientid_confirm auth=%s, (client ID %llx)\n", |
4344 | clp->cl_rpcclient->cl_auth->au_ops->au_name, | 4371 | clp->cl_rpcclient->cl_auth->au_ops->au_name, |
4345 | clp->cl_clientid); | 4372 | clp->cl_clientid); |
4346 | now = jiffies; | ||
4347 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); | 4373 | status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT); |
4348 | if (status == 0) { | ||
4349 | spin_lock(&clp->cl_lock); | ||
4350 | clp->cl_lease_time = fsinfo.lease_time * HZ; | ||
4351 | clp->cl_last_renewal = now; | ||
4352 | spin_unlock(&clp->cl_lock); | ||
4353 | } | ||
4354 | dprintk("NFS reply setclientid_confirm: %d\n", status); | 4374 | dprintk("NFS reply setclientid_confirm: %d\n", status); |
4355 | return status; | 4375 | return status; |
4356 | } | 4376 | } |