summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-11-09 12:43:12 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2020-11-09 12:43:12 -0800
commit3552c3709c0e78144c11748718180441ac647ece (patch)
treee965be9f04f6c0a28706784fb5cac3bb5667beb4
parent91808cd6c24359eee0c1eb7a06ea02dac358cbb5 (diff)
parentae2975046dbc65855c217fe6fbd5b33140c5ff18 (diff)
downloadlinux-3552c3709c0e78144c11748718180441ac647ece.tar.bz2
Merge tag 'nfsd-5.10-1' of git://linux-nfs.org/~bfields/linux
Pull nfsd fixes from Bruce Fields: "This is mainly server-to-server copy and fallout from Chuck's 5.10 rpc refactoring" * tag 'nfsd-5.10-1' of git://linux-nfs.org/~bfields/linux: net/sunrpc: fix useless comparison in proc_do_xprt() net/sunrpc: return 0 on attempt to write to "transports" NFSD: fix missing refcount in nfsd4_copy by nfsd4_do_async_copy NFSD: Fix use-after-free warning when doing inter-server copy NFSD: MKNOD should return NFSERR_BADTYPE instead of NFSERR_INVAL SUNRPC: Fix general protection fault in trace_rpc_xdr_overflow() NFSD: NFSv3 PATHCONF Reply is improperly formed
-rw-r--r--fs/nfsd/nfs3proc.c6
-rw-r--r--fs/nfsd/nfs3xdr.c1
-rw-r--r--fs/nfsd/nfs4proc.c3
-rw-r--r--include/trace/events/sunrpc.h8
-rw-r--r--net/sunrpc/sysctl.c9
5 files changed, 13 insertions, 14 deletions
diff --git a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
index 14468613d150..a633044b0dc1 100644
--- a/fs/nfsd/nfs3proc.c
+++ b/fs/nfsd/nfs3proc.c
@@ -316,10 +316,6 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
fh_copy(&resp->dirfh, &argp->fh);
fh_init(&resp->fh, NFS3_FHSIZE);
- if (argp->ftype == 0 || argp->ftype >= NF3BAD) {
- resp->status = nfserr_inval;
- goto out;
- }
if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) {
rdev = MKDEV(argp->major, argp->minor);
if (MAJOR(rdev) != argp->major ||
@@ -328,7 +324,7 @@ nfsd3_proc_mknod(struct svc_rqst *rqstp)
goto out;
}
} else if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) {
- resp->status = nfserr_inval;
+ resp->status = nfserr_badtype;
goto out;
}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 9c23b6acf234..2277f83da250 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -1114,6 +1114,7 @@ nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p)
{
struct nfsd3_pathconfres *resp = rqstp->rq_resp;
+ *p++ = resp->status;
*p++ = xdr_zero; /* no post_op_attr */
if (resp->status == 0) {
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index ad2fa1a8e7ad..e83b21778816 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1299,7 +1299,7 @@ nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
struct nfsd_file *dst)
{
nfs42_ssc_close(src->nf_file);
- nfsd_file_put(src);
+ /* 'src' is freed by nfsd4_do_async_copy */
nfsd_file_put(dst);
mntput(ss_mnt);
}
@@ -1486,6 +1486,7 @@ do_callback:
cb_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
if (!cb_copy)
goto out;
+ refcount_set(&cb_copy->refcount, 1);
memcpy(&cb_copy->cp_res, &copy->cp_res, sizeof(copy->cp_res));
cb_copy->cp_clp = copy->cp_clp;
cb_copy->nfserr = copy->nfserr;
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index f45b3c01370c..2477014e3fa6 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -655,10 +655,10 @@ TRACE_EVENT(rpc_xdr_overflow,
__field(size_t, tail_len)
__field(unsigned int, page_len)
__field(unsigned int, len)
- __string(progname,
- xdr->rqst->rq_task->tk_client->cl_program->name)
- __string(procedure,
- xdr->rqst->rq_task->tk_msg.rpc_proc->p_name)
+ __string(progname, xdr->rqst ?
+ xdr->rqst->rq_task->tk_client->cl_program->name : "unknown")
+ __string(procedure, xdr->rqst ?
+ xdr->rqst->rq_task->tk_msg.rpc_proc->p_name : "unknown")
),
TP_fast_assign(
diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c
index a18b36b5422d..3aad6ef18504 100644
--- a/net/sunrpc/sysctl.c
+++ b/net/sunrpc/sysctl.c
@@ -63,19 +63,20 @@ static int proc_do_xprt(struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
char tmpbuf[256];
- size_t len;
+ ssize_t len;
- if ((*ppos && !write) || !*lenp) {
+ if (write || *ppos) {
*lenp = 0;
return 0;
}
len = svc_print_xprts(tmpbuf, sizeof(tmpbuf));
- *lenp = memory_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
+ len = memory_read_from_buffer(buffer, *lenp, ppos, tmpbuf, len);
- if (*lenp < 0) {
+ if (len < 0) {
*lenp = 0;
return -EINVAL;
}
+ *lenp = len;
return 0;
}