aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2025-01-10 03:54:41 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2025-01-10 03:54:41 +0000
commitf9f0a1d61c7b97c705246c747baec385e0592966 (patch)
tree34d5c0361273e83f0e900492ceaf0ac0c00c3a2c
parented49d3b31d425a0add04aff6eb721a474937b7da (diff)
nfscl: Fix a crash when a readdir entry has nul in it
Commit 026cdaa3b3a9 added a check for a nul or "/" in a file name in a readdir reply. Unfortunately, the minimal testing done on it did not detect a bug that can cause the client to crash. This patch fixes the code so that it does not crash. Note that a NFS server will not normally return a file name in a readdir reply that has a nul or "/" in it, so the crash is unlikely. PR: 283965 Reported by: asomers Tested by: asomers MFC after: 2 weeks
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index e1c02a71939b..c35d0c6295b9 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -3397,6 +3397,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
nfsattrbit_t attrbits, dattrbits;
u_int32_t rderr, *tl2 = NULL;
size_t tresid;
+ bool validentry;
KASSERT(uiop->uio_iovcnt == 1 &&
(uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
@@ -3622,6 +3623,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
/* loop through the dir entries, doctoring them to 4bsd form */
while (more_dirs && bigenough) {
+ validentry = true;
if (nd->nd_flag & ND_NFSV4) {
NFSM_DISSECT(tl, u_int32_t *, 3*NFSX_UNSIGNED);
ncookie.lval[0] = *tl++;
@@ -3701,6 +3703,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
uiop->uio_offset = savoff;
uiop->uio_resid = savresid;
blksiz = savblksiz;
+ validentry = false;
} else {
cp = uiop->uio_iov->iov_base;
tlen -= len;
@@ -3738,7 +3741,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
ncookie.lval[0] = 0;
ncookie.lval[1] = *tl++;
}
- if (bigenough) {
+ if (bigenough && validentry) {
if (nd->nd_flag & ND_NFSV4) {
if (rderr) {
dp->d_fileno = 0;
@@ -3875,7 +3878,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
size_t tresid;
u_int32_t *tl2 = NULL, rderr;
struct timespec dctime, ts;
- bool attr_ok;
+ bool attr_ok, validentry;
KASSERT(uiop->uio_iovcnt == 1 &&
(uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
@@ -4086,6 +4089,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
/* loop through the dir entries, doctoring them to 4bsd form */
while (more_dirs && bigenough) {
+ validentry = true;
NFSM_DISSECT(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
if (nd->nd_flag & ND_NFSV4) {
ncookie.lval[0] = *tl++;
@@ -4161,6 +4165,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
uiop->uio_offset = savoff;
uiop->uio_resid = savresid;
blksiz = savblksiz;
+ validentry = false;
} else {
cp = uiop->uio_iov->iov_base;
tlen -= len;
@@ -4217,7 +4222,7 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
goto nfsmout;
}
- if (bigenough) {
+ if (bigenough && validentry) {
if (nd->nd_flag & ND_NFSV4) {
if (rderr) {
dp->d_fileno = 0;