]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
lib: harden full_timespec_to_nt_time()
authorRalph Boehme <slow@samba.org>
Fri, 6 Dec 2019 16:45:04 +0000 (16:45 +0000)
committerRalph Boehme <slow@samba.org>
Mon, 9 Dec 2019 16:10:38 +0000 (16:10 +0000)
This protects against overflows when tv_sec is less then
TIME_FIXUP_CONSTANT_INT.

It also correctly limits the range of returned values to be
[NTTIME_MIN, NTTIME_MAX].

Signed-off-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
lib/util/time.c

index 0875c9fbda9e4c486cc16c5511058b592f51a49a..d8f1daca901451b512939bfebac4c6f8ec1a7926 100644 (file)
@@ -1080,23 +1080,37 @@ struct timespec make_omit_timespec(void)
  * Like unix_timespec_to_nt_time() but without the special casing of tv_sec=0
  * and -1. Also dealing with SAMBA_UTIME_OMIT.
  **/
-NTTIME full_timespec_to_nt_time(const struct timespec *ts)
+NTTIME full_timespec_to_nt_time(const struct timespec *_ts)
 {
+       struct timespec ts = *_ts;
        uint64_t d;
 
-       if (ts->tv_sec == TIME_T_MAX) {
-               return 0x7fffffffffffffffLL;
+       if (is_omit_timespec(_ts)) {
+               return NTTIME_OMIT;
        }
 
-       if (is_omit_timespec(ts)) {
-               return 0;
+       /* Ensure tv_nsec is less than 1 sec. */
+       while (ts.tv_nsec > 1000000000) {
+               if (ts.tv_sec > TIME_T_MAX) {
+                       return NTTIME_MAX;
+               }
+               ts.tv_sec += 1;
+               ts.tv_nsec -= 1000000000;
        }
 
-       d = ts->tv_sec;
-       d += TIME_FIXUP_CONSTANT_INT;
+       if (ts.tv_sec >= TIME_T_MAX) {
+               return NTTIME_MAX;
+       }
+       if ((ts.tv_sec + TIME_FIXUP_CONSTANT_INT) <= 0) {
+               return NTTIME_MIN;
+       }
+
+       d = TIME_FIXUP_CONSTANT_INT;
+       d += ts.tv_sec;
+
        d *= 1000*1000*10;
        /* d is now in 100ns units. */
-       d += (ts->tv_nsec / 100);
+       d += (ts.tv_nsec / 100);
 
        return d;
 }