git: ef4edb70c909 - main - nfsd: Add a sanity check for Owner/OwnerGroup string length

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Wed, 04 May 2022 20:59:42 UTC
The branch main has been updated by rmacklem:

URL: https://cgit.FreeBSD.org/src/commit/?id=ef4edb70c909fc2b1de867601c2230597d07daa0

commit ef4edb70c909fc2b1de867601c2230597d07daa0
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2022-05-04 20:58:22 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2022-05-04 20:58:22 +0000

    nfsd: Add a sanity check for Owner/OwnerGroup string length
    
    Robert Morris reported that, if a client sends an absurdly
    large Owner/OwnerGroup string, the kernel malloc() for the
    large size string can block forever.
    
    This patch adds a sanity limit for Owner/OwnerGroup string
    length.  Since the RFCs do not specify any limit and FreeBSD
    can handle a group name greater than 1Kbyte, the limit is
    set at a generous 10Kbytes.
    
    Reported by:    rtm@lcs.mit.edu
    PR:     260546
    MFC after:      2 weeks
---
 sys/fs/nfs/nfs.h            | 7 +++++++
 sys/fs/nfs/nfs_commonsubs.c | 4 ++--
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h
index 1a29a7e1d6ec..ffd612331c1f 100644
--- a/sys/fs/nfs/nfs.h
+++ b/sys/fs/nfs/nfs.h
@@ -143,6 +143,13 @@
 
 #define	NFS_READDIRBLKSIZ	DIRBLKSIZ	/* Minimal nm_readdirsize */
 
+/*
+ * The NFSv4 RFCs do not define an upper limit on the length of Owner and
+ * OwnerGroup strings.  Since FreeBSD handles a group name > 1024bytes in
+ * length, set a generous sanity limit of 10Kbytes.
+ */
+#define	NFSV4_MAXOWNERGROUPLEN	(10 * 1024)
+
 /*
  * Oddballs
  */
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 0a601553fa40..e11dba4d2d5e 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -1843,7 +1843,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
 		case NFSATTRBIT_OWNER:
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			j = fxdr_unsigned(int, *tl);
-			if (j < 0) {
+			if (j < 0 || j > NFSV4_MAXOWNERGROUPLEN) {
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
@@ -1876,7 +1876,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
 		case NFSATTRBIT_OWNERGROUP:
 			NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
 			j = fxdr_unsigned(int, *tl);
-			if (j < 0) {
+			if (j < 0 || j > NFSV4_MAXOWNERGROUPLEN) {
 				error =  NFSERR_BADXDR;
 				goto nfsmout;
 			}