Skip to content

Commit 960f071

Browse files
committed
Merge tag 'nfs-for-5.13-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
Pull NFS client bugfixes from Trond Myklebust: "Highlights include: Stable fixes: - Fix use-after-free in nfs4_init_client() Bugfixes: - Fix deadlock between nfs4_evict_inode() and nfs4_opendata_get_inode() - Fix second deadlock in nfs4_evict_inode() - nfs4_proc_set_acl should not change the value of NFS_CAP_UIDGID_NOMAP - Fix setting of the NFS_CAP_SECURITY_LABEL capability" * tag 'nfs-for-5.13-3' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: NFSv4: Fix second deadlock in nfs4_evict_inode() NFSv4: Fix deadlock between nfs4_evict_inode() and nfs4_opendata_get_inode() NFS: FMODE_READ and friends are C macros, not enum types NFS: Fix a potential NULL dereference in nfs_get_client() NFS: Fix use-after-free in nfs4_init_client() NFS: Ensure the NFS_CAP_SECURITY_LABEL capability is set when appropriate NFSv4: nfs4_proc_set_acl needs to restore NFS_CAP_UIDGID_NOMAP on error.
2 parents 331a6ed + c3aba89 commit 960f071

File tree

5 files changed

+33
-13
lines changed

5 files changed

+33
-13
lines changed

fs/nfs/client.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
406406

407407
if (cl_init->hostname == NULL) {
408408
WARN_ON(1);
409-
return NULL;
409+
return ERR_PTR(-EINVAL);
410410
}
411411

412412
/* see if the client already exists */

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ struct nfs4_exception {
205205
struct inode *inode;
206206
nfs4_stateid *stateid;
207207
long timeout;
208+
unsigned char task_is_privileged : 1;
208209
unsigned char delay : 1,
209210
recovering : 1,
210211
retry : 1;

fs/nfs/nfs4client.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,8 +435,8 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
435435
*/
436436
nfs_mark_client_ready(clp, -EPERM);
437437
}
438-
nfs_put_client(clp);
439438
clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
439+
nfs_put_client(clp);
440440
return old;
441441

442442
error:

fs/nfs/nfs4proc.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,8 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
589589
goto out_retry;
590590
}
591591
if (exception->recovering) {
592+
if (exception->task_is_privileged)
593+
return -EDEADLOCK;
592594
ret = nfs4_wait_clnt_recover(clp);
593595
if (test_bit(NFS_MIG_FAILED, &server->mig_status))
594596
return -EIO;
@@ -614,6 +616,8 @@ nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server,
614616
goto out_retry;
615617
}
616618
if (exception->recovering) {
619+
if (exception->task_is_privileged)
620+
return -EDEADLOCK;
617621
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
618622
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
619623
rpc_wake_up_queued_task(&clp->cl_rpcwaitq, task);
@@ -3878,6 +3882,10 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
38783882
server->caps |= NFS_CAP_HARDLINKS;
38793883
if (res.has_symlinks != 0)
38803884
server->caps |= NFS_CAP_SYMLINKS;
3885+
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
3886+
if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
3887+
server->caps |= NFS_CAP_SECURITY_LABEL;
3888+
#endif
38813889
if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID))
38823890
server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID;
38833891
if (!(res.attr_bitmask[1] & FATTR4_WORD1_MODE))
@@ -3898,10 +3906,6 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
38983906
server->fattr_valid &= ~NFS_ATTR_FATTR_CTIME;
38993907
if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY))
39003908
server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME;
3901-
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
3902-
if (!(res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL))
3903-
server->fattr_valid &= ~NFS_ATTR_FATTR_V4_SECURITY_LABEL;
3904-
#endif
39053909
memcpy(server->attr_bitmask_nl, res.attr_bitmask,
39063910
sizeof(server->attr_bitmask));
39073911
server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
@@ -5968,6 +5972,14 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
59685972
do {
59695973
err = __nfs4_proc_set_acl(inode, buf, buflen);
59705974
trace_nfs4_set_acl(inode, err);
5975+
if (err == -NFS4ERR_BADOWNER || err == -NFS4ERR_BADNAME) {
5976+
/*
5977+
* no need to retry since the kernel
5978+
* isn't involved in encoding the ACEs.
5979+
*/
5980+
err = -EINVAL;
5981+
break;
5982+
}
59715983
err = nfs4_handle_exception(NFS_SERVER(inode), err,
59725984
&exception);
59735985
} while (exception.retry);
@@ -6409,6 +6421,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
64096421
struct nfs4_exception exception = {
64106422
.inode = data->inode,
64116423
.stateid = &data->stateid,
6424+
.task_is_privileged = data->args.seq_args.sa_privileged,
64126425
};
64136426

64146427
if (!nfs4_sequence_done(task, &data->res.seq_res))
@@ -6532,7 +6545,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
65326545
data = kzalloc(sizeof(*data), GFP_NOFS);
65336546
if (data == NULL)
65346547
return -ENOMEM;
6535-
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
65366548

65376549
nfs4_state_protect(server->nfs_client,
65386550
NFS_SP4_MACH_CRED_CLEANUP,
@@ -6563,6 +6575,12 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
65636575
}
65646576
}
65656577

6578+
if (!data->inode)
6579+
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
6580+
1);
6581+
else
6582+
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
6583+
0);
65666584
task_setup_data.callback_data = data;
65676585
msg.rpc_argp = &data->args;
65686586
msg.rpc_resp = &data->res;
@@ -9640,15 +9658,20 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
96409658
&task_setup_data.rpc_client, &msg);
96419659

96429660
dprintk("--> %s\n", __func__);
9661+
lrp->inode = nfs_igrab_and_active(lrp->args.inode);
96439662
if (!sync) {
9644-
lrp->inode = nfs_igrab_and_active(lrp->args.inode);
96459663
if (!lrp->inode) {
96469664
nfs4_layoutreturn_release(lrp);
96479665
return -EAGAIN;
96489666
}
96499667
task_setup_data.flags |= RPC_TASK_ASYNC;
96509668
}
9651-
nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1, 0);
9669+
if (!lrp->inode)
9670+
nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1,
9671+
1);
9672+
else
9673+
nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1,
9674+
0);
96529675
task = rpc_run_task(&task_setup_data);
96539676
if (IS_ERR(task))
96549677
return PTR_ERR(task);

fs/nfs/nfstrace.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,6 @@ TRACE_DEFINE_ENUM(O_CLOEXEC);
430430
{ O_NOATIME, "O_NOATIME" }, \
431431
{ O_CLOEXEC, "O_CLOEXEC" })
432432

433-
TRACE_DEFINE_ENUM(FMODE_READ);
434-
TRACE_DEFINE_ENUM(FMODE_WRITE);
435-
TRACE_DEFINE_ENUM(FMODE_EXEC);
436-
437433
#define show_fmode_flags(mode) \
438434
__print_flags(mode, "|", \
439435
{ ((__force unsigned long)FMODE_READ), "READ" }, \

0 commit comments

Comments
 (0)