diff options
author | Bryan Schumaker <bjschuma@netapp.com> | 2013-04-19 16:09:38 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2013-04-23 14:49:37 -0400 |
commit | bf8d909705e9d9bac31d9b8eac6734d2b51332a7 (patch) | |
tree | 9ad53ba8e5d8b6cfd5dc85c86d243fb157a6b0e6 /fs | |
parent | ba138435d1f8b25aa2b787848ee939270a50e34f (diff) |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 19 |
1 files changed, 5 insertions, 14 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 1cf154511dae..888a600dad8c 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -344,10 +344,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
344 | all 32 bits of 'nseconds'. */ | 344 | all 32 bits of 'nseconds'. */ |
345 | READ_BUF(12); | 345 | READ_BUF(12); |
346 | len += 12; | 346 | len += 12; |
347 | READ32(dummy32); | 347 | READ64(iattr->ia_atime.tv_sec); |
348 | if (dummy32) | ||
349 | return nfserr_inval; | ||
350 | READ32(iattr->ia_atime.tv_sec); | ||
351 | READ32(iattr->ia_atime.tv_nsec); | 348 | READ32(iattr->ia_atime.tv_nsec); |
352 | if (iattr->ia_atime.tv_nsec >= (u32)1000000000) | 349 | if (iattr->ia_atime.tv_nsec >= (u32)1000000000) |
353 | return nfserr_inval; | 350 | return nfserr_inval; |
@@ -370,10 +367,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, | |||
370 | all 32 bits of 'nseconds'. */ | 367 | all 32 bits of 'nseconds'. */ |
371 | READ_BUF(12); | 368 | READ_BUF(12); |
372 | len += 12; | 369 | len += 12; |
373 | READ32(dummy32); | 370 | READ64(iattr->ia_mtime.tv_sec); |
374 | if (dummy32) | ||
375 | return nfserr_inval; | ||
376 | READ32(iattr->ia_mtime.tv_sec); | ||
377 | READ32(iattr->ia_mtime.tv_nsec); | 371 | READ32(iattr->ia_mtime.tv_nsec); |
378 | if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) | 372 | if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) |
379 | return nfserr_inval; | 373 | return nfserr_inval; |
@@ -2372,8 +2366,7 @@ out_acl: | |||
2372 | if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { | 2366 | if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { |
2373 | if ((buflen -= 12) < 0) | 2367 | if ((buflen -= 12) < 0) |
2374 | goto out_resource; | 2368 | goto out_resource; |
2375 | WRITE32(0); | 2369 | WRITE64((s64)stat.atime.tv_sec); |
2376 | WRITE32(stat.atime.tv_sec); | ||
2377 | WRITE32(stat.atime.tv_nsec); | 2370 | WRITE32(stat.atime.tv_nsec); |
2378 | } | 2371 | } |
2379 | if (bmval1 & FATTR4_WORD1_TIME_DELTA) { | 2372 | if (bmval1 & FATTR4_WORD1_TIME_DELTA) { |
@@ -2386,15 +2379,13 @@ out_acl: | |||
2386 | if (bmval1 & FATTR4_WORD1_TIME_METADATA) { | 2379 | if (bmval1 & FATTR4_WORD1_TIME_METADATA) { |
2387 | if ((buflen -= 12) < 0) | 2380 | if ((buflen -= 12) < 0) |
2388 | goto out_resource; | 2381 | goto out_resource; |
2389 | WRITE32(0); | 2382 | WRITE64((s64)stat.ctime.tv_sec); |
2390 | WRITE32(stat.ctime.tv_sec); | ||
2391 | WRITE32(stat.ctime.tv_nsec); | 2383 | WRITE32(stat.ctime.tv_nsec); |
2392 | } | 2384 | } |
2393 | if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { | 2385 | if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { |
2394 | if ((buflen -= 12) < 0) | 2386 | if ((buflen -= 12) < 0) |
2395 | goto out_resource; | 2387 | goto out_resource; |
2396 | WRITE32(0); | 2388 | WRITE64((s64)stat.mtime.tv_sec); |
2397 | WRITE32(stat.mtime.tv_sec); | ||
2398 | WRITE32(stat.mtime.tv_nsec); | 2389 | WRITE32(stat.mtime.tv_nsec); |
2399 | } | 2390 | } |
2400 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { | 2391 | if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { |