summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordds <dds@FreeBSD.org>2006-01-03 21:58:21 +0000
committerdds <dds@FreeBSD.org>2006-01-03 21:58:21 +0000
commite2090521119fa0784e32129524558d6684ba4c69 (patch)
treec049892abc8478e41743636db5c394179001889c /sys
parentc5944732d82d8b2776786c7219fd7707310b5495 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/kern/vfs_extattr.c27
-rw-r--r--sys/kern/vfs_syscalls.c27
2 files changed, 48 insertions, 6 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);
}
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);
}
OpenPOWER on IntegriCloud