From e2090521119fa0784e32129524558d6684ba4c69 Mon Sep 17 00:00:00 2001 From: dds Date: Tue, 3 Jan 2006 21:58:21 +0000 Subject: 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 --- sys/kern/vfs_extattr.c | 27 ++++++++++++++++++++++++--- sys/kern/vfs_syscalls.c | 27 ++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) (limited to 'sys') 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); } diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 1632076..8939d18 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.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); } -- cgit v1.1