Commit 92c5e469 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by J. Bruce Fields
Browse files

nfsd: handle nfs3 timestamps as unsigned



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: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent e29f4703
Loading
Loading
Loading
Loading
+8 −12
Original line number Diff line number Diff line
@@ -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;
	}
+2 −2
Original line number Diff line number Diff line
@@ -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.