aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2022-05-04 20:58:22 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2022-05-20 00:43:22 +0000
commitc0ea059da22f0f1f20ee43db536a74032f140429 (patch)
treeeba0387bd15bbba1d81e3bc0aa166c3cd1f32252
parent6aaf8a8b1bcf500aa7342043d43007ff9c52cd65 (diff)
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. PR: 260546 (cherry picked from commit ef4edb70c909fc2b1de867601c2230597d07daa0)
-rw-r--r--sys/fs/nfs/nfs.h7
-rw-r--r--sys/fs/nfs/nfs_commonsubs.c4
2 files changed, 9 insertions, 2 deletions
diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h
index de35f40f40d0..b6af8902ca98 100644
--- a/sys/fs/nfs/nfs.h
+++ b/sys/fs/nfs/nfs.h
@@ -144,6 +144,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
*/
#define NFS_CMPFH(n, f, s) \
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index c7271cffe1ab..3ccfb6cce0d2 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -1815,7 +1815,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;
}
@@ -1848,7 +1848,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;
}