]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: fix time_t handling
authorSamanta Navarro <ferivoz@riseup.net>
Sun, 8 Nov 2020 11:46:56 +0000 (11:46 +0000)
committerSamanta Navarro <ferivoz@riseup.net>
Tue, 10 Nov 2020 11:52:45 +0000 (11:52 +0000)
The time_t data type is a signed integer. A signed integer overflow is
not defined in C programming language.

A signed overflow occurs on 32 bit systems with 32 time_t for loop back
devices, e.g. when calling "blkid /dev/loop0". This happens because
bid_time is set to INT_MIN and the diff calculation cannot store the
result in time_t (positive int - INT_MIN > INT_MAX).

This fix changes the code to use an unsigned integer calculation. It
pretty much means that the code works as before, but well defined in C.
Checking diff to be positive protects the code against system setups
with dates before 1970 as well.

The time_t data type on modern Linux systems is 64 bit even for 32 bit
systems. Since long is 32 bit on these systems, long long is a better
data type for 64 bit output.

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
libblkid/src/dev.c
libblkid/src/devname.c
libblkid/src/save.c
libblkid/src/verify.c

index 056df2b867962ac5fb6c06ac88f8f3be7bdfae55..c38ec3d3213445770a34fded2738a93090d75aa7 100644 (file)
@@ -87,8 +87,8 @@ void blkid_debug_dump_dev(blkid_dev dev)
        }
 
        fprintf(stderr, "  dev: name = %s\n", dev->bid_name);
-       fprintf(stderr, "  dev: DEVNO=\"0x%0llx\"\n", (long long)dev->bid_devno);
-       fprintf(stderr, "  dev: TIME=\"%ld.%ld\"\n", (long)dev->bid_time, (long)dev->bid_utime);
+       fprintf(stderr, "  dev: DEVNO=\"0x%0lx\"\n", (unsigned long)dev->bid_devno);
+       fprintf(stderr, "  dev: TIME=\"%lld.%lld\"\n", (long long)dev->bid_time, (long long)dev->bid_utime);
        fprintf(stderr, "  dev: PRI=\"%d\"\n", dev->bid_pri);
        fprintf(stderr, "  dev: flags = 0x%08X\n", dev->bid_flags);
 
index 5582551316eb3019b150e5ec54692d0d510345b5..c541d30ba6a78fd824b28f9e4fe57715ea09a802 100644 (file)
@@ -92,7 +92,7 @@ blkid_dev blkid_get_dev(blkid_cache cache, const char *devname, int flags)
                dev = blkid_new_dev();
                if (!dev)
                        goto done;
-               dev->bid_time = INT_MIN;
+               dev->bid_time = (uintmax_t)1 << (sizeof(time_t) * 8 - 1);
                if (cn) {
                        dev->bid_name = cn;
                        dev->bid_xname = strdup(devname);
index bceaa11398ebd26392fdbfc210d641746efb0116..9a342c69cfef1881af469fdb04fb15e6c51ae2c7 100644 (file)
@@ -52,10 +52,10 @@ static int save_dev(blkid_dev dev, FILE *file)
        DBG(SAVE, ul_debug("device %s, type %s", dev->bid_name, dev->bid_type ?
                   dev->bid_type : "(null)"));
 
-       fprintf(file, "<device DEVNO=\"0x%04lx\" TIME=\"%ld.%ld\"",
+       fprintf(file, "<device DEVNO=\"0x%04lx\" TIME=\"%lld.%lld\"",
                        (unsigned long) dev->bid_devno,
-                       (long) dev->bid_time,
-                       (long) dev->bid_utime);
+                       (long long) dev->bid_time,
+                       (long long) dev->bid_utime);
 
        if (dev->bid_pri)
                fprintf(file, " PRI=\"%d\"", dev->bid_pri);
index db38623732e6c7887e77701f88509bff9ffdf6be..3b9754f57df286faa6169e5845b461313e899377 100644 (file)
@@ -70,7 +70,7 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
                return NULL;
 
        now = time(NULL);
-       diff = now - dev->bid_time;
+       diff = (uintmax_t)now - dev->bid_time;
 
        if (stat(dev->bid_name, &st) < 0) {
                DBG(PROBE, ul_debug("blkid_verify: error %s (%d) while "
@@ -95,23 +95,23 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
 #else
            st.st_mtime <= dev->bid_time &&
 #endif
-           diff < BLKID_PROBE_MIN) {
+           diff >= 0 && diff < BLKID_PROBE_MIN) {
                dev->bid_flags |= BLKID_BID_FL_VERIFIED;
                return dev;
        }
 
 #ifndef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
-       DBG(PROBE, ul_debug("need to revalidate %s (cache time %lu, stat time %lu,\t"
-                  "time since last check %lu)",
-                  dev->bid_name, (unsigned long)dev->bid_time,
-                  (unsigned long)st.st_mtime, (unsigned long)diff));
+       DBG(PROBE, ul_debug("need to revalidate %s (cache time %lld, stat time %lld,\t"
+                  "time since last check %lld)",
+                  dev->bid_name, (long long)dev->bid_time,
+                  (long long)st.st_mtime, (long long)diff));
 #else
-       DBG(PROBE, ul_debug("need to revalidate %s (cache time %lu.%lu, stat time %lu.%lu,\t"
-                  "time since last check %lu)",
+       DBG(PROBE, ul_debug("need to revalidate %s (cache time %lld.%lld, stat time %lld.%lld,\t"
+                  "time since last check %lld)",
                   dev->bid_name,
-                  (unsigned long)dev->bid_time, (unsigned long)dev->bid_utime,
-                  (unsigned long)st.st_mtime, (unsigned long)st.st_mtim.tv_nsec / 1000,
-                  (unsigned long)diff));
+                  (long long)dev->bid_time, (long long)dev->bid_utime,
+                  (long long)st.st_mtime, (long long)st.st_mtim.tv_nsec / 1000,
+                  (long long)diff));
 #endif
 
        if (sysfs_devno_is_dm_private(st.st_rdev, NULL)) {