diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 56 | 
1 files changed, 29 insertions, 27 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 442811809f3d..533d0fc3c96b 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -49,6 +49,7 @@  #include "cache.h"  #include "netns.h"  #include "pnfs.h" +#include "filecache.h"  #ifdef CONFIG_NFSD_V4_SECURITY_LABEL  #include <linux/security.h> @@ -203,6 +204,13 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)  	return p;  } +static unsigned int compoundargs_bytes_left(struct nfsd4_compoundargs *argp) +{ +	unsigned int this = (char *)argp->end - (char *)argp->p; + +	return this + argp->pagelen; +} +  static int zero_clientid(clientid_t *clid)  {  	return (clid->cl_boot == 0) && (clid->cl_id == 0); @@ -211,10 +219,10 @@ static int zero_clientid(clientid_t *clid)  /**   * svcxdr_tmpalloc - allocate memory to be freed after compound processing   * @argp: NFSv4 compound argument structure - * @p: pointer to be freed (with kfree()) + * @len: length of buffer to allocate   * - * Marks @p to be freed when processing the compound operation - * described in @argp finishes. + * Allocates a buffer of size @len to be freed when processing the compound + * operation described in @argp finishes.   */  static void *  svcxdr_tmpalloc(struct nfsd4_compoundargs *argp, u32 len) @@ -347,7 +355,12 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,  		READ_BUF(4); len += 4;  		nace = be32_to_cpup(p++); -		if (nace > NFS4_ACL_MAX) +		if (nace > compoundargs_bytes_left(argp)/20) +			/* +			 * Even with 4-byte names there wouldn't be +			 * space for that many aces; something fishy is +			 * going on: +			 */  			return nfserr_fbig;  		*acl = svcxdr_tmpalloc(argp, nfs4_acl_bytes(nace)); @@ -1418,7 +1431,6 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,  			    struct nfsd4_create_session *sess)  {  	DECODE_HEAD; -	u32 dummy;  	READ_BUF(16);  	COPYMEM(&sess->clientid, 8); @@ -1427,7 +1439,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,  	/* Fore channel attrs */  	READ_BUF(28); -	dummy = be32_to_cpup(p++); /* headerpadsz is always 0 */ +	p++; /* headerpadsz is always 0 */  	sess->fore_channel.maxreq_sz = be32_to_cpup(p++);  	sess->fore_channel.maxresp_sz = be32_to_cpup(p++);  	sess->fore_channel.maxresp_cached = be32_to_cpup(p++); @@ -1444,7 +1456,7 @@ nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,  	/* Back channel attrs */  	READ_BUF(28); -	dummy = be32_to_cpup(p++); /* headerpadsz is always 0 */ +	p++; /* headerpadsz is always 0 */  	sess->back_channel.maxreq_sz = be32_to_cpup(p++);  	sess->back_channel.maxresp_sz = be32_to_cpup(p++);  	sess->back_channel.maxresp_cached = be32_to_cpup(p++); @@ -1736,7 +1748,6 @@ static __be32  nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)  {  	DECODE_HEAD; -	unsigned int tmp;  	status = nfsd4_decode_stateid(argp, ©->cp_src_stateid);  	if (status) @@ -1751,7 +1762,7 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)  	p = xdr_decode_hyper(p, ©->cp_count);  	p++; /* ca_consecutive: we always do consecutive copies */  	copy->cp_synchronous = be32_to_cpup(p++); -	tmp = be32_to_cpup(p); /* Source server list not supported */ +	/* tmp = be32_to_cpup(p); Source server list not supported */  	DECODE_TAIL;  } @@ -3217,9 +3228,8 @@ nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_  	if (!p)  		return nfserr_resource;  	encode_cinfo(p, &create->cr_cinfo); -	nfserr = nfsd4_encode_bitmap(xdr, create->cr_bmval[0], +	return nfsd4_encode_bitmap(xdr, create->cr_bmval[0],  			create->cr_bmval[1], create->cr_bmval[2]); -	return 0;  }  static __be32 @@ -3462,7 +3472,7 @@ static __be32 nfsd4_encode_splice_read(  	len = maxcount;  	nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp, -				  file, read->rd_offset, &maxcount); +				  file, read->rd_offset, &maxcount, &eof);  	read->rd_length = maxcount;  	if (nfserr) {  		/* @@ -3474,9 +3484,6 @@ static __be32 nfsd4_encode_splice_read(  		return nfserr;  	} -	eof = nfsd_eof_on_read(len, maxcount, read->rd_offset, -				d_inode(read->rd_fhp->fh_dentry)->i_size); -  	*(p++) = htonl(eof);  	*(p++) = htonl(maxcount); @@ -3547,15 +3554,13 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,  	len = maxcount;  	nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset, -			    resp->rqstp->rq_vec, read->rd_vlen, &maxcount); +			    resp->rqstp->rq_vec, read->rd_vlen, &maxcount, +			    &eof);  	read->rd_length = maxcount;  	if (nfserr)  		return nfserr;  	xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3)); -	eof = nfsd_eof_on_read(len, maxcount, read->rd_offset, -				d_inode(read->rd_fhp->fh_dentry)->i_size); -  	tmp = htonl(eof);  	write_bytes_to_xdr_buf(xdr->buf, starting_len    , &tmp, 4);  	tmp = htonl(maxcount); @@ -3574,11 +3579,14 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,  {  	unsigned long maxcount;  	struct xdr_stream *xdr = &resp->xdr; -	struct file *file = read->rd_filp; +	struct file *file;  	int starting_len = xdr->buf->len; -	struct raparms *ra = NULL;  	__be32 *p; +	if (nfserr) +		return nfserr; +	file = read->rd_nf->nf_file; +  	p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */  	if (!p) {  		WARN_ON_ONCE(test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)); @@ -3596,18 +3604,12 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,  			 (xdr->buf->buflen - xdr->buf->len));  	maxcount = min_t(unsigned long, maxcount, read->rd_length); -	if (read->rd_tmp_file) -		ra = nfsd_init_raparms(file); -  	if (file->f_op->splice_read &&  	    test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))  		nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);  	else  		nfserr = nfsd4_encode_readv(resp, read, file, maxcount); -	if (ra) -		nfsd_put_raparams(file, ra); -  	if (nfserr)  		xdr_truncate_encode(xdr, starting_len);  |