git: 374e8226d225 - stable/12 - nfs: don't truncate directory cookies to 32-bits in the NFS server
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 03 Jan 2022 05:44:30 UTC
The branch stable/12 has been updated by asomers:
URL: https://cgit.FreeBSD.org/src/commit/?id=374e8226d2252da6421a05313a7ac223fc00c432
commit 374e8226d2252da6421a05313a7ac223fc00c432
Author: Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2021-12-13 03:57:14 +0000
Commit: Alan Somers <asomers@FreeBSD.org>
CommitDate: 2022-01-03 05:37:51 +0000
nfs: don't truncate directory cookies to 32-bits in the NFS server
In NFSv2, the directory cookie was 32-bits. NFSv3 widened it to
64-bits and SVN r22521 widened the corresponding argument in
VOP_READDIR, but FreeBSD's NFS server continued to treat the cookies as
32-bits, and 0-extended to fill the field on the wire. Nobody ever
noticed, because every in-tree file system generates cookies that fit
comfortably within 32-bits.
Also, have better type safety for txdr_hyper. Turn it into an inline
function that type-checks its arguments. Prevents warnings about
shift-count-overflow.
PR: 260375
Reviewed by: rmacklem
Differential Revision: https://reviews.freebsd.org/D33404
(cherry picked from commit 32fbc5d824f51f97220bc5c61a23e0bf3ff2b470)
---
sys/fs/nfs/xdr_subs.h | 10 ++++++----
sys/fs/nfsserver/nfs_nfsdport.c | 13 ++++++-------
sys/fs/nfsserver/nfs_nfsdsubs.c | 6 +++---
sys/nfs/xdr_subs.h | 12 +++++++-----
4 files changed, 22 insertions(+), 19 deletions(-)
diff --git a/sys/fs/nfs/xdr_subs.h b/sys/fs/nfs/xdr_subs.h
index 54c7d914983e..9a6d4608d5f1 100644
--- a/sys/fs/nfs/xdr_subs.h
+++ b/sys/fs/nfs/xdr_subs.h
@@ -93,9 +93,11 @@
((((u_quad_t)ntohl(((u_int32_t *)(f))[0])) << 32) | \
(u_quad_t)(ntohl(((u_int32_t *)(f))[1])))
-#define txdr_hyper(f, t) do { \
- ((u_int32_t *)(t))[0] = htonl((u_int32_t)((f) >> 32)); \
- ((u_int32_t *)(t))[1] = htonl((u_int32_t)((f) & 0xffffffff)); \
- } while (0)
+static inline void
+txdr_hyper(uint64_t f, uint32_t* t)
+{
+ t[0] = htonl((u_int32_t)(f >> 32));
+ t[1] = htonl((u_int32_t)(f & 0xffffffff));
+}
#endif /* _NFS_XDR_SUBS_H_ */
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 0bb3edbddec9..0f3852318068 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -2026,10 +2026,11 @@ again:
(void) nfsm_strtom(nd, dp->d_name, nlen);
if (nd->nd_flag & ND_NFSV3) {
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = 0;
- } else
+ txdr_hyper(*cookiep, tl);
+ } else {
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
- *tl = txdr_unsigned(*cookiep);
+ *tl = txdr_unsigned(*cookiep);
+ }
}
cpos += dp->d_reclen;
dp = (struct dirent *)cpos;
@@ -2496,8 +2497,7 @@ again:
*tl = txdr_unsigned(dp->d_fileno);
dirlen += nfsm_strtom(nd, dp->d_name, nlen);
NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
- *tl++ = 0;
- *tl = txdr_unsigned(*cookiep);
+ txdr_hyper(*cookiep, tl);
nfsrv_postopattr(nd, 0, nvap);
dirlen += nfsm_fhtom(nd,(u_int8_t *)&nfh,0,1);
dirlen += (5*NFSX_UNSIGNED+NFSX_V3POSTOPATTR);
@@ -2506,8 +2506,7 @@ again:
} else {
NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
*tl++ = newnfs_true;
- *tl++ = 0;
- *tl = txdr_unsigned(*cookiep);
+ txdr_hyper(*cookiep, tl);
dirlen += nfsm_strtom(nd, dp->d_name, nlen);
if (nvp != NULL) {
supports_nfsv4acls =
diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c b/sys/fs/nfsserver/nfs_nfsdsubs.c
index 9ab5ca174b29..e4dcb77001a6 100644
--- a/sys/fs/nfsserver/nfs_nfsdsubs.c
+++ b/sys/fs/nfsserver/nfs_nfsdsubs.c
@@ -1394,13 +1394,13 @@ nfsrv_fillattr(struct nfsrv_descript *nd, struct nfsvattr *nvap)
if (nd->nd_flag & ND_NFSV3) {
fp->fa_type = vtonfsv34_type(nvap->na_type);
fp->fa_mode = vtonfsv34_mode(nvap->na_mode);
- txdr_hyper(nvap->na_size, &fp->fa3_size);
- txdr_hyper(nvap->na_bytes, &fp->fa3_used);
+ txdr_hyper(nvap->na_size, (uint32_t*)&fp->fa3_size);
+ txdr_hyper(nvap->na_bytes, (uint32_t*)&fp->fa3_used);
fp->fa3_rdev.specdata1 = txdr_unsigned(NFSMAJOR(nvap->na_rdev));
fp->fa3_rdev.specdata2 = txdr_unsigned(NFSMINOR(nvap->na_rdev));
fp->fa3_fsid.nfsuquad[0] = 0;
fp->fa3_fsid.nfsuquad[1] = txdr_unsigned(nvap->na_fsid);
- txdr_hyper(nvap->na_fileid, &fp->fa3_fileid);
+ txdr_hyper(nvap->na_fileid, (uint32_t*)&fp->fa3_fileid);
txdr_nfsv3time(&nvap->na_atime, &fp->fa3_atime);
txdr_nfsv3time(&nvap->na_mtime, &fp->fa3_mtime);
txdr_nfsv3time(&nvap->na_ctime, &fp->fa3_ctime);
diff --git a/sys/nfs/xdr_subs.h b/sys/nfs/xdr_subs.h
index 829711e8ddd5..f5a38277c300 100644
--- a/sys/nfs/xdr_subs.h
+++ b/sys/nfs/xdr_subs.h
@@ -84,10 +84,12 @@ do { \
#define fxdr_hyper(f) \
((((u_quad_t)ntohl(((u_int32_t *)(f))[0])) << 32) | \
(u_quad_t)(ntohl(((u_int32_t *)(f))[1])))
-#define txdr_hyper(f, t) \
-do { \
- ((u_int32_t *)(t))[0] = htonl((u_int32_t)((f) >> 32)); \
- ((u_int32_t *)(t))[1] = htonl((u_int32_t)((f) & 0xffffffff)); \
-} while (0)
+
+static inline void
+txdr_hyper(uint64_t f, uint32_t* t)
+{
+ t[0] = htonl((u_int32_t)(f >> 32));
+ t[1] = htonl((u_int32_t)(f & 0xffffffff));
+}
#endif