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.
This commit is contained in:
+1
-1
@@ -406,7 +406,7 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
|
||||
|
||||
if (cl_init->hostname == NULL) {
|
||||
WARN_ON(1);
|
||||
return NULL;
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
/* see if the client already exists */
|
||||
|
||||
@@ -205,6 +205,7 @@ struct nfs4_exception {
|
||||
struct inode *inode;
|
||||
nfs4_stateid *stateid;
|
||||
long timeout;
|
||||
unsigned char task_is_privileged : 1;
|
||||
unsigned char delay : 1,
|
||||
recovering : 1,
|
||||
retry : 1;
|
||||
|
||||
+1
-1
@@ -435,8 +435,8 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
|
||||
*/
|
||||
nfs_mark_client_ready(clp, -EPERM);
|
||||
}
|
||||
nfs_put_client(clp);
|
||||
clear_bit(NFS_CS_TSM_POSSIBLE, &clp->cl_flags);
|
||||
nfs_put_client(clp);
|
||||
return old;
|
||||
|
||||
error:
|
||||
|
||||
+30
-7
@@ -589,6 +589,8 @@ int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_
|
||||
goto out_retry;
|
||||
}
|
||||
if (exception->recovering) {
|
||||
if (exception->task_is_privileged)
|
||||
return -EDEADLOCK;
|
||||
ret = nfs4_wait_clnt_recover(clp);
|
||||
if (test_bit(NFS_MIG_FAILED, &server->mig_status))
|
||||
return -EIO;
|
||||
@@ -614,6 +616,8 @@ nfs4_async_handle_exception(struct rpc_task *task, struct nfs_server *server,
|
||||
goto out_retry;
|
||||
}
|
||||
if (exception->recovering) {
|
||||
if (exception->task_is_privileged)
|
||||
return -EDEADLOCK;
|
||||
rpc_sleep_on(&clp->cl_rpcwaitq, task, NULL);
|
||||
if (test_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) == 0)
|
||||
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
|
||||
server->caps |= NFS_CAP_HARDLINKS;
|
||||
if (res.has_symlinks != 0)
|
||||
server->caps |= NFS_CAP_SYMLINKS;
|
||||
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
|
||||
if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL)
|
||||
server->caps |= NFS_CAP_SECURITY_LABEL;
|
||||
#endif
|
||||
if (!(res.attr_bitmask[0] & FATTR4_WORD0_FILEID))
|
||||
server->fattr_valid &= ~NFS_ATTR_FATTR_FILEID;
|
||||
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
|
||||
server->fattr_valid &= ~NFS_ATTR_FATTR_CTIME;
|
||||
if (!(res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY))
|
||||
server->fattr_valid &= ~NFS_ATTR_FATTR_MTIME;
|
||||
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
|
||||
if (!(res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL))
|
||||
server->fattr_valid &= ~NFS_ATTR_FATTR_V4_SECURITY_LABEL;
|
||||
#endif
|
||||
memcpy(server->attr_bitmask_nl, res.attr_bitmask,
|
||||
sizeof(server->attr_bitmask));
|
||||
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
|
||||
do {
|
||||
err = __nfs4_proc_set_acl(inode, buf, buflen);
|
||||
trace_nfs4_set_acl(inode, err);
|
||||
if (err == -NFS4ERR_BADOWNER || err == -NFS4ERR_BADNAME) {
|
||||
/*
|
||||
* no need to retry since the kernel
|
||||
* isn't involved in encoding the ACEs.
|
||||
*/
|
||||
err = -EINVAL;
|
||||
break;
|
||||
}
|
||||
err = nfs4_handle_exception(NFS_SERVER(inode), err,
|
||||
&exception);
|
||||
} while (exception.retry);
|
||||
@@ -6409,6 +6421,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
|
||||
struct nfs4_exception exception = {
|
||||
.inode = data->inode,
|
||||
.stateid = &data->stateid,
|
||||
.task_is_privileged = data->args.seq_args.sa_privileged,
|
||||
};
|
||||
|
||||
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,
|
||||
data = kzalloc(sizeof(*data), GFP_NOFS);
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
|
||||
|
||||
nfs4_state_protect(server->nfs_client,
|
||||
NFS_SP4_MACH_CRED_CLEANUP,
|
||||
@@ -6563,6 +6575,12 @@ static int _nfs4_proc_delegreturn(struct inode *inode, const struct cred *cred,
|
||||
}
|
||||
}
|
||||
|
||||
if (!data->inode)
|
||||
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
|
||||
1);
|
||||
else
|
||||
nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1,
|
||||
0);
|
||||
task_setup_data.callback_data = data;
|
||||
msg.rpc_argp = &data->args;
|
||||
msg.rpc_resp = &data->res;
|
||||
@@ -9640,15 +9658,20 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
|
||||
&task_setup_data.rpc_client, &msg);
|
||||
|
||||
dprintk("--> %s\n", __func__);
|
||||
lrp->inode = nfs_igrab_and_active(lrp->args.inode);
|
||||
if (!sync) {
|
||||
lrp->inode = nfs_igrab_and_active(lrp->args.inode);
|
||||
if (!lrp->inode) {
|
||||
nfs4_layoutreturn_release(lrp);
|
||||
return -EAGAIN;
|
||||
}
|
||||
task_setup_data.flags |= RPC_TASK_ASYNC;
|
||||
}
|
||||
nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1, 0);
|
||||
if (!lrp->inode)
|
||||
nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1,
|
||||
1);
|
||||
else
|
||||
nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1,
|
||||
0);
|
||||
task = rpc_run_task(&task_setup_data);
|
||||
if (IS_ERR(task))
|
||||
return PTR_ERR(task);
|
||||
|
||||
@@ -430,10 +430,6 @@ TRACE_DEFINE_ENUM(O_CLOEXEC);
|
||||
{ O_NOATIME, "O_NOATIME" }, \
|
||||
{ O_CLOEXEC, "O_CLOEXEC" })
|
||||
|
||||
TRACE_DEFINE_ENUM(FMODE_READ);
|
||||
TRACE_DEFINE_ENUM(FMODE_WRITE);
|
||||
TRACE_DEFINE_ENUM(FMODE_EXEC);
|
||||
|
||||
#define show_fmode_flags(mode) \
|
||||
__print_flags(mode, "|", \
|
||||
{ ((__force unsigned long)FMODE_READ), "READ" }, \
|
||||
|
||||
Reference in New Issue
Block a user