diff mbox

[2/3] hfsplus: stop using timespec based interfaces

Message ID 20180619160223.4108556-2-arnd@arndb.de (mailing list archive)
State New, archived
Headers show

Commit Message

Arnd Bergmann June 19, 2018, 4:02 p.m. UTC
The native HFS+ timestamps overflow in year 2040, two years after the Unix
y2038 overflow. However, the way that the conversion between on-disk
timestamps and in-kernel timestamps was implemented, 64-bit machines
actually ended up converting negative UTC timestamps (1902 through 1969)
into times between 2038 and 2106.

Rather than making all machines faithfully represent timestamps in the
ancient past but break after 2040, this changes the file system to
always use the unsigned UTC interpretation, reading back times between
1970 and 2106.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
 fs/hfsplus/hfsplus_fs.h |  7 ++++---
 fs/hfsplus/inode.c      | 12 ++++++------
 2 files changed, 10 insertions(+), 9 deletions(-)

Comments

Ernesto A. Fernández June 24, 2018, 3:11 a.m. UTC | #1
On Tue, Jun 19, 2018 at 06:02:08PM +0200, Arnd Bergmann wrote:
> The native HFS+ timestamps overflow in year 2040, two years after the Unix
> y2038 overflow. However, the way that the conversion between on-disk
> timestamps and in-kernel timestamps was implemented, 64-bit machines
> actually ended up converting negative UTC timestamps (1902 through 1969)
> into times between 2038 and 2106.
> 
> Rather than making all machines faithfully represent timestamps in the
> ancient past but break after 2040, this changes the file system to
> always use the unsigned UTC interpretation, reading back times between
> 1970 and 2106.
> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
>  fs/hfsplus/hfsplus_fs.h |  7 ++++---
>  fs/hfsplus/inode.c      | 12 ++++++------
>  2 files changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
> index d9255abafb81..646c207be38d 100644
> --- a/fs/hfsplus/hfsplus_fs.h
> +++ b/fs/hfsplus/hfsplus_fs.h
> @@ -530,13 +530,14 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf,
>  		       void **data, int op, int op_flags);
>  int hfsplus_read_wrapper(struct super_block *sb);
>  
> -/* time macros */
> +/* time macros: convert between 1904-2040 and 1970-2106 range,
> + * pre-1970 timestamps are interpreted as post-2038 times after wrap-around
						  ^^^^
If we are talking about on-disk timestamps, this should be 2040.


Everything else looks fine, if it helps you can use:

Reviewed-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>

> */
>  #define __hfsp_mt2ut(t)		(be32_to_cpu(t) - 2082844800U)
>  #define __hfsp_ut2mt(t)		(cpu_to_be32(t + 2082844800U))
>  
>  /* compatibility */
> -#define hfsp_mt2ut(t)		(struct timespec){ .tv_sec = __hfsp_mt2ut(t) }
> +#define hfsp_mt2ut(t)		(struct timespec64){ .tv_sec = __hfsp_mt2ut(t) }
>  #define hfsp_ut2mt(t)		__hfsp_ut2mt((t).tv_sec)
> -#define hfsp_now2mt()		__hfsp_ut2mt(get_seconds())
> +#define hfsp_now2mt()		__hfsp_ut2mt(ktime_get_real_seconds())
>  
>  #endif
> diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
> index c824f702feec..c0c8d433864f 100644
> --- a/fs/hfsplus/inode.c
> +++ b/fs/hfsplus/inode.c
> @@ -493,9 +493,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
>  		hfsplus_get_perms(inode, &folder->permissions, 1);
>  		set_nlink(inode, 1);
>  		inode->i_size = 2 + be32_to_cpu(folder->valence);
> -		inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(folder->access_date));
> -		inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(folder->content_mod_date));
> -		inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(folder->attribute_mod_date));
> +		inode->i_atime = hfsp_mt2ut(folder->access_date);
> +		inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
> +		inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
>  		HFSPLUS_I(inode)->create_date = folder->create_date;
>  		HFSPLUS_I(inode)->fs_blocks = 0;
>  		if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
> @@ -531,9 +531,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
>  			init_special_inode(inode, inode->i_mode,
>  					   be32_to_cpu(file->permissions.dev));
>  		}
> -		inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(file->access_date));
> -		inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(file->content_mod_date));
> -		inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(file->attribute_mod_date));
> +		inode->i_atime = hfsp_mt2ut(file->access_date);
> +		inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
> +		inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
>  		HFSPLUS_I(inode)->create_date = file->create_date;
>  	} else {
>  		pr_err("bad catalog entry used to create inode\n");
> -- 
> 2.9.0
>
diff mbox

Patch

diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h
index d9255abafb81..646c207be38d 100644
--- a/fs/hfsplus/hfsplus_fs.h
+++ b/fs/hfsplus/hfsplus_fs.h
@@ -530,13 +530,14 @@  int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf,
 		       void **data, int op, int op_flags);
 int hfsplus_read_wrapper(struct super_block *sb);
 
-/* time macros */
+/* time macros: convert between 1904-2040 and 1970-2106 range,
+ * pre-1970 timestamps are interpreted as post-2038 times after wrap-around */
 #define __hfsp_mt2ut(t)		(be32_to_cpu(t) - 2082844800U)
 #define __hfsp_ut2mt(t)		(cpu_to_be32(t + 2082844800U))
 
 /* compatibility */
-#define hfsp_mt2ut(t)		(struct timespec){ .tv_sec = __hfsp_mt2ut(t) }
+#define hfsp_mt2ut(t)		(struct timespec64){ .tv_sec = __hfsp_mt2ut(t) }
 #define hfsp_ut2mt(t)		__hfsp_ut2mt((t).tv_sec)
-#define hfsp_now2mt()		__hfsp_ut2mt(get_seconds())
+#define hfsp_now2mt()		__hfsp_ut2mt(ktime_get_real_seconds())
 
 #endif
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index c824f702feec..c0c8d433864f 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -493,9 +493,9 @@  int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
 		hfsplus_get_perms(inode, &folder->permissions, 1);
 		set_nlink(inode, 1);
 		inode->i_size = 2 + be32_to_cpu(folder->valence);
-		inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(folder->access_date));
-		inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(folder->content_mod_date));
-		inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(folder->attribute_mod_date));
+		inode->i_atime = hfsp_mt2ut(folder->access_date);
+		inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
+		inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
 		HFSPLUS_I(inode)->create_date = folder->create_date;
 		HFSPLUS_I(inode)->fs_blocks = 0;
 		if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
@@ -531,9 +531,9 @@  int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
 			init_special_inode(inode, inode->i_mode,
 					   be32_to_cpu(file->permissions.dev));
 		}
-		inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(file->access_date));
-		inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(file->content_mod_date));
-		inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(file->attribute_mod_date));
+		inode->i_atime = hfsp_mt2ut(file->access_date);
+		inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
+		inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
 		HFSPLUS_I(inode)->create_date = file->create_date;
 	} else {
 		pr_err("bad catalog entry used to create inode\n");