summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2010-04-06 01:14:49 +0000
committerrmacklem <rmacklem@FreeBSD.org>2010-04-06 01:14:49 +0000
commit5ef25d55acb6cc2f83074997e0382ac0a50832ff (patch)
tree1085c6711086c4c6e6be4e4e99d8b05c6a4c0d9d
parent7a6a4ef0c70e78d6d8e438c687976283875e40c4 (diff)
downloadFreeBSD-src-5ef25d55acb6cc2f83074997e0382ac0a50832ff.zip
FreeBSD-src-5ef25d55acb6cc2f83074997e0382ac0a50832ff.tar.gz
Harden the experimental NFS server a little, by adding range
checks on the length of the client's open/lock owner name. Also, add free()'s for one case where they were missing and would have caused a leak if NFSERR_BADXDR had been replied. Probably never happens, but the leak is now plugged, just in case. MFC after: 2 weeks
-rw-r--r--sys/fs/nfsserver/nfs_nfsdserv.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index 9a36287..50fa822 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -2086,6 +2086,10 @@ nfsrvd_lock(struct nfsrv_descript *nd, __unused int isdgram,
if (flags & NFSLCK_OPENTOLOCK) {
NFSM_DISSECT(tl, u_int32_t *, 5 * NFSX_UNSIGNED + NFSX_STATEID);
i = fxdr_unsigned(int, *(tl+4+(NFSX_STATEID / NFSX_UNSIGNED)));
+ if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ }
MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i,
M_NFSDSTATE, M_WAITOK);
stp->ls_ownerlen = i;
@@ -2229,6 +2233,10 @@ nfsrvd_lockt(struct nfsrv_descript *nd, __unused int isdgram,
NFSM_DISSECT(tl, u_int32_t *, 8 * NFSX_UNSIGNED);
i = fxdr_unsigned(int, *(tl + 7));
+ if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ goto nfsmout;
+ }
MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i,
M_NFSDSTATE, M_WAITOK);
stp->ls_ownerlen = i;
@@ -2350,6 +2358,8 @@ nfsrvd_locku(struct nfsrv_descript *nd, __unused int isdgram,
break;
default:
nd->nd_repstat = NFSERR_BADXDR;
+ free(stp, M_NFSDSTATE);
+ free(lop, M_NFSDLOCK);
goto nfsmout;
};
stp->ls_ownerlen = 0;
@@ -2439,6 +2449,14 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
named.ni_cnd.cn_nameiop = 0;
NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
i = fxdr_unsigned(int, *(tl + 5));
+ if (i <= 0 || i > NFSV4_OPAQUELIMIT) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ vrele(dp);
+#ifdef NFS4_ACL_EXTATTR_NAME
+ acl_free(aclp);
+#endif
+ return (0);
+ }
MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + i,
M_NFSDSTATE, M_WAITOK);
stp->ls_ownerlen = i;
@@ -3391,6 +3409,10 @@ nfsrvd_releaselckown(struct nfsrv_descript *nd, __unused int isdgram,
}
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
len = fxdr_unsigned(int, *(tl + 2));
+ if (len <= 0 || len > NFSV4_OPAQUELIMIT) {
+ nd->nd_repstat = NFSERR_BADXDR;
+ return (0);
+ }
MALLOC(stp, struct nfsstate *, sizeof (struct nfsstate) + len,
M_NFSDSTATE, M_WAITOK);
stp->ls_ownerlen = len;
OpenPOWER on IntegriCloud