diff options
author | Alan Somers <asomers@FreeBSD.org> | 2021-12-13 03:57:14 +0000 |
---|---|---|
committer | Alan Somers <asomers@FreeBSD.org> | 2022-01-03 03:09:15 +0000 |
commit | 8ec62f06143a54dcb917cba4f24cf7c7a614265a (patch) | |
tree | f4161510fa92f3652ca2ca1903d09ef61f2dd629 | |
parent | 642399932d58e880ac4a65ab6011a94292b37134 (diff) | |
download | src-8ec62f06143a54dcb917cba4f24cf7c7a614265a.tar.gz src-8ec62f06143a54dcb917cba4f24cf7c7a614265a.zip |
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)
-rw-r--r-- | sys/fs/nfs/xdr_subs.h | 10 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdport.c | 13 | ||||
-rw-r--r-- | sys/fs/nfsserver/nfs_nfsdsubs.c | 6 | ||||
-rw-r--r-- | 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 f28d973a867a..26bd900a2a99 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -2257,10 +2257,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; @@ -2748,8 +2749,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); @@ -2758,8 +2758,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 9e278dbab7e5..ca691941ed0d 100644 --- a/sys/fs/nfsserver/nfs_nfsdsubs.c +++ b/sys/fs/nfsserver/nfs_nfsdsubs.c @@ -1433,13 +1433,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 a4f7ae0b7e40..84155035c1cd 100644 --- a/sys/nfs/xdr_subs.h +++ b/sys/nfs/xdr_subs.h @@ -83,10 +83,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 |