lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1452144972-15802-3-git-send-email-deepa.kernel@gmail.com>
Date:	Wed,  6 Jan 2016 21:35:59 -0800
From:	Deepa Dinamani <deepa.kernel@...il.com>
To:	linux-kernel@...r.kernel.org, linux-fsdevel@...r.kernel.org,
	y2038@...ts.linaro.org
Subject: [RFC 02/15] vfs: Change all structures to support 64 bit time

The current representation of inode times in struct inode, struct iattr,
and struct kstat use struct timespec. timespec is not y2038 safe.

Use scalar data types (seconds and nanoseconds stored separately) to
represent timestamps in struct inode in order to maintain same size for
times across 32 bit and 64 bit architectures.
In addition, lay them out such that they are packed on a naturally
aligned boundary on 64 bit arch as 4 bytes are used to store nsec.
This makes each tuple(sec, nscec) use 12 bytes instead of 16 bytes.
This will help save RAM space as inode structure is cached in memory.
The other structures are transient and do not benefit from these
changes.

Add accessors for inode timestamps.
These provide a way to access the time field members.
Accessors abstract the timestamp representation so that any logic
to convert between the struct inode timestamps and other interfaces
can be placed here.
The plan is to globally change all references to these types through
these accessors only. So when the actual internal representation
changes, it will be transparent to the outside world.
This can be extended to add code to validate the inode times that
are being set.
Macros are chosen as accessors rather than functions because we can
condense 3 {a,c,m} time functions into a single macro. After we agree
on an approach, the implementation could be changed to use static
inline functions if it suits more.

Add inode_timespec aliases to help convert kstat and iattr times to use
64 bit times. These hide the internal data type.
Use uapi exposed data types here to keep minimal timstamp data type
conversions in API's interfacing with vfs.

After the CONFIG_FS_USES_64BIT_TIME is enabled, all inode_timespec
aliases will be removed and timespec64 data types and API's will
be used directly.

Signed-off-by: Deepa Dinamani <deepa.kernel@...il.com>
---
 include/linux/fs.h     | 55 +++++++++++++++++++++++++++++++++++++++++++-------
 include/linux/stat.h   |  6 +++---
 include/linux/time64.h | 21 +++++++++++++++++++
 3 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/include/linux/fs.h b/include/linux/fs.h
index 12ba937..b9f3cee 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -245,13 +245,13 @@ typedef void (dax_iodone_t)(struct buffer_head *bh_map, int uptodate);
  */
 struct iattr {
 	unsigned int	ia_valid;
-	umode_t		ia_mode;
-	kuid_t		ia_uid;
-	kgid_t		ia_gid;
-	loff_t		ia_size;
-	struct timespec	ia_atime;
-	struct timespec	ia_mtime;
-	struct timespec	ia_ctime;
+	umode_t			ia_mode;
+	kuid_t			ia_uid;
+	kgid_t			ia_gid;
+	loff_t			ia_size;
+	struct inode_timespec	ia_atime;
+	struct inode_timespec	ia_mtime;
+	struct inode_timespec	ia_ctime;
 
 	/*
 	 * Not an attribute, but an auxiliary info for filesystems wanting to
@@ -616,9 +616,18 @@ struct inode {
 	};
 	dev_t			i_rdev;
 	loff_t			i_size;
+#ifdef CONFIG_FS_USES_64BIT_TIME
+	time64_t		i_atime_sec;
+	time64_t		i_mtime_sec;
+	time64_t		i_ctime_sec;
+	s32			i_atime_nsec;
+	s32			i_mtime_nsec;
+	s32			i_ctime_nsec;
+#else
 	struct timespec		i_atime;
 	struct timespec		i_mtime;
 	struct timespec		i_ctime;
+#endif
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	unsigned short          i_bytes;
 	unsigned int		i_blkbits;
@@ -679,6 +688,38 @@ struct inode {
 	void			*i_private; /* fs or device private pointer */
 };
 
+#ifdef CONFIG_FS_USES_64BIT_TIME
+
+#define VFS_INODE_SET_XTIME(xtime, inode, ts64)			\
+	do {								\
+		struct inode_timespec __ts = (ts64);			\
+		(inode)->xtime##_sec = __ts.tv_sec;			\
+		(inode)->xtime##_nsec = __ts.tv_nsec;			\
+	} while (0)
+
+#define VFS_INODE_GET_XTIME(xtime, inode)			\
+	(struct timespec64){.tv_sec = (inode)->xtime##_sec,	\
+			    .tv_nsec = (inode)->xtime##_nsec}
+
+#else
+
+#define VFS_INODE_SET_XTIME(xtime, inode, ts)			\
+	((inode)->xtime = (ts))
+
+#define VFS_INODE_GET_XTIME(xtime, inode)       \
+	((inode)->xtime)
+
+#endif
+
+#define VFS_INODE_SWAP_XTIME(xtime, inode1, inode2)		\
+	do {							\
+		struct inode_timespec __ts =			\
+			VFS_INODE_GET_XTIME(xtime, inode1);	\
+		VFS_INODE_SET_XTIME(xtime, inode1,		\
+			VFS_INODE_GET_XTIME(xtime, inode2));	\
+		VFS_INODE_SET_XTIME(xtime, inode2, __ts);	\
+	} while (0)
+
 static inline int inode_unhashed(struct inode *inode)
 {
 	return hlist_unhashed(&inode->i_hash);
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 075cb0c..559983f 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -27,9 +27,9 @@ struct kstat {
 	kgid_t		gid;
 	dev_t		rdev;
 	loff_t		size;
-	struct timespec  atime;
-	struct timespec	mtime;
-	struct timespec	ctime;
+	struct inode_timespec	atime;
+	struct inode_timespec	mtime;
+	struct inode_timespec	ctime;
 	unsigned long	blksize;
 	unsigned long long	blocks;
 };
diff --git a/include/linux/time64.h b/include/linux/time64.h
index 367d5af..be98201 100644
--- a/include/linux/time64.h
+++ b/include/linux/time64.h
@@ -26,6 +26,27 @@ struct itimerspec64 {
 
 #endif
 
+#ifdef CONFIG_FS_USES_64BIT_TIME
+
+/* Place holder defines until CONFIG_FS_USES_64BIT_TIME
+ * is enabled.
+ * timespec64 data type and functions will be used at that
+ * time directly and these defines will be deleted.
+ */
+#define inode_timespec timespec64
+
+#define inode_timespec_compare	timespec64_compare
+#define inode_timespec_equal	timespec64_equal
+
+#else
+
+#define inode_timespec timespec
+
+#define inode_timespec_compare	timespec_compare
+#define inode_timespec_equal	timespec_equal
+
+#endif
+
 /* Parameters used to convert the timespec values: */
 #define MSEC_PER_SEC	1000L
 #define USEC_PER_MSEC	1000L
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ