From 3fbeb9eeb86a04283e38ee9272a7726e7fbb8de9 Mon Sep 17 00:00:00 2001 From: Samanta Navarro Date: Sun, 8 Nov 2020 11:46:56 +0000 Subject: [PATCH] libblkid: fix time_t handling 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 --- libblkid/src/dev.c | 4 ++-- libblkid/src/devname.c | 2 +- libblkid/src/save.c | 6 +++--- libblkid/src/verify.c | 22 +++++++++++----------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/libblkid/src/dev.c b/libblkid/src/dev.c index 056df2b867..c38ec3d321 100644 --- a/libblkid/src/dev.c +++ b/libblkid/src/dev.c @@ -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); diff --git a/libblkid/src/devname.c b/libblkid/src/devname.c index 5582551316..c541d30ba6 100644 --- a/libblkid/src/devname.c +++ b/libblkid/src/devname.c @@ -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); diff --git a/libblkid/src/save.c b/libblkid/src/save.c index bceaa11398..9a342c69cf 100644 --- a/libblkid/src/save.c +++ b/libblkid/src/save.c @@ -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, "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); diff --git a/libblkid/src/verify.c b/libblkid/src/verify.c index db38623732..3b9754f57d 100644 --- a/libblkid/src/verify.c +++ b/libblkid/src/verify.c @@ -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)) { -- 2.47.3