nfsd: Decode and send 64bit time values

The seconds field of an nfstime4 structure is 64bit, but we are assuming
that the first 32bits are zero-filled.  So if the client tries to set
atime to a value before the epoch (touch -t 196001010101), then the
server will save the wrong value on disk.

Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Cc: stable@kernel.org
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
Bryan Schumaker 2013-04-19 16:09:38 -04:00 committed by J. Bruce Fields
parent ba138435d1
commit bf8d909705

View File

@ -344,10 +344,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
all 32 bits of 'nseconds'. */ all 32 bits of 'nseconds'. */
READ_BUF(12); READ_BUF(12);
len += 12; len += 12;
READ32(dummy32); READ64(iattr->ia_atime.tv_sec);
if (dummy32)
return nfserr_inval;
READ32(iattr->ia_atime.tv_sec);
READ32(iattr->ia_atime.tv_nsec); READ32(iattr->ia_atime.tv_nsec);
if (iattr->ia_atime.tv_nsec >= (u32)1000000000) if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
return nfserr_inval; return nfserr_inval;
@ -370,10 +367,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
all 32 bits of 'nseconds'. */ all 32 bits of 'nseconds'. */
READ_BUF(12); READ_BUF(12);
len += 12; len += 12;
READ32(dummy32); READ64(iattr->ia_mtime.tv_sec);
if (dummy32)
return nfserr_inval;
READ32(iattr->ia_mtime.tv_sec);
READ32(iattr->ia_mtime.tv_nsec); READ32(iattr->ia_mtime.tv_nsec);
if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
return nfserr_inval; return nfserr_inval;
@ -2372,8 +2366,7 @@ out_acl:
if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
if ((buflen -= 12) < 0) if ((buflen -= 12) < 0)
goto out_resource; goto out_resource;
WRITE32(0); WRITE64((s64)stat.atime.tv_sec);
WRITE32(stat.atime.tv_sec);
WRITE32(stat.atime.tv_nsec); WRITE32(stat.atime.tv_nsec);
} }
if (bmval1 & FATTR4_WORD1_TIME_DELTA) { if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
@ -2386,15 +2379,13 @@ out_acl:
if (bmval1 & FATTR4_WORD1_TIME_METADATA) { if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
if ((buflen -= 12) < 0) if ((buflen -= 12) < 0)
goto out_resource; goto out_resource;
WRITE32(0); WRITE64((s64)stat.ctime.tv_sec);
WRITE32(stat.ctime.tv_sec);
WRITE32(stat.ctime.tv_nsec); WRITE32(stat.ctime.tv_nsec);
} }
if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
if ((buflen -= 12) < 0) if ((buflen -= 12) < 0)
goto out_resource; goto out_resource;
WRITE32(0); WRITE64((s64)stat.mtime.tv_sec);
WRITE32(stat.mtime.tv_sec);
WRITE32(stat.mtime.tv_nsec); WRITE32(stat.mtime.tv_nsec);
} }
if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {