[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <174553065069.1160461.14751120886781323020.stgit@frogsfrogsfrogs>
Date: Thu, 24 Apr 2025 14:42:52 -0700
From: "Darrick J. Wong" <djwong@...nel.org>
To: tytso@....edu
Cc: linux-ext4@...r.kernel.org
Subject: [PATCH 08/16] fuse2fs: clamp timestamps that are being written to
disk
From: Darrick J. Wong <djwong@...nel.org>
Clamp the timestamps that we write to disk to the minimum and maximum
values permitted given the ondisk format. This fixes y2038 support, as
tested by generic/402.
Signed-off-by: "Darrick J. Wong" <djwong@...nel.org>
---
lib/ext2fs/ext2_fs.h | 4 ++++
misc/fuse2fs.c | 39 ++++++++++++++++++++++++++++++++-------
2 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index 3a5eb7387d0c9d..fcd42055665788 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -801,6 +801,10 @@ struct ext2_super_block {
#define EXT2_GOOD_OLD_INODE_SIZE 128
+#define EXT4_EXTRA_TIMESTAMP_MAX (((int64_t)1 << 34) - 1 + INT32_MIN)
+#define EXT4_NON_EXTRA_TIMESTAMP_MAX INT32_MAX
+#define EXT4_TIMESTAMP_MIN INT32_MIN
+
/*
* Journal inode backup types
*/
diff --git a/misc/fuse2fs.c b/misc/fuse2fs.c
index bf4e592e7d2782..9cf8c59b8b88ee 100644
--- a/misc/fuse2fs.c
+++ b/misc/fuse2fs.c
@@ -227,21 +227,43 @@ static inline void ext4_decode_extra_time(struct timespec *time, __u32 extra)
time->tv_nsec = ((extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
}
+#define EXT4_CLAMP_TIMESTAMP(xtime, timespec, raw_inode) \
+do { \
+ if ((timespec)->tv_sec < EXT4_TIMESTAMP_MIN) \
+ (timespec)->tv_sec = EXT4_TIMESTAMP_MIN; \
+ if ((timespec)->tv_sec < EXT4_TIMESTAMP_MIN) \
+ (timespec)->tv_sec = EXT4_TIMESTAMP_MIN; \
+ \
+ if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) { \
+ if ((timespec)->tv_sec > EXT4_EXTRA_TIMESTAMP_MAX) \
+ (timespec)->tv_sec = EXT4_EXTRA_TIMESTAMP_MAX; \
+ } else { \
+ if ((timespec)->tv_sec > EXT4_NON_EXTRA_TIMESTAMP_MAX) \
+ (timespec)->tv_sec = EXT4_NON_EXTRA_TIMESTAMP_MAX; \
+ } \
+} while (0)
+
#define EXT4_INODE_SET_XTIME(xtime, timespec, raw_inode) \
do { \
- (raw_inode)->xtime = (timespec)->tv_sec; \
+ typeof(*(timespec)) _ts = *(timespec); \
+ \
+ EXT4_CLAMP_TIMESTAMP(xtime, &_ts, raw_inode); \
+ (raw_inode)->xtime = _ts.tv_sec; \
if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
(raw_inode)->xtime ## _extra = \
- ext4_encode_extra_time(timespec); \
+ ext4_encode_extra_time(&_ts); \
} while (0)
#define EXT4_EINODE_SET_XTIME(xtime, timespec, raw_inode) \
do { \
+ typeof(*(timespec)) _ts = *(timespec); \
+ \
+ EXT4_CLAMP_TIMESTAMP(xtime, &_ts, raw_inode); \
if (EXT4_FITS_IN_INODE(raw_inode, xtime)) \
- (raw_inode)->xtime = (timespec)->tv_sec; \
+ (raw_inode)->xtime = _ts.tv_sec; \
if (EXT4_FITS_IN_INODE(raw_inode, xtime ## _extra)) \
(raw_inode)->xtime ## _extra = \
- ext4_encode_extra_time(timespec); \
+ ext4_encode_extra_time(&_ts); \
} while (0)
#define EXT4_INODE_GET_XTIME(xtime, timespec, raw_inode) \
@@ -2884,7 +2906,10 @@ static int op_utimens(const char *path, const struct timespec ctv[2]
ret = translate_error(fs, 0, err);
goto out;
}
- dbg_printf(ff, "%s: ino=%d\n", __func__, ino);
+ dbg_printf(ff, "%s: ino=%d atime=%lld.%ld mtime=%lld.%ld\n", __func__,
+ ino,
+ (long long int)ctv[0].tv_sec, ctv[0].tv_nsec,
+ (long long int)ctv[1].tv_sec, ctv[1].tv_nsec);
ret = check_inum_access(fs, ino, W_OK);
if (ret)
@@ -2908,9 +2933,9 @@ static int op_utimens(const char *path, const struct timespec ctv[2]
#endif /* UTIME_NOW */
#ifdef UTIME_OMIT
if (tv[0].tv_nsec != UTIME_OMIT)
- EXT4_INODE_SET_XTIME(i_atime, tv, &inode);
+ EXT4_INODE_SET_XTIME(i_atime, &tv[0], &inode);
if (tv[1].tv_nsec != UTIME_OMIT)
- EXT4_INODE_SET_XTIME(i_mtime, tv + 1, &inode);
+ EXT4_INODE_SET_XTIME(i_mtime, &tv[1], &inode);
#endif /* UTIME_OMIT */
ret = update_ctime(fs, ino, &inode);
if (ret)
Powered by blists - more mailing lists