svn rev #25088: trunk/src/lib/krb5/os/

hartmans@MIT.EDU hartmans at MIT.EDU
Tue Aug 9 16:07:34 EDT 2011


http://src.mit.edu/fisheye/changelog/krb5/?cs=25088
Commit By: hartmans
Log Message:
Fix rare duplicate time issue On systems with imprecise clocks
(e.g. windows), there was as issue where microsecond rollover could
conceivably cause the same time to be reported twice. Also document
potential performance improvement by using thread-local storage for
last_time and eliminating the mutex.

Signed-off-by: Kevin Wasserman <kevin.wasserman at painless-security.com>
Signed-off-by: Sam Hartman <hartmans at painless-security.com>


Changed Files:
U   trunk/src/lib/krb5/os/c_ustime.c
Modified: trunk/src/lib/krb5/os/c_ustime.c
===================================================================
--- trunk/src/lib/krb5/os/c_ustime.c	2011-08-09 20:07:23 UTC (rev 25087)
+++ trunk/src/lib/krb5/os/c_ustime.c	2011-08-09 20:07:34 UTC (rev 25088)
@@ -83,6 +83,11 @@
     if (err)
         return err;
 
+    /* It would probably be more efficient to remove this mutex and use
+       thread-local storage for last_time.  But that could result in
+       different threads getting the same value for time, which may be
+       a technical violation of spec. */
+
     err = k5_mutex_lock(&krb5int_us_time_mutex);
     if (err)
         return err;
@@ -94,16 +99,24 @@
        On Windows, where we get millisecond accuracy currently, that's
        quite likely.  On UNIX, it appears that we always get new
        microsecond values, so this case should never trigger.  */
-    if ((now.sec == last_time.sec) && (now.usec <= last_time.usec)) {
-        /* Same as last time??? */
+
+    /* Check for case where previously usec rollover caused bump in sec,
+       putting now.sec in the past.  But don't just use '<' because we
+       need to properly handle the case where the administrator intentionally
+       adjusted time backwards. */
+    if ((now.sec == last_time.sec-1) ||
+        ((now.sec == last_time.sec) && (now.usec <= last_time.usec))) {
+        /* Correct 'now' to be exactly one microsecond later than 'last_time'.
+           Note that _because_ we perform this hack, 'now' may be _earlier_
+           than 'last_time', even though the system time is monotonically
+           increasing. */
+
+        now.sec = last_time.sec;
         now.usec = ++last_time.usec;
         if (now.usec >= 1000000) {
             ++now.sec;
             now.usec = 0;
         }
-        /* For now, we're not worrying about the case of enough
-           returns of the same value that we roll over now.sec, and
-           the next call still gets the previous now.sec value.  */
     }
     last_time.sec = now.sec;    /* Remember for next time */
     last_time.usec = now.usec;




More information about the cvs-krb5 mailing list