Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

NFSD: Insulate nfsd4_encode_readlink() from page boundaries in the encode buffer

There's no guarantee that the pointer returned from
xdr_reserve_space() will still point to the correct reserved space
in the encode buffer after one or more intervening calls to
xdr_reserve_space(). It just happens to work with the current
implementation of xdr_reserve_space().

Reviewed-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

+10 -12
+10 -12
fs/nfsd/nfs4xdr.c
··· 4450 4450 union nfsd4_op_u *u) 4451 4451 { 4452 4452 struct nfsd4_readlink *readlink = &u->readlink; 4453 - __be32 *p, *maxcount_p, zero = xdr_zero; 4453 + __be32 *p, wire_count, zero = xdr_zero; 4454 4454 struct xdr_stream *xdr = resp->xdr; 4455 - int length_offset = xdr->buf->len; 4455 + unsigned int length_offset; 4456 4456 int maxcount, status; 4457 4457 4458 - maxcount_p = xdr_reserve_space(xdr, XDR_UNIT); 4459 - if (!maxcount_p) 4458 + /* linktext4.count */ 4459 + length_offset = xdr->buf->len; 4460 + if (unlikely(!xdr_reserve_space(xdr, XDR_UNIT))) 4460 4461 return nfserr_resource; 4461 - maxcount = PAGE_SIZE; 4462 4462 4463 + /* linktext4.data */ 4464 + maxcount = PAGE_SIZE; 4463 4465 p = xdr_reserve_space(xdr, maxcount); 4464 4466 if (!p) 4465 4467 return nfserr_resource; 4466 - /* 4467 - * XXX: By default, vfs_readlink() will truncate symlinks if they 4468 - * would overflow the buffer. Is this kosher in NFSv4? If not, one 4469 - * easy fix is: if vfs_readlink() precisely fills the buffer, assume 4470 - * that truncation occurred, and return NFS4ERR_RESOURCE. 4471 - */ 4472 4468 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, 4473 4469 (char *)p, &maxcount); 4474 4470 if (nfserr == nfserr_isdir) ··· 4477 4481 nfserr = nfserrno(status); 4478 4482 goto out_err; 4479 4483 } 4480 - *maxcount_p = cpu_to_be32(maxcount); 4484 + 4485 + wire_count = cpu_to_be32(maxcount); 4486 + write_bytes_to_xdr_buf(xdr->buf, length_offset, &wire_count, XDR_UNIT); 4481 4487 xdr_truncate_encode(xdr, length_offset + 4 + xdr_align_size(maxcount)); 4482 4488 write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount, &zero, 4483 4489 xdr_pad_size(maxcount));