OSDN Git Service

NFSv4: Catch and trace server filehandle encoding errors
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Thu, 1 Apr 2021 18:03:26 +0000 (14:03 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Wed, 14 Apr 2021 13:36:29 +0000 (09:36 -0400)
If the server returns a filehandle with an invalid length, then trace
that, and return an EREMOTEIO error.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/nfs3xdr.c
fs/nfs/nfs4trace.h
fs/nfs/nfs4xdr.c
fs/nfs/nfstrace.c
fs/nfs/nfstrace.h

index 83ad62c..e6eca1d 100644 (file)
@@ -433,7 +433,7 @@ static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
        if (unlikely(!p))
                return -EIO;
        length = be32_to_cpup(p++);
-       if (unlikely(length > NFS3_FHSIZE))
+       if (unlikely(length > NFS3_FHSIZE || length == 0))
                goto out_toobig;
        p = xdr_inline_decode(xdr, length);
        if (unlikely(!p))
@@ -442,7 +442,7 @@ static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
        memcpy(fh->data, p, length);
        return 0;
 out_toobig:
-       dprintk("NFS: file handle size (%u) too big\n", length);
+       trace_nfs_xdr_bad_filehandle(xdr, NFSERR_BADHANDLE);
        return -E2BIG;
 }
 
index 114983a..2ef75ca 100644 (file)
@@ -745,6 +745,7 @@ DECLARE_EVENT_CLASS(nfs4_xdr_event,
                        ), \
                        TP_ARGS(xdr, op, error))
 DEFINE_NFS4_XDR_EVENT(nfs4_xdr_status);
+DEFINE_NFS4_XDR_EVENT(nfs4_xdr_bad_filehandle);
 
 DECLARE_EVENT_CLASS(nfs4_cb_error_class,
                TP_PROTO(
index ee7a7a1..3d7e10c 100644 (file)
@@ -3495,8 +3495,11 @@ static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, stru
                if (unlikely(!p))
                        return -EIO;
                len = be32_to_cpup(p);
-               if (len > NFS4_FHSIZE)
-                       return -EIO;
+               if (len > NFS4_FHSIZE || len == 0) {
+                       trace_nfs4_xdr_bad_filehandle(xdr, OP_READDIR,
+                                                     NFS4ERR_BADHANDLE);
+                       return -EREMOTEIO;
+               }
                p = xdr_inline_decode(xdr, len);
                if (unlikely(!p))
                        return -EIO;
@@ -4952,8 +4955,10 @@ static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
        if (unlikely(!p))
                return -EIO;
        len = be32_to_cpup(p);
-       if (len > NFS4_FHSIZE)
-               return -EIO;
+       if (len > NFS4_FHSIZE || len == 0) {
+               trace_nfs4_xdr_bad_filehandle(xdr, OP_GETFH, NFS4ERR_BADHANDLE);
+               return -EREMOTEIO;
+       }
        fh->size = len;
        p = xdr_inline_decode(xdr, len);
        if (unlikely(!p))
index a90b363..5d1bfcc 100644 (file)
@@ -12,3 +12,4 @@
 EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_enter);
 EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_exit);
 EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_xdr_status);
+EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_xdr_bad_filehandle);
index 45eda4d..eb1ef34 100644 (file)
@@ -1451,6 +1451,7 @@ DECLARE_EVENT_CLASS(nfs_xdr_event,
                        ), \
                        TP_ARGS(xdr, error))
 DEFINE_NFS_XDR_EVENT(nfs_xdr_status);
+DEFINE_NFS_XDR_EVENT(nfs_xdr_bad_filehandle);
 
 #endif /* _TRACE_NFS_H */