diff --git a/0197-fs-xfs-Add-bigtime-support-for-xfs-driver.patch b/0197-fs-xfs-Add-bigtime-support-for-xfs-driver.patch new file mode 100644 index 0000000..7758c0c --- /dev/null +++ b/0197-fs-xfs-Add-bigtime-support-for-xfs-driver.patch @@ -0,0 +1,167 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Carlos Maiolino +Date: Wed, 14 Apr 2021 11:07:20 +0200 +Subject: [PATCH] fs/xfs: Add bigtime support for xfs driver + +XFS filesystem now supports bigtime feature, to overcome y2038 problem. +This patch makes grub able to support xfs filesystems with this feature +enabled. + +xfs counter for bigtime enable timestamps starts on 0, which translates +to INT32_MIN (Dec 31 20:45:52 UTC 1901) in the legacy timestamps. The +conversion to unix timestamps is made before passing the value to +grub-core. + +For this to work properly, grub requires to access flags2 field in the +xfs ondisk inode, so, the grub_xfs_inode structure has been updated to +the full ondisk inode size. + +This patch is enough to make grub work properly with files with +timestamps up to INT32_MAX (y2038), any file with timestamps bigger than +this will overflow the counter, causing grub to show wrong timestamps +(not really much difference on current situation). + +Reviewed-by: Javier Martinez Canillas +Signed-off-by: Carlos Maiolino +--- + grub-core/fs/xfs.c | 69 ++++++++++++++++++++++++++++++++++++++++++------------ + 1 file changed, 54 insertions(+), 15 deletions(-) + +diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c +index 43023e03fb3..2ce76ec70f9 100644 +--- a/grub-core/fs/xfs.c ++++ b/grub-core/fs/xfs.c +@@ -75,10 +75,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); + XFS_SB_VERSION2_PROJID32BIT | \ + XFS_SB_VERSION2_FTYPE) + ++/* Inode flags2 flags */ ++#define XFS_DIFLAG2_BIGTIME_BIT 3 ++#define XFS_DIFLAG2_BIGTIME (1 << XFS_DIFLAG2_BIGTIME_BIT) ++ + /* incompat feature flags */ +-#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ +-#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ +-#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ ++#define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ ++#define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ ++#define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ ++#define XFS_SB_FEAT_INCOMPAT_BIGTIME (1 << 3) /* large timestamps */ + + /* + * Directory entries with ftype are explicitly handled by GRUB code. +@@ -92,7 +97,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); + #define XFS_SB_FEAT_INCOMPAT_SUPPORTED \ + (XFS_SB_FEAT_INCOMPAT_FTYPE | \ + XFS_SB_FEAT_INCOMPAT_SPINODES | \ +- XFS_SB_FEAT_INCOMPAT_META_UUID) ++ XFS_SB_FEAT_INCOMPAT_META_UUID | \ ++ XFS_SB_FEAT_INCOMPAT_BIGTIME) + + struct grub_xfs_sblock + { +@@ -177,7 +183,7 @@ struct grub_xfs_btree_root + grub_uint64_t keys[1]; + } GRUB_PACKED; + +-struct grub_xfs_time ++struct grub_xfs_time_legacy + { + grub_uint32_t sec; + grub_uint32_t nanosec; +@@ -190,20 +196,23 @@ struct grub_xfs_inode + grub_uint8_t version; + grub_uint8_t format; + grub_uint8_t unused2[26]; +- struct grub_xfs_time atime; +- struct grub_xfs_time mtime; +- struct grub_xfs_time ctime; ++ grub_uint64_t atime; ++ grub_uint64_t mtime; ++ grub_uint64_t ctime; + grub_uint64_t size; + grub_uint64_t nblocks; + grub_uint32_t extsize; + grub_uint32_t nextents; + grub_uint16_t unused3; + grub_uint8_t fork_offset; +- grub_uint8_t unused4[17]; ++ grub_uint8_t unused4[37]; ++ grub_uint64_t flags2; ++ grub_uint8_t unused5[48]; + } GRUB_PACKED; + +-#define XFS_V2_INODE_SIZE sizeof(struct grub_xfs_inode) +-#define XFS_V3_INODE_SIZE (XFS_V2_INODE_SIZE + 76) ++#define XFS_V3_INODE_SIZE sizeof(struct grub_xfs_inode) ++/* Size of struct grub_xfs_inode until fork_offset (included)*/ ++#define XFS_V2_INODE_SIZE (XFS_V3_INODE_SIZE - 92) + + struct grub_xfs_dirblock_tail + { +@@ -233,8 +242,6 @@ struct grub_xfs_data + + static grub_dl_t my_mod; + +- +- + static int grub_xfs_sb_hascrc(struct grub_xfs_data *data) + { + return (data->sblock.version & grub_cpu_to_be16_compile_time(XFS_SB_VERSION_NUMBITS)) == +@@ -950,7 +957,6 @@ grub_xfs_mount (grub_disk_t disk) + return 0; + } + +- + /* Context for grub_xfs_dir. */ + struct grub_xfs_dir_ctx + { +@@ -958,6 +964,39 @@ struct grub_xfs_dir_ctx + void *hook_data; + }; + ++/* Bigtime inodes helpers */ ++ ++#define NSEC_PER_SEC 1000000000L ++#define XFS_BIGTIME_EPOCH_OFFSET (-(grub_int64_t)GRUB_INT32_MIN) ++ ++static int grub_xfs_inode_has_bigtime(const struct grub_xfs_inode *inode) ++{ ++ return inode->version >= 3 && ++ (inode->flags2 & grub_cpu_to_be64_compile_time(XFS_DIFLAG2_BIGTIME)); ++} ++ ++static grub_int64_t ++grub_xfs_bigtime_to_unix(grub_uint64_t time) ++{ ++ grub_uint64_t rem; ++ grub_int64_t nsec = NSEC_PER_SEC; ++ grub_int64_t seconds = grub_divmod64((grub_int64_t)time, nsec, &rem); ++ ++ return seconds - XFS_BIGTIME_EPOCH_OFFSET; ++} ++ ++static grub_int64_t ++grub_xfs_get_inode_time(struct grub_xfs_inode *inode) ++{ ++ struct grub_xfs_time_legacy *lts; ++ ++ if (grub_xfs_inode_has_bigtime(inode)) ++ return grub_xfs_bigtime_to_unix(grub_be_to_cpu64(inode->mtime)); ++ ++ lts = (struct grub_xfs_time_legacy *)&inode->mtime; ++ return grub_be_to_cpu32(lts->sec); ++} ++ + /* Helper for grub_xfs_dir. */ + static int + grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, +@@ -970,7 +1009,7 @@ grub_xfs_dir_iter (const char *filename, enum grub_fshelp_filetype filetype, + if (node->inode_read) + { + info.mtimeset = 1; +- info.mtime = grub_be_to_cpu32 (node->inode.mtime.sec); ++ info.mtime = grub_xfs_get_inode_time(&node->inode); + } + info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR); + grub_free (node); diff --git a/0198-fs-Use-64bit-type-for-filesystem-timestamp.patch b/0198-fs-Use-64bit-type-for-filesystem-timestamp.patch new file mode 100644 index 0000000..5938deb --- /dev/null +++ b/0198-fs-Use-64bit-type-for-filesystem-timestamp.patch @@ -0,0 +1,327 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Carlos Maiolino +Date: Wed, 14 Apr 2021 11:07:21 +0200 +Subject: [PATCH] fs: Use 64bit type for filesystem timestamp + +Some filesystems nowadays uses 64bit types for timestamps, so, update +grub_dirhook_info struct to use an int64 type to store mtime. This also +updates grub_unixtime2datetime() to receive a 64-bit timestamp +argument and do 64bit-safe divisions. + +All the remaining conversion from 32 to 64 should be safe, as 32 to 64 +attributions will be implicitly casted. The most crictical part in the +32 to 64bits conversion is on grub_unixtime2datetime() where it needs +to deal with the 64bit type, specially with division in x86_architectures, +so, for that, the grub_divmod64() helper has been used. + +These changes enables grub to support dates beyond y2038. + +Reviewed-by: Javier Martinez Canillas +Signed-off-by: Carlos Maiolino +--- + grub-core/fs/affs.c | 2 +- + grub-core/fs/ext2.c | 2 +- + grub-core/fs/fat.c | 4 ++-- + grub-core/fs/hfs.c | 2 +- + grub-core/fs/hfsplus.c | 2 +- + grub-core/fs/iso9660.c | 6 +++--- + grub-core/fs/nilfs2.c | 2 +- + grub-core/fs/squash4.c | 2 +- + grub-core/fs/ufs.c | 2 +- + grub-core/fs/zfs/zfs.c | 2 +- + grub-core/lib/datetime.c | 15 ++++++++++++--- + grub-core/net/bootp.c | 2 +- + grub-core/normal/misc.c | 2 +- + grub-core/tests/sleep_test.c | 4 ++-- + include/grub/datetime.h | 4 ++-- + include/grub/fs.h | 4 ++-- + 16 files changed, 33 insertions(+), 24 deletions(-) + +diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c +index 230e26af0f8..cafcd0fba91 100644 +--- a/grub-core/fs/affs.c ++++ b/grub-core/fs/affs.c +@@ -641,7 +641,7 @@ grub_affs_label (grub_device_t device, char **label) + } + + static grub_err_t +-grub_affs_mtime (grub_device_t device, grub_int32_t *t) ++grub_affs_mtime (grub_device_t device, grub_int64_t *t) + { + struct grub_affs_data *data; + grub_disk_t disk = device->disk; +diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c +index 848bf939dba..e7dd78e6635 100644 +--- a/grub-core/fs/ext2.c ++++ b/grub-core/fs/ext2.c +@@ -1055,7 +1055,7 @@ grub_ext2_uuid (grub_device_t device, char **uuid) + + /* Get mtime. */ + static grub_err_t +-grub_ext2_mtime (grub_device_t device, grub_int32_t *tm) ++grub_ext2_mtime (grub_device_t device, grub_int64_t *tm) + { + struct grub_ext2_data *data; + grub_disk_t disk = device->disk; +diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c +index 7f775a17038..dd82e4ee35d 100644 +--- a/grub-core/fs/fat.c ++++ b/grub-core/fs/fat.c +@@ -737,7 +737,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, + * https://docs.microsoft.com/en-us/windows/win32/fileio/exfat-specification + */ + static int +-grub_exfat_timestamp (grub_uint32_t field, grub_uint8_t msec, grub_int32_t *nix) { ++grub_exfat_timestamp (grub_uint32_t field, grub_uint8_t msec, grub_int64_t *nix) { + struct grub_datetime datetime = { + .year = (field >> 25) + 1980, + .month = (field & 0x01E00000) >> 21, +@@ -891,7 +891,7 @@ grub_fat_iterate_dir_next (grub_fshelp_node_t node, + * https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-107.pdf + */ + static int +-grub_fat_timestamp (grub_uint16_t time, grub_uint16_t date, grub_int32_t *nix) { ++grub_fat_timestamp (grub_uint16_t time, grub_uint16_t date, grub_int64_t *nix) { + struct grub_datetime datetime = { + .year = (date >> 9) + 1980, + .month = (date & 0x01E0) >> 5, +diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c +index 9a5b7bbe906..f419965d154 100644 +--- a/grub-core/fs/hfs.c ++++ b/grub-core/fs/hfs.c +@@ -1374,7 +1374,7 @@ grub_hfs_label (grub_device_t device, char **label) + } + + static grub_err_t +-grub_hfs_mtime (grub_device_t device, grub_int32_t *tm) ++grub_hfs_mtime (grub_device_t device, grub_int64_t *tm) + { + struct grub_hfs_data *data; + +diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c +index 2a69055c7ec..19c7b336798 100644 +--- a/grub-core/fs/hfsplus.c ++++ b/grub-core/fs/hfsplus.c +@@ -1083,7 +1083,7 @@ grub_hfsplus_label (grub_device_t device, char **label) + + /* Get mtime. */ + static grub_err_t +-grub_hfsplus_mtime (grub_device_t device, grub_int32_t *tm) ++grub_hfsplus_mtime (grub_device_t device, grub_int64_t *tm) + { + struct grub_hfsplus_data *data; + grub_disk_t disk = device->disk; +diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c +index 5ec4433b8f8..ac011950a64 100644 +--- a/grub-core/fs/iso9660.c ++++ b/grub-core/fs/iso9660.c +@@ -178,7 +178,7 @@ static grub_dl_t my_mod; + + + static grub_err_t +-iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) ++iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int64_t *nix) + { + struct grub_datetime datetime; + +@@ -206,7 +206,7 @@ iso9660_to_unixtime (const struct grub_iso9660_date *i, grub_int32_t *nix) + } + + static int +-iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int32_t *nix) ++iso9660_to_unixtime2 (const struct grub_iso9660_date2 *i, grub_int64_t *nix) + { + struct grub_datetime datetime; + +@@ -1107,7 +1107,7 @@ grub_iso9660_uuid (grub_device_t device, char **uuid) + + /* Get writing time of filesystem. */ + static grub_err_t +-grub_iso9660_mtime (grub_device_t device, grub_int32_t *timebuf) ++grub_iso9660_mtime (grub_device_t device, grub_int64_t *timebuf) + { + struct grub_iso9660_data *data; + grub_disk_t disk = device->disk; +diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c +index 9b76982b3b0..3c248a910b4 100644 +--- a/grub-core/fs/nilfs2.c ++++ b/grub-core/fs/nilfs2.c +@@ -1186,7 +1186,7 @@ grub_nilfs2_uuid (grub_device_t device, char **uuid) + + /* Get mtime. */ + static grub_err_t +-grub_nilfs2_mtime (grub_device_t device, grub_int32_t * tm) ++grub_nilfs2_mtime (grub_device_t device, grub_int64_t * tm) + { + struct grub_nilfs2_data *data; + grub_disk_t disk = device->disk; +diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c +index a5f35c10e2f..6dd731e231e 100644 +--- a/grub-core/fs/squash4.c ++++ b/grub-core/fs/squash4.c +@@ -1003,7 +1003,7 @@ grub_squash_close (grub_file_t file) + } + + static grub_err_t +-grub_squash_mtime (grub_device_t dev, grub_int32_t *tm) ++grub_squash_mtime (grub_device_t dev, grub_int64_t *tm) + { + struct grub_squash_data *data = 0; + +diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c +index fca46baa19d..34a698b71b8 100644 +--- a/grub-core/fs/ufs.c ++++ b/grub-core/fs/ufs.c +@@ -837,7 +837,7 @@ grub_ufs_uuid (grub_device_t device, char **uuid) + + /* Get mtime. */ + static grub_err_t +-grub_ufs_mtime (grub_device_t device, grub_int32_t *tm) ++grub_ufs_mtime (grub_device_t device, grub_int64_t *tm) + { + struct grub_ufs_data *data = 0; + +diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c +index f9e755197c5..cf4d2ab189a 100644 +--- a/grub-core/fs/zfs/zfs.c ++++ b/grub-core/fs/zfs/zfs.c +@@ -3771,7 +3771,7 @@ zfs_uuid (grub_device_t device, char **uuid) + } + + static grub_err_t +-zfs_mtime (grub_device_t device, grub_int32_t *mt) ++zfs_mtime (grub_device_t device, grub_int64_t *mt) + { + struct grub_zfs_data *data; + grub_zfs_endian_t ub_endian = GRUB_ZFS_UNKNOWN_ENDIAN; +diff --git a/grub-core/lib/datetime.c b/grub-core/lib/datetime.c +index 95b8c9ff5e3..3e84fa1dbc4 100644 +--- a/grub-core/lib/datetime.c ++++ b/grub-core/lib/datetime.c +@@ -19,6 +19,7 @@ + + #include + #include ++#include + + static const char *const grub_weekday_names[] = + { +@@ -60,9 +61,10 @@ grub_get_weekday_name (struct grub_datetime *datetime) + + + void +-grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime) ++grub_unixtime2datetime (grub_int64_t nix, struct grub_datetime *datetime) + { + int i; ++ grub_uint64_t rem; + grub_uint8_t months[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + /* In the period of validity of unixtime all years divisible by 4 + are bissextile*/ +@@ -75,9 +77,16 @@ grub_unixtime2datetime (grub_int32_t nix, struct grub_datetime *datetime) + unsigned secs_in_day; + /* Transform C divisions and modulos to mathematical ones */ + if (nix < 0) +- days_epoch = -(((unsigned) (SECPERDAY-nix-1)) / SECPERDAY); ++ /* ++ * the division here shouldn't be larger than INT_MAX, ++ * so, it's safe to store the result back in an int ++ */ ++ days_epoch = -(grub_divmod64(((grub_int64_t)(SECPERDAY) - nix - 1), ++ SECPERDAY, ++ &rem)); + else +- days_epoch = ((unsigned) nix) / SECPERDAY; ++ days_epoch = grub_divmod64(nix, SECPERDAY, &rem); ++ + secs_in_day = nix - days_epoch * SECPERDAY; + days = days_epoch + 69 * DAYSPERYEAR + 17; + +diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c +index 8f2f55c0079..7baf3540c81 100644 +--- a/grub-core/net/bootp.c ++++ b/grub-core/net/bootp.c +@@ -610,7 +610,7 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) + grub_err_t err; + struct grub_net_bootp_packet *pack; + struct grub_datetime date; +- grub_int32_t t = 0; ++ grub_int64_t t = 0; + struct grub_net_buff *nb; + struct udphdr *udph; + grub_net_network_level_address_t target; +diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c +index 8bb6da31fb3..f7e9e3ac4a1 100644 +--- a/grub-core/normal/misc.c ++++ b/grub-core/normal/misc.c +@@ -136,7 +136,7 @@ grub_normal_print_device_info (const char *name) + } + if (fs->fs_mtime) + { +- grub_int32_t tm; ++ grub_int64_t tm; + struct grub_datetime datetime; + (fs->fs_mtime) (dev, &tm); + if (grub_errno == GRUB_ERR_NONE) +diff --git a/grub-core/tests/sleep_test.c b/grub-core/tests/sleep_test.c +index 3d11c717cb7..63f6713165f 100644 +--- a/grub-core/tests/sleep_test.c ++++ b/grub-core/tests/sleep_test.c +@@ -32,7 +32,7 @@ static void + sleep_test (void) + { + struct grub_datetime st, en; +- grub_int32_t stu = 0, enu = 0; ++ grub_int64_t stu = 0, enu = 0; + int is_delayok; + grub_test_assert (!grub_get_datetime (&st), "Couldn't retrieve start time"); + grub_millisleep (10000); +@@ -45,7 +45,7 @@ sleep_test (void) + if (enu - stu >= 15 && enu - stu <= 17) + is_delayok = 1; + #endif +- grub_test_assert (is_delayok, "Interval out of range: %d", enu-stu); ++ grub_test_assert (is_delayok, "Interval out of range: %lld", enu-stu); + + } + +diff --git a/include/grub/datetime.h b/include/grub/datetime.h +index fef281404d7..23ae0791ced 100644 +--- a/include/grub/datetime.h ++++ b/include/grub/datetime.h +@@ -48,11 +48,11 @@ grub_err_t grub_set_datetime (struct grub_datetime *datetime); + int grub_get_weekday (struct grub_datetime *datetime); + const char *grub_get_weekday_name (struct grub_datetime *datetime); + +-void grub_unixtime2datetime (grub_int32_t nix, ++void grub_unixtime2datetime (grub_int64_t nix, + struct grub_datetime *datetime); + + static inline int +-grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) ++grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int64_t *nix) + { + grub_int32_t ret; + int y4, ay; +diff --git a/include/grub/fs.h b/include/grub/fs.h +index 302e48d4b50..026bc3bb861 100644 +--- a/include/grub/fs.h ++++ b/include/grub/fs.h +@@ -39,7 +39,7 @@ struct grub_dirhook_info + unsigned mtimeset:1; + unsigned case_insensitive:1; + unsigned inodeset:1; +- grub_int32_t mtime; ++ grub_int64_t mtime; + grub_uint64_t inode; + }; + +@@ -81,7 +81,7 @@ struct grub_fs + grub_err_t (*fs_uuid) (grub_device_t device, char **uuid); + + /* Get writing time of filesystem. */ +- grub_err_t (*fs_mtime) (grub_device_t device, grub_int32_t *timebuf); ++ grub_err_t (*fs_mtime) (grub_device_t device, grub_int64_t *timebuf); + + #ifdef GRUB_UTIL + /* Determine sectors available for embedding. */ diff --git a/grub.patches b/grub.patches index 4f8f473..59f42c3 100644 --- a/grub.patches +++ b/grub.patches @@ -194,3 +194,5 @@ Patch0193: 0193-appended-signatures-documentation.patch Patch0194: 0194-ieee1275-enter-lockdown-based-on-ibm-secure-boot.patch Patch0195: 0195-Revert-templates-Properly-disable-the-os-prober-by-d.patch Patch0196: 0196-Revert-templates-Disable-the-os-prober-by-default.patch +Patch0197: 0197-fs-xfs-Add-bigtime-support-for-xfs-driver.patch +Patch0198: 0198-fs-Use-64bit-type-for-filesystem-timestamp.patch diff --git a/grub2.spec b/grub2.spec index d499397..450af50 100644 --- a/grub2.spec +++ b/grub2.spec @@ -14,7 +14,7 @@ Name: grub2 Epoch: 1 Version: 2.06~rc1 -Release: 4%{?dist} +Release: 5%{?dist} Summary: Bootloader with support for Linux, Multiboot and more License: GPLv3+ URL: http://www.gnu.org/software/grub/ @@ -555,6 +555,9 @@ mv ${EFI_HOME}/grub.cfg.stb ${EFI_HOME}/grub.cfg %endif %changelog +* Wed Apr 14 2021 Javier Martinez Canillas - 2.06~rc1-5 +- Add XFS bigtime support (cmaiolino) + * Mon Apr 12 2021 Javier Martinez Canillas - 2.06~rc1-4 - Add again 20_linux_xen script fix that got dropped by mistake Resolves: rhbz#1858364