git: b0ce7dfc5e28 - main - makefs: Fix 32-bit issues in ZFS time attributes setting
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 18 Aug 2022 01:46:42 UTC
The branch main has been updated by jrtc27: URL: https://cgit.FreeBSD.org/src/commit/?id=b0ce7dfc5e28650980d52f45aadd79e10012c291 commit b0ce7dfc5e28650980d52f45aadd79e10012c291 Author: Jessica Clarke <jrtc27@FreeBSD.org> AuthorDate: 2022-08-18 01:46:27 +0000 Commit: Jessica Clarke <jrtc27@FreeBSD.org> CommitDate: 2022-08-18 01:46:27 +0000 makefs: Fix 32-bit issues in ZFS time attributes setting Currently the code copies a struct timespec's raw bits as a pair of uint64_t. On 64-bit systems this has the same representation, but on 32-bit issues there are two issues: 1. tv_sec is a time_t which is 32-bit on i386 specifically 2. tv_nsec is a long not a 64-bit integer On i386, this means the assertion should fire as the size doesn't match. On other 32-bit systems there are 4 bytes of padding after tv_nsec, which in practice are probably 0, as this data is ultimately coming from the kernel, so it's deterministic (though the padding bytes are not required to be preserved by the compiler, so are strictly unspecified). However, on 32-bit big-endian systems, the padding bytes are in the wrong half to be harmless, resulting in the nanoseconds being multiplied by 2^32. Fix this all by marshalling via a real uint64_t pair like is done by the real ZFS_TIME_ENCODE. Reviewed by: markj Fixes: 240afd8c1fcc ("makefs: Add ZFS support") Differential Revision: https://reviews.freebsd.org/D36131 --- usr.sbin/makefs/zfs/fs.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/usr.sbin/makefs/zfs/fs.c b/usr.sbin/makefs/zfs/fs.c index b246a8e23f4e..bf8d5483d610 100644 --- a/usr.sbin/makefs/zfs/fs.c +++ b/usr.sbin/makefs/zfs/fs.c @@ -301,6 +301,21 @@ fs_readlink(const fsnode *cur, struct fs_populate_arg *arg, buf[n] = '\0'; } +static void +fs_populate_time(zfs_fs_t *fs, char *attrbuf, struct timespec *ts, + uint16_t ind, size_t *szp) +{ + uint64_t timebuf[2]; + + assert(ind < fs->sacnt); + assert(fs->saoffs[ind] != 0xffff); + assert(fs->satab[ind].size == sizeof(timebuf)); + + timebuf[0] = ts->tv_sec; + timebuf[1] = ts->tv_nsec; + fs_populate_attr(fs, attrbuf, timebuf, ind, szp); +} + static void fs_populate_sattrs(struct fs_populate_arg *arg, const fsnode *cur, dnode_phys_t *dnode) @@ -438,14 +453,10 @@ fs_populate_sattrs(struct fs_populate_arg *arg, const fsnode *cur, * We deliberately set atime = mtime here to ensure that images are * reproducible. */ - assert(sizeof(sb->st_mtim) == fs->satab[ZPL_ATIME].size); - fs_populate_attr(fs, attrbuf, &sb->st_mtim, ZPL_ATIME, &bonussz); - assert(sizeof(sb->st_ctim) == fs->satab[ZPL_CTIME].size); - fs_populate_attr(fs, attrbuf, &sb->st_ctim, ZPL_CTIME, &bonussz); - assert(sizeof(sb->st_mtim) == fs->satab[ZPL_MTIME].size); - fs_populate_attr(fs, attrbuf, &sb->st_mtim, ZPL_MTIME, &bonussz); - assert(sizeof(sb->st_birthtim) == fs->satab[ZPL_CRTIME].size); - fs_populate_attr(fs, attrbuf, &sb->st_birthtim, ZPL_CRTIME, &bonussz); + fs_populate_time(fs, attrbuf, &sb->st_mtim, ZPL_ATIME, &bonussz); + fs_populate_time(fs, attrbuf, &sb->st_ctim, ZPL_CTIME, &bonussz); + fs_populate_time(fs, attrbuf, &sb->st_mtim, ZPL_MTIME, &bonussz); + fs_populate_time(fs, attrbuf, &sb->st_birthtim, ZPL_CRTIME, &bonussz); fs_populate_varszattr(fs, attrbuf, aces, sizeof(aces), 0, ZPL_DACL_ACES, &bonussz);