NFSv4: Ensure decode_compound_hdr() sanity checks the tag
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 4 Nov 2021 21:18:01 +0000 (17:18 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 5 Nov 2021 18:54:30 +0000 (14:54 -0400)
The server is supposed to return the same tag that the client sends in
the outgoing RPC call, but we should still sanity check the length just
in case.

Reported-by: <rtm@csail.mit.edu>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/nfs4xdr.c

index a8cff19c6f00cc16bcb22e47c8ade46d16caa8de..f206d41d6bee11a9c651d7a6b88f11ef673cd715 100644 (file)
@@ -3168,20 +3168,23 @@ static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char
 
 static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
 {
-       __be32 *p;
+       ssize_t ret;
+       void *ptr;
+       u32 tmp;
 
-       p = xdr_inline_decode(xdr, 8);
-       if (unlikely(!p))
+       if (xdr_stream_decode_u32(xdr, &tmp) < 0)
                return -EIO;
-       hdr->status = be32_to_cpup(p++);
-       hdr->taglen = be32_to_cpup(p);
+       hdr->status = tmp;
 
-       p = xdr_inline_decode(xdr, hdr->taglen + 4);
-       if (unlikely(!p))
+       ret = xdr_stream_decode_opaque_inline(xdr, &ptr, NFS4_OPAQUE_LIMIT);
+       if (ret < 0)
+               return -EIO;
+       hdr->taglen = ret;
+       hdr->tag = ptr;
+
+       if (xdr_stream_decode_u32(xdr, &tmp) < 0)
                return -EIO;
-       hdr->tag = (char *)p;
-       p += XDR_QUADLEN(hdr->taglen);
-       hdr->nops = be32_to_cpup(p);
+       hdr->nops = tmp;
        if (unlikely(hdr->nops < 1))
                return nfs4_stat_to_errno(hdr->status);
        return 0;