git: f9f0a1d61c7b - main - nfscl: Fix a crash when a readdir entry has nul in it
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 10 Jan 2025 03:56:12 UTC
The branch main has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=f9f0a1d61c7b97c705246c747baec385e0592966
commit f9f0a1d61c7b97c705246c747baec385e0592966
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2025-01-10 03:54:41 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2025-01-10 03:54:41 +0000
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
---
sys/fs/nfsclient/nfs_clrpcops.c | 11 ++++++++---
1 file 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;