NFS: add new file handle decoders to in-kernel mountd client
authorChuck Lever <chuck.lever@oracle.com>
Thu, 18 Jun 2009 01:02:12 +0000 (18:02 -0700)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 18 Jun 2009 01:02:12 +0000 (18:02 -0700)
Introduce xdr_stream-based XDR file handle decoders to the in-kernel
mountd client.  These are more careful than the existing decoder
functions about buffer overflows and data type and range checking.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/mount_clnt.c

index 8429885bc72935ffe116c09757494c8838b3fc9d..dd8c6f448eaa15b19d1ff8c164f35a6a7d18bc07 100644 (file)
@@ -31,6 +31,8 @@
 #define encode_dirpath_sz      (1 + XDR_QUADLEN(MNTPATHLEN))
 #define MNT_status_sz          (1)
 #define MNT_fhs_status_sz      (1)
+#define MNT_fhandle_sz         XDR_QUADLEN(NFS2_FHSIZE)
+#define MNT_fhandle3_sz                (1 + XDR_QUADLEN(NFS3_FHSIZE))
 
 /*
  * XDR argument and result sizes
@@ -272,6 +274,20 @@ static int decode_status(struct xdr_stream *xdr, struct mountres *res)
        return 0;
 }
 
+static int decode_fhandle(struct xdr_stream *xdr, struct mountres *res)
+{
+       struct nfs_fh *fh = res->fh;
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, NFS2_FHSIZE);
+       if (unlikely(p == NULL))
+               return -EIO;
+
+       fh->size = NFS2_FHSIZE;
+       memcpy(fh->data, p, NFS2_FHSIZE);
+       return 0;
+}
+
 static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
 {
        unsigned int i;
@@ -295,6 +311,29 @@ static int decode_fhs_status(struct xdr_stream *xdr, struct mountres *res)
        return 0;
 }
 
+static int decode_fhandle3(struct xdr_stream *xdr, struct mountres *res)
+{
+       struct nfs_fh *fh = res->fh;
+       u32 size;
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, sizeof(size));
+       if (unlikely(p == NULL))
+               return -EIO;
+
+       size = ntohl(*p++);
+       if (size > NFS3_FHSIZE || size == 0)
+               return -EIO;
+
+       p = xdr_inline_decode(xdr, size);
+       if (unlikely(p == NULL))
+               return -EIO;
+
+       fh->size = size;
+       memcpy(fh->data, p, size);
+       return 0;
+}
+
 static int xdr_decode_fhstatus3(struct rpc_rqst *req, __be32 *p,
                                struct mnt_fhstatus *res)
 {