diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2020-10-20 16:01:16 -0400 |
---|---|---|
committer | Chuck Lever <chuck.lever@oracle.com> | 2021-01-25 09:36:25 -0500 |
commit | da39201637297460c13134c29286a00f3a1c92fe (patch) | |
tree | 7e6c2a063fa081e5803198708b45af6c2e969abb /fs/nfsd/nfs3xdr.c | |
parent | 83374c278db193f3e8b2608b45da1132b867a760 (diff) | |
download | lwn-da39201637297460c13134c29286a00f3a1c92fe.tar.gz lwn-da39201637297460c13134c29286a00f3a1c92fe.zip |
NFSD: Update the SYMLINK3args decoder to use struct xdr_stream
Similar to the WRITE decoder, code that checks the sanity of the
payload size is re-wired to work with xdr_stream infrastructure.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Diffstat (limited to 'fs/nfsd/nfs3xdr.c')
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index b4071cda1d65..eb17231ab166 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -616,25 +616,28 @@ nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p) int nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p) { + struct xdr_stream *xdr = &rqstp->rq_arg_stream; struct nfsd3_symlinkargs *args = rqstp->rq_argp; - char *base = (char *)p; - size_t dlen; + struct kvec *head = rqstp->rq_arg.head; + struct kvec *tail = rqstp->rq_arg.tail; + size_t remaining; - if (!(p = decode_fh(p, &args->ffh)) || - !(p = decode_filename(p, &args->fname, &args->flen))) + if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen)) + return 0; + if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs)) + return 0; + if (xdr_stream_decode_u32(xdr, &args->tlen) < 0) return 0; - p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp)); - args->tlen = ntohl(*p++); + /* request sanity */ + remaining = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len; + remaining -= xdr_stream_pos(xdr); + if (remaining < xdr_align_size(args->tlen)) + return 0; - args->first.iov_base = p; - args->first.iov_len = rqstp->rq_arg.head[0].iov_len; - args->first.iov_len -= (char *)p - base; + args->first.iov_base = xdr->p; + args->first.iov_len = head->iov_len - xdr_stream_pos(xdr); - dlen = args->first.iov_len + rqstp->rq_arg.page_len + - rqstp->rq_arg.tail[0].iov_len; - if (dlen < XDR_QUADLEN(args->tlen) << 2) - return 0; return 1; } |