Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

NFSv4: Catch and trace server filehandle encoding errors

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>

+14 -6
+2 -2
fs/nfs/nfs3xdr.c
··· 433 433 if (unlikely(!p)) 434 434 return -EIO; 435 435 length = be32_to_cpup(p++); 436 - if (unlikely(length > NFS3_FHSIZE)) 436 + if (unlikely(length > NFS3_FHSIZE || length == 0)) 437 437 goto out_toobig; 438 438 p = xdr_inline_decode(xdr, length); 439 439 if (unlikely(!p)) ··· 442 442 memcpy(fh->data, p, length); 443 443 return 0; 444 444 out_toobig: 445 - dprintk("NFS: file handle size (%u) too big\n", length); 445 + trace_nfs_xdr_bad_filehandle(xdr, NFSERR_BADHANDLE); 446 446 return -E2BIG; 447 447 } 448 448
+1
fs/nfs/nfs4trace.h
··· 745 745 ), \ 746 746 TP_ARGS(xdr, op, error)) 747 747 DEFINE_NFS4_XDR_EVENT(nfs4_xdr_status); 748 + DEFINE_NFS4_XDR_EVENT(nfs4_xdr_bad_filehandle); 748 749 749 750 DECLARE_EVENT_CLASS(nfs4_cb_error_class, 750 751 TP_PROTO(
+9 -4
fs/nfs/nfs4xdr.c
··· 3495 3495 if (unlikely(!p)) 3496 3496 return -EIO; 3497 3497 len = be32_to_cpup(p); 3498 - if (len > NFS4_FHSIZE) 3499 - return -EIO; 3498 + if (len > NFS4_FHSIZE || len == 0) { 3499 + trace_nfs4_xdr_bad_filehandle(xdr, OP_READDIR, 3500 + NFS4ERR_BADHANDLE); 3501 + return -EREMOTEIO; 3502 + } 3500 3503 p = xdr_inline_decode(xdr, len); 3501 3504 if (unlikely(!p)) 3502 3505 return -EIO; ··· 4955 4952 if (unlikely(!p)) 4956 4953 return -EIO; 4957 4954 len = be32_to_cpup(p); 4958 - if (len > NFS4_FHSIZE) 4959 - return -EIO; 4955 + if (len > NFS4_FHSIZE || len == 0) { 4956 + trace_nfs4_xdr_bad_filehandle(xdr, OP_GETFH, NFS4ERR_BADHANDLE); 4957 + return -EREMOTEIO; 4958 + } 4960 4959 fh->size = len; 4961 4960 p = xdr_inline_decode(xdr, len); 4962 4961 if (unlikely(!p))
+1
fs/nfs/nfstrace.c
··· 12 12 EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_enter); 13 13 EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_fsync_exit); 14 14 EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_xdr_status); 15 + EXPORT_TRACEPOINT_SYMBOL_GPL(nfs_xdr_bad_filehandle);
+1
fs/nfs/nfstrace.h
··· 1451 1451 ), \ 1452 1452 TP_ARGS(xdr, error)) 1453 1453 DEFINE_NFS_XDR_EVENT(nfs_xdr_status); 1454 + DEFINE_NFS_XDR_EVENT(nfs_xdr_bad_filehandle); 1454 1455 1455 1456 #endif /* _TRACE_NFS_H */ 1456 1457