diff options
author | dds <dds@FreeBSD.org> | 2006-01-03 21:58:21 +0000 |
---|---|---|
committer | dds <dds@FreeBSD.org> | 2006-01-03 21:58:21 +0000 |
commit | e2090521119fa0784e32129524558d6684ba4c69 (patch) | |
tree | c049892abc8478e41743636db5c394179001889c /sys/kern/vfs_extattr.c | |
parent | c5944732d82d8b2776786c7219fd7707310b5495 (diff) | |
download | FreeBSD-src-e2090521119fa0784e32129524558d6684ba4c69.zip FreeBSD-src-e2090521119fa0784e32129524558d6684ba4c69.tar.gz |
Normalize the tv_usec part of the utimes(2) arguments to ensure
that a file's atime and mtime are only set to correct fractional
second values (0-999999000ns with the current interface).
Prior to this change users could create files with values outside
that range. Moreover, on 32-bit machines tv_usec offsets larger than
4.3s would result in an unnormalized AND wrong timestamp value,
due to overflow.
MFC after: 1 week
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r-- | sys/kern/vfs_extattr.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 1632076..8939d18 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -2713,6 +2713,25 @@ fchown(td, uap) } /* + * Normalize the tv_usec value of t within the allowed range. + */ +static struct timeval +normalize_timeval(const struct timeval *t) +{ + struct timeval n; + + if (t->tv_usec >= 0 && t->tv_usec < 1000000) + return *t; + n.tv_sec = t->tv_sec + t->tv_usec / 1000000; + n.tv_usec = t->tv_usec % 1000000; + if (n.tv_usec < 0) { + n.tv_sec--; + n.tv_usec += 1000000; + } + return n; +} + +/* * Common implementation code for utimes(), lutimes(), and futimes(). */ static int @@ -2721,7 +2740,7 @@ getutimes(usrtvp, tvpseg, tsp) enum uio_seg tvpseg; struct timespec *tsp; { - struct timeval tv[2]; + struct timeval tv[2], tvn; const struct timeval *tvp; int error; @@ -2738,8 +2757,10 @@ getutimes(usrtvp, tvpseg, tsp) tvp = tv; } - TIMEVAL_TO_TIMESPEC(&tvp[0], &tsp[0]); - TIMEVAL_TO_TIMESPEC(&tvp[1], &tsp[1]); + tvn = normalize_timeval(&tvp[0]); + TIMEVAL_TO_TIMESPEC(&tvn, &tsp[0]); + tvn = normalize_timeval(&tvp[1]); + TIMEVAL_TO_TIMESPEC(&tvn, &tsp[1]); } return (0); } |