OSDN Git Service

nfsd: handle nfs3 timestamps as unsigned
authorArnd Bergmann <arnd@arndb.de>
Thu, 31 Oct 2019 13:55:32 +0000 (14:55 +0100)
committerJ. Bruce Fields <bfields@redhat.com>
Thu, 19 Dec 2019 22:46:08 +0000 (17:46 -0500)
The decode_time3 function behaves differently on 32-bit
and 64-bit architectures: on the former, a 32-bit timestamp
gets converted into an signed number and then into a timestamp
between 1902 and 2038, while on the latter it is interpreted
as unsigned in the range 1970-2106.

Change all the remaining 'timespec' in nfsd to 'timespec64'
to make the behavior the same, and use the current interpretation
of the dominant 64-bit architectures.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/nfsd/nfs3xdr.c
fs/nfsd/nfsfh.h

index 195ab7a..c997b71 100644 (file)
@@ -32,14 +32,14 @@ static u32  nfs3_ftypes[] = {
  * XDR functions for basic NFS types
  */
 static __be32 *
-encode_time3(__be32 *p, struct timespec *time)
+encode_time3(__be32 *p, struct timespec64 *time)
 {
        *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
        return p;
 }
 
 static __be32 *
-decode_time3(__be32 *p, struct timespec *time)
+decode_time3(__be32 *p, struct timespec64 *time)
 {
        time->tv_sec = ntohl(*p++);
        time->tv_nsec = ntohl(*p++);
@@ -167,7 +167,6 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
              struct kstat *stat)
 {
        struct user_namespace *userns = nfsd_user_namespace(rqstp);
-       struct timespec ts;
        *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
        *p++ = htonl((u32) (stat->mode & S_IALLUGO));
        *p++ = htonl((u32) stat->nlink);
@@ -183,12 +182,9 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
        *p++ = htonl((u32) MINOR(stat->rdev));
        p = encode_fsid(p, fhp);
        p = xdr_encode_hyper(p, stat->ino);
-       ts = timespec64_to_timespec(stat->atime);
-       p = encode_time3(p, &ts);
-       ts = timespec64_to_timespec(stat->mtime);
-       p = encode_time3(p, &ts);
-       ts = timespec64_to_timespec(stat->ctime);
-       p = encode_time3(p, &ts);
+       p = encode_time3(p, &stat->atime);
+       p = encode_time3(p, &stat->mtime);
+       p = encode_time3(p, &stat->ctime);
 
        return p;
 }
@@ -277,8 +273,8 @@ void fill_pre_wcc(struct svc_fh *fhp)
                stat.size  = inode->i_size;
        }
 
-       fhp->fh_pre_mtime = timespec64_to_timespec(stat.mtime);
-       fhp->fh_pre_ctime = timespec64_to_timespec(stat.ctime);
+       fhp->fh_pre_mtime = stat.mtime;
+       fhp->fh_pre_ctime = stat.ctime;
        fhp->fh_pre_size  = stat.size;
        fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
        fhp->fh_pre_saved = true;
@@ -330,7 +326,7 @@ nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p)
        p = decode_sattr3(p, &args->attrs, nfsd_user_namespace(rqstp));
 
        if ((args->check_guard = ntohl(*p++)) != 0) { 
-               struct timespec time; 
+               struct timespec64 time;
                p = decode_time3(p, &time);
                args->guardtime = time.tv_sec;
        }
index b9c7568..56cfbc3 100644 (file)
@@ -42,8 +42,8 @@ typedef struct svc_fh {
 
        /* Pre-op attributes saved during fh_lock */
        __u64                   fh_pre_size;    /* size before operation */
-       struct timespec         fh_pre_mtime;   /* mtime before oper */
-       struct timespec         fh_pre_ctime;   /* ctime before oper */
+       struct timespec64       fh_pre_mtime;   /* mtime before oper */
+       struct timespec64       fh_pre_ctime;   /* ctime before oper */
        /*
         * pre-op nfsv4 change attr: note must check IS_I_VERSION(inode)
         *  to find out if it is valid.