NFS client bugfixes for Linux 5.13
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEESQctxSBg8JpV8KqEZwvnipYKAPIFAmDGJPEACgkQZwvnipYK APLH8xAAsdoKVCW35P+FtlzQvq0iWoTvk15i4Jv8+SyFtqAZe6y6pEj9+RT47CAV kt/uNa6CQ9KjxxgwBf2XoGTuf4MrOUU34kQBF/tRLy9zDdXUsZH263vapopmel6L BVHEEsID6hz8+BUt1LFsr+8sWxG+12UiimEu0CVo4BE8SgYushWpJOQ9iL/zxi1O gXmlAfA9g38I9aUApke4hOPSHVTGaQaAKl5LbSoycQlJblzgA1yIXdU9sVTHDJY6 sco9O9M+NPY8gefS4d7iXSihZin5V9rNuSJ9SKiCPikTEjZYgZbw1umGj6VnF/5e QD47QGgOwXKeCOBv6Oe4VYxE2JISoUFZw8+pxjy4eDO+EcJv3IrHOM8UrsiddGAA DLHzbbrMUx6mGdgibw/ktkwx0Q/DvGrfrvKidk33cs16DPWgTZAG//n7spuqYTmT 8fQbJF6DDjsYM7v+WdImf7VBA8dreXb/QcHwxCtH7uG+hGyRiYoDSOmH3mGBKpLX idkjz6Hvj7V7Y1z4qd+nvh4Ch1V0b9BX+J/+6dKHRykpmSJTIMIlQw7/wA6a8Lp6 WJX4KbUzZHojvqM1BMzRL34+qidihUso0RIj0VjCB1JQyosRnIeTPorfHLQZTOM0 IjP8h48BB7E7cJeJP1dmhvm7Hb8SpFVDxDHoWRtscbQflO3Wdkw= =PABi -----END PGP SIGNATURE----- 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:
commit
960f0716d8
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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" }, \
|
||||
|
Loading…
Reference in New Issue
Block a user