static int decode_nfspath3(struct xdr_stream *xdr) { u32 recvd, count; size_t hdrlen; __be32 *p; p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) goto out_overflow; count = be32_to_cpup(p); if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN)) goto out_nametoolong; hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base; recvd = xdr->buf->len - hdrlen; if (unlikely(count > recvd)) goto out_cheating; xdr_read_pages(xdr, count); xdr_terminate_string(xdr->buf, count); return 0; out_nametoolong: dprintk("NFS: returned pathname too long: %u\n", count); return -ENAMETOOLONG; out_cheating: dprintk("NFS: server cheating in pathname result: " "count %u > recvd %u\n", count, recvd); return -EIO; out_overflow: print_overflow_msg(__func__, xdr); return -EIO; }
static int decode_path(struct xdr_stream *xdr) { u32 length, recvd; __be32 *p; p = xdr_inline_decode(xdr, 4); if (unlikely(p == NULL)) goto out_overflow; length = be32_to_cpup(p); if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN)) goto out_size; recvd = xdr_read_pages(xdr, length); if (unlikely(length > recvd)) goto out_cheating; xdr_terminate_string(xdr->buf, length); return 0; out_size: dprintk("NFS: returned pathname too long: %u\n", length); return -ENAMETOOLONG; out_cheating: dprintk("NFS: server cheating in pathname result: " "length %u > received %u\n", length, recvd); return -EIO; out_overflow: print_overflow_msg(__func__, xdr); return -EIO; }
/* * Decode READLINK reply */ static int nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy) { struct xdr_buf *rcvbuf = &req->rq_rcv_buf; struct kvec *iov = rcvbuf->head; size_t hdrlen; u32 len, recvd; int status; if ((status = ntohl(*p++))) return nfs_stat_to_errno(status); /* Convert length of symlink */ len = ntohl(*p++); if (len >= rcvbuf->page_len) { dprintk("nfs: server returned giant symlink!\n"); return -ENAMETOOLONG; } hdrlen = (u8 *) p - (u8 *) iov->iov_base; if (iov->iov_len < hdrlen) { dprintk("NFS: READLINK reply header overflowed:" "length %Zu > %Zu\n", hdrlen, iov->iov_len); return -errno_NFSERR_IO; } else if (iov->iov_len != hdrlen) { dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); } recvd = req->rq_rcv_buf.len - hdrlen; if (recvd < len) { dprintk("NFS: server cheating in readlink reply: " "count %u > recvd %u\n", len, recvd); return -EIO; } xdr_terminate_string(rcvbuf, len); return 0; }