Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

SUNRPC: return proper error from get_expiry()

The get_expiry() function currently returns a timestamp, and uses the
special return value of 0 to indicate an error.

Unfortunately this causes a problem when 0 is the correct return value.

On a system with no RTC it is possible that the boot time will be seen
to be "3". When exportfs probes to see if a particular filesystem
supports NFS export it tries to cache information with an expiry time of
"3". The intention is for this to be "long in the past". Even with no
RTC it will not be far in the future (at most a second or two) so this
is harmless.
But if the boot time happens to have been calculated to be "3", then
get_expiry will fail incorrectly as it converts the number to "seconds
since bootime" - 0.

To avoid this problem we change get_expiry() to report the error quite
separately from the expiry time. The error is now the return value.
The expiry time is reported through a by-reference parameter.

Reported-by: Jerry Zhang <jerry@skydio.com>
Tested-by: Jerry Zhang <jerry@skydio.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>

authored by

NeilBrown and committed by
Chuck Lever
cf64b9bc 2f90e18f

+30 -30
+6 -7
fs/nfsd/export.c
··· 123 123 124 124 /* OK, we seem to have a valid key */ 125 125 key.h.flags = 0; 126 - key.h.expiry_time = get_expiry(&mesg); 127 - if (key.h.expiry_time == 0) 126 + err = get_expiry(&mesg, &key.h.expiry_time); 127 + if (err) 128 128 goto out; 129 129 130 - key.ek_client = dom; 130 + key.ek_client = dom; 131 131 key.ek_fsidtype = fsidtype; 132 132 memcpy(key.ek_fsid, buf, len); 133 133 ··· 610 610 exp.ex_devid_map = NULL; 611 611 612 612 /* expiry */ 613 - err = -EINVAL; 614 - exp.h.expiry_time = get_expiry(&mesg); 615 - if (exp.h.expiry_time == 0) 613 + err = get_expiry(&mesg, &exp.h.expiry_time); 614 + if (err) 616 615 goto out3; 617 616 618 617 /* flags */ ··· 623 624 if (err || an_int < 0) 624 625 goto out3; 625 626 exp.ex_flags= an_int; 626 - 627 + 627 628 /* anon uid */ 628 629 err = get_int(&mesg, &an_int); 629 630 if (err)
+4 -4
fs/nfsd/nfs4idmap.c
··· 240 240 goto out; 241 241 242 242 /* expiry */ 243 - ent.h.expiry_time = get_expiry(&buf); 244 - if (ent.h.expiry_time == 0) 243 + error = get_expiry(&buf, &ent.h.expiry_time); 244 + if (error) 245 245 goto out; 246 246 247 247 error = -ENOMEM; ··· 408 408 memcpy(ent.name, buf1, sizeof(ent.name)); 409 409 410 410 /* expiry */ 411 - ent.h.expiry_time = get_expiry(&buf); 412 - if (ent.h.expiry_time == 0) 411 + error = get_expiry(&buf, &ent.h.expiry_time); 412 + if (error) 413 413 goto out; 414 414 415 415 /* ID */
+8 -7
include/linux/sunrpc/cache.h
··· 300 300 return 0; 301 301 } 302 302 303 - static inline time64_t get_expiry(char **bpp) 303 + static inline int get_expiry(char **bpp, time64_t *rvp) 304 304 { 305 - time64_t rv; 305 + int error; 306 306 struct timespec64 boot; 307 307 308 - if (get_time(bpp, &rv)) 309 - return 0; 310 - if (rv < 0) 311 - return 0; 308 + error = get_time(bpp, rvp); 309 + if (error) 310 + return error; 311 + 312 312 getboottime64(&boot); 313 - return rv - boot.tv_sec; 313 + (*rvp) -= boot.tv_sec; 314 + return 0; 314 315 } 315 316 316 317 #endif /* _LINUX_SUNRPC_CACHE_H_ */
+6 -6
net/sunrpc/auth_gss/svcauth_gss.c
··· 257 257 258 258 rsii.h.flags = 0; 259 259 /* expiry */ 260 - expiry = get_expiry(&mesg); 261 - status = -EINVAL; 262 - if (expiry == 0) 260 + status = get_expiry(&mesg, &expiry); 261 + if (status) 263 262 goto out; 264 263 264 + status = -EINVAL; 265 265 /* major/minor */ 266 266 len = qword_get(&mesg, buf, mlen); 267 267 if (len <= 0) ··· 483 483 484 484 rsci.h.flags = 0; 485 485 /* expiry */ 486 - expiry = get_expiry(&mesg); 487 - status = -EINVAL; 488 - if (expiry == 0) 486 + status = get_expiry(&mesg, &expiry); 487 + if (status) 489 488 goto out; 490 489 490 + status = -EINVAL; 491 491 rscp = rsc_lookup(cd, &rsci); 492 492 if (!rscp) 493 493 goto out;
+6 -6
net/sunrpc/svcauth_unix.c
··· 225 225 return -EINVAL; 226 226 } 227 227 228 - expiry = get_expiry(&mesg); 229 - if (expiry ==0) 230 - return -EINVAL; 228 + err = get_expiry(&mesg, &expiry); 229 + if (err) 230 + return err; 231 231 232 232 /* domainname, or empty for NEGATIVE */ 233 233 len = qword_get(&mesg, buf, mlen); ··· 506 506 uid = make_kuid(current_user_ns(), id); 507 507 ug.uid = uid; 508 508 509 - expiry = get_expiry(&mesg); 510 - if (expiry == 0) 511 - return -EINVAL; 509 + err = get_expiry(&mesg, &expiry); 510 + if (err) 511 + return err; 512 512 513 513 rv = get_int(&mesg, &gids); 514 514 if (rv || gids < 0 || gids > 8192)