From: David Turner <novalis@novalis.org>
To: Andreas Dilger <adilger@dilger.ca>
Cc: "Theodore Ts'o" <tytso@mit.edu>, Mark Harris <mhlk@osj.us>,
Jan Kara <jack@suse.cz>,
Ext4 Developers List <linux-ext4@vger.kernel.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH v5 1/2] ext4: Fix handling of extended tv_sec (bug 23732)
Date: Thu, 14 Nov 2013 03:38:53 -0500 [thread overview]
Message-ID: <1384418333.8994.203.camel@chiang> (raw)
In-Reply-To: <276FA06E-1EE0-4FB4-94E1-B6D9F05F0B5B@dilger.ca>
Thanks for your patient and detailed comments.
--
In ext4, the bottom two bits of {a,c,m}time_extra are used to extend
the {a,c,m}time fields, deferring the year 2038 problem to the year
2446.
When decoding these extended fields, for times whose bottom 32 bits
would represent a negative number, sign extension causes the 64-bit
extended timestamp to be negative as well, which is not what's
intended. This patch corrects that issue, so that the only negative
{a,c,m}times are those between 1901 and 1970 (as per 32-bit signed
timestamps).
Some older kernels might have written pre-1970 dates with 1,1 in the
extra bits. This patch treats those incorrectly-encoded dates as
pre-1970, instead of post-2311, until kernel 4.20 is released.
Hopefully by then e2fsck will have fixed up the bad data.
Signed-off-by: David Turner <novalis@novalis.org>
Reported-by: Mark Harris <mh8928@yahoo.com>
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=23732
---
fs/ext4/ext4.h | 61 +++++++++++++++++++++++++++++++++++++---------------------
1 file changed, 39 insertions(+), 22 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 18aa56b..ac54dac 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -26,6 +26,7 @@
#include <linux/seqlock.h>
#include <linux/mutex.h>
#include <linux/timer.h>
+#include <linux/version.h>
#include <linux/wait.h>
#include <linux/blockgroup_lock.h>
#include <linux/percpu_counter.h>
@@ -713,38 +714,54 @@ struct move_extent {
sizeof((ext4_inode)->field)) \
<= (EXT4_GOOD_OLD_INODE_SIZE + \
(einode)->i_extra_isize)) \
+
/*
- * We use the bottom 34 bits of the signed 64-bit time value, with
- * the top two of these bits in the bottom of extra. This leads
- * to a slightly odd encoding, which works like this:
+ * We need is an encoding that preserves the times for extra epoch "00":
*
- * extra msb of
- * epoch 32-bit
- * bits time decoded 64-bit tv_sec valid time range
- * 0 0 0 0x000000000..0x07fffffff 1970-01-01..2038-01-19
- * 0 0 1 0x080000000..0x0ffffffff 2038-01-19..2106-02-07
- * 0 1 0 0x100000000..0x17fffffff 2106-02-07..2174-02-25
- * 0 1 1 0x180000000..0x1ffffffff 2174-02-25..2242-03-16
- * 1 0 0 0x200000000..0x27fffffff 2242-03-16..2310-04-04
- * 1 0 1 0x280000000..0x2ffffffff 2310-04-04..2378-04-22
- * 1 1 0 0x300000000..0x37fffffff 2378-04-22..2446-05-10
-
- * 1 1 1 -0x80000000..-0x00000001 1901-12-13..1969-12-31
+ * extra msb of adjust for signed
+ * epoch 32-bit 32-bit tv_sec to
+ * bits time decoded 64-bit tv_sec 64-bit tv_sec valid time range
+ * 0 0 1 -0x80000000..-0x00000001 0x000000000 1901-12-13..1969-12-31
+ * 0 0 0 0x000000000..0x07fffffff 0x000000000 1970-01-01..2038-01-19
+ * 0 1 1 0x080000000..0x0ffffffff 0x100000000 2038-01-19..2106-02-07
+ * 0 1 0 0x100000000..0x17fffffff 0x100000000 2106-02-07..2174-02-25
+ * 1 0 1 0x180000000..0x1ffffffff 0x200000000 2174-02-25..2242-03-16
+ * 1 0 0 0x200000000..0x27fffffff 0x200000000 2242-03-16..2310-04-04
+ * 1 1 1 0x280000000..0x2ffffffff 0x300000000 2310-04-04..2378-04-22
+ * 1 1 0 0x300000000..0x37fffffff 0x300000000 2378-04-22..2446-05-10
+ *
+ * Note that previous versions of the kernel on 64-bit systems would
+ * incorrectly use extra epoch bits 1,1 for dates between 1901 and
+ * 1970. e2fsck will correct this, assuming that it is run on the
+ * affected filesystem before 2242.
*/
static inline __le32 ext4_encode_extra_time(struct timespec *time)
{
- return cpu_to_le32((sizeof(time->tv_sec) > 4 ?
- (time->tv_sec >> 32) & EXT4_EPOCH_MASK : 0) |
- ((time->tv_nsec << EXT4_EPOCH_BITS) & EXT4_NSEC_MASK));
+ u32 extra = sizeof(time->tv_sec) > 4 ?
+ ((time->tv_sec - (s32)time->tv_sec) >> 32) & EXT4_EPOCH_MASK : 0;
+ return cpu_to_le32(extra | (time->tv_nsec << EXT4_EPOCH_BITS));
}
static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
{
- if (sizeof(time->tv_sec) > 4)
- time->tv_sec |= (__u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK)
- << 32;
- time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
+ if (unlikely(sizeof(time->tv_sec) > 4 &&
+ (extra & cpu_to_le32(EXT4_EPOCH_MASK)))) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4,20,0)
+ /* Handle legacy encoding of pre-1970 dates with epoch
+ * bits 1,1. We assume that by kernel version 4.20,
+ * everyone will have run fsck over the affected
+ * filesystems to correct the problem.
+ */
+ u64 extra_bits = le32_to_cpu(extra) & EXT4_EPOCH_MASK;
+ if (extra_bits == 3)
+ extra_bits = 0;
+ time->tv_sec += extra_bits << 32;
+#else
+ time->tv_sec += (u64)(le32_to_cpu(extra) & EXT4_EPOCH_MASK) << 32;
+#endif
+ }
+ time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
}
#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
--
1.8.1.2
next prev parent reply other threads:[~2013-11-14 8:39 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-07 7:16 [PATCH] ext4: Fix reading of extended tv_sec (bug 23732) David Turner
2013-11-07 16:03 ` Jan Kara
2013-11-07 22:54 ` [PATCH v2] " David Turner
2013-11-07 23:14 ` Jan Kara
2013-11-07 23:26 ` [PATCH v3] " David Turner
2013-11-08 5:17 ` Theodore Ts'o
2013-11-08 21:37 ` Andreas Dilger
2013-11-09 7:19 ` [PATCH] ext4: explain encoding of 34-bit a,c,mtime values David Turner
2013-11-09 7:19 ` David Turner
2013-11-09 23:51 ` Mark Harris
2013-11-09 23:51 ` Mark Harris
2013-11-10 7:56 ` David Turner
2013-11-12 0:30 ` Theodore Ts'o
2013-11-12 21:35 ` Andreas Dilger
2013-11-13 7:00 ` [PATCH v4 1/2] ext4: Fix handling of extended tv_sec (bug 23732) David Turner
2013-11-13 8:19 ` Darrick J. Wong
2013-11-13 7:00 ` [PATCH v4 2/2] e2fsck: Correct ext4 dates generated by old kernels David Turner
2013-11-13 7:56 ` Andreas Dilger
2013-11-14 8:38 ` David Turner [this message]
2013-11-14 8:44 ` [PATCH v5 " David Turner
2013-11-14 10:15 ` Mark Harris
2013-11-14 21:06 ` [PATCH v6] " David Turner
2013-11-29 21:54 ` David Turner
2013-11-29 22:11 ` Andreas Dilger
2013-12-07 20:02 ` [PATCH v7 1/2] " David Turner
2013-12-07 22:33 ` Andreas Dilger
2013-12-08 0:53 ` Theodore Ts'o
2013-12-08 2:58 ` David Turner
2013-12-08 3:21 ` Theodore Ts'o
2013-12-07 20:02 ` [PATCH v7 2/2] debugfs: Decode {a,c,cr,m}time_extra fields in stat David Turner
2013-11-12 23:03 ` [PATCH] ext4: explain encoding of 34-bit a,c,mtime values Darrick J. Wong
2013-11-13 2:36 ` David Turner
2014-01-22 6:22 ` Darrick J. Wong
2014-02-11 5:12 ` David Turner
2014-02-11 7:07 ` Andreas Dilger
2014-02-14 3:47 ` [PATCH v8 1/2] ext4: Fix handling of extended tv_sec (bug 23732) David Turner
2014-02-14 3:47 ` [PATCH v8 2/2] e2fsck: Correct ext4 dates generated by old kernels David Turner
2014-02-14 5:40 ` Andreas Dilger
2014-02-14 22:11 ` Darrick J. Wong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1384418333.8994.203.camel@chiang \
--to=novalis@novalis.org \
--cc=adilger@dilger.ca \
--cc=jack@suse.cz \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mhlk@osj.us \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.