aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c92
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 */
2558static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle, 2567static 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/* 2600static 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 */
2594int nfs4_proc_get_rootfh(struct nfs_server *server, struct nfs_fh *fhandle, 2615int 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,
3484static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) 3505static 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}