mirror of
https://github.com/openbsd/src.git
synced 2026-06-18 07:13:36 +02:00
Add checks for invalid dir count and max size for readdir/readdirplus.
A zero count or max size value is now rejected early instead of relying on VOP_GETATTR to return an error. Also verify that the max size after rounding up to a multiple of DIRBLKSIZ is positive. A negative value would turn into a large allocation, causing the malloc() to fail. From an LLM bug report. With help from miod@ and kirill@.
This commit is contained in:
+34
-23
@@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: nfs_serv.c,v 1.132 2025/04/30 18:38:20 miod Exp $ */
|
||||
/* $OpenBSD: nfs_serv.c,v 1.133 2026/05/04 17:05:59 millert Exp $ */
|
||||
/* $NetBSD: nfs_serv.c,v 1.34 1997/05/12 23:37:12 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
@@ -2427,17 +2427,24 @@ nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
}
|
||||
off = toff;
|
||||
cnt = fxdr_unsigned(int, *tl);
|
||||
xfer = NFS_SRVMAXDATA(nfsd);
|
||||
if (cnt > xfer || cnt < 0)
|
||||
cnt = xfer;
|
||||
siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
|
||||
if (siz > xfer)
|
||||
siz = xfer;
|
||||
fullsiz = siz;
|
||||
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
|
||||
if (!error && vp->v_type != VDIR) {
|
||||
error = ENOTDIR;
|
||||
vput(vp);
|
||||
if (cnt == 0) {
|
||||
if (info.nmi_v3)
|
||||
error = NFSERR_TOOSMALL;
|
||||
else
|
||||
error = EBADRPC;
|
||||
} else {
|
||||
xfer = NFS_SRVMAXDATA(nfsd);
|
||||
if (cnt > xfer || cnt < 0)
|
||||
cnt = xfer;
|
||||
siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
|
||||
if (siz > xfer || siz <= 0)
|
||||
siz = xfer;
|
||||
fullsiz = siz;
|
||||
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
|
||||
if (!error && vp->v_type != VDIR) {
|
||||
error = ENOTDIR;
|
||||
vput(vp);
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
if (nfsm_reply(&info, nfsd, slp, mrq, error,
|
||||
@@ -2649,17 +2656,21 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
|
||||
tl += 2;
|
||||
siz = fxdr_unsigned(int, *tl++);
|
||||
cnt = fxdr_unsigned(int, *tl);
|
||||
xfer = NFS_SRVMAXDATA(nfsd);
|
||||
if (cnt > xfer || cnt < 0)
|
||||
cnt = xfer;
|
||||
siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
|
||||
if (siz > xfer)
|
||||
siz = xfer;
|
||||
fullsiz = siz;
|
||||
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
|
||||
if (!error && vp->v_type != VDIR) {
|
||||
error = ENOTDIR;
|
||||
vput(vp);
|
||||
if (siz == 0 || cnt == 0) {
|
||||
error = NFSERR_TOOSMALL;
|
||||
} else {
|
||||
xfer = NFS_SRVMAXDATA(nfsd);
|
||||
if (cnt > xfer || cnt < 0)
|
||||
cnt = xfer;
|
||||
siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
|
||||
if (siz > xfer || siz <= 0)
|
||||
siz = xfer;
|
||||
fullsiz = siz;
|
||||
error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly);
|
||||
if (!error && vp->v_type != VDIR) {
|
||||
error = ENOTDIR;
|
||||
vput(vp);
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
if (nfsm_reply(&info, nfsd, slp, mrq, error,
|
||||
|
||||
Reference in New Issue
Block a user