From 6f50f8e16b7c4a3f1925b41e3d47b479cd7b2d9f Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Sat, 28 Sep 2024 02:18:11 +1000 Subject: [PATCH] zfs_log: add flex array fields to log record structs ZIL log record structs (lr_XX_t) are frequently allocated with extra space after the struct to carry variable-sized "payload" items. Linux 6.10+ compiled with CONFIG_FORTIFY_SOURCE has been doing runtime bounds checking on memcpy() calls. Because these types had no indicator that they might use more space than their simple definition, __fortify_memcpy_chk will frequently complain about overruns eg: memcpy: detected field-spanning write (size 7) of single field "lr + 1" at zfs_log.c:425 (size 0) memcpy: detected field-spanning write (size 9) of single field "(char *)(lr + 1)" at zfs_log.c:593 (size 0) memcpy: detected field-spanning write (size 4) of single field "(char *)(lr + 1) + snamesize" at zfs_log.c:594 (size 0) memcpy: detected field-spanning write (size 7) of single field "lr + 1" at zfs_log.c:425 (size 0) memcpy: detected field-spanning write (size 9) of single field "(char *)(lr + 1)" at zfs_log.c:593 (size 0) memcpy: detected field-spanning write (size 4) of single field "(char *)(lr + 1) + snamesize" at zfs_log.c:594 (size 0) memcpy: detected field-spanning write (size 7) of single field "lr + 1" at zfs_log.c:425 (size 0) memcpy: detected field-spanning write (size 9) of single field "(char *)(lr + 1)" at zfs_log.c:593 (size 0) memcpy: detected field-spanning write (size 4) of single field "(char *)(lr + 1) + snamesize" at zfs_log.c:594 (size 0) To fix this, this commit adds flex array fields to all lr_XX_t structs that require them, and then uses those fields to access that end-of-struct area rather than more complicated casts and pointer addition. Sponsored-by: https://despairlabs.com/sponsor/ Reviewed-by: Alexander Motin Reviewed-by: Brian Behlendorf Signed-off-by: Rob Norris Closes #16501 Closes #16539 --- cmd/zdb/zdb_il.c | 6 +- cmd/ztest.c | 24 +++---- include/sys/zil.h | 30 +++++++-- module/zfs/zfs_log.c | 90 ++++++++++++------------- module/zfs/zfs_replay.c | 143 +++++++++++++++++++++------------------- 5 files changed, 162 insertions(+), 131 deletions(-) diff --git a/cmd/zdb/zdb_il.c b/cmd/zdb/zdb_il.c index e3caaeb70..80d81c115 100644 --- a/cmd/zdb/zdb_il.c +++ b/cmd/zdb/zdb_il.c @@ -64,7 +64,8 @@ static void zil_prt_rec_create(zilog_t *zilog, int txtype, const void *arg) { (void) zilog; - const lr_create_t *lr = arg; + const lr_create_t *lrc = arg; + const _lr_create_t *lr = &lrc->lr_create; time_t crtime = lr->lr_crtime[0]; char *name, *link; lr_attr_t *lrattr; @@ -121,7 +122,8 @@ static void zil_prt_rec_rename(zilog_t *zilog, int txtype, const void *arg) { (void) zilog, (void) txtype; - const lr_rename_t *lr = arg; + const lr_rename_t *lrr = arg; + const _lr_rename_t *lr = &lrr->lr_rename; char *snm = (char *)(lr + 1); char *tnm = snm + strlen(snm) + 1; diff --git a/cmd/ztest.c b/cmd/ztest.c index 8ad576627..c58d35c99 100644 --- a/cmd/ztest.c +++ b/cmd/ztest.c @@ -1940,7 +1940,7 @@ ztest_verify_unused_bonus(dmu_buf_t *db, void *end, uint64_t obj, static void ztest_log_create(ztest_ds_t *zd, dmu_tx_t *tx, lr_create_t *lr) { - char *name = (void *)(lr + 1); /* name follows lr */ + char *name = (char *)&lr->lr_data[0]; /* name follows lr */ size_t namesize = strlen(name) + 1; itx_t *itx; @@ -1948,7 +1948,7 @@ ztest_log_create(ztest_ds_t *zd, dmu_tx_t *tx, lr_create_t *lr) return; itx = zil_itx_create(TX_CREATE, sizeof (*lr) + namesize); - memcpy(&itx->itx_lr + 1, &lr->lr_common + 1, + memcpy(&itx->itx_lr + 1, &lr->lr_create.lr_common + 1, sizeof (*lr) + namesize - sizeof (lr_t)); zil_itx_assign(zd->zd_zilog, itx, tx); @@ -1957,7 +1957,7 @@ ztest_log_create(ztest_ds_t *zd, dmu_tx_t *tx, lr_create_t *lr) static void ztest_log_remove(ztest_ds_t *zd, dmu_tx_t *tx, lr_remove_t *lr, uint64_t object) { - char *name = (void *)(lr + 1); /* name follows lr */ + char *name = (char *)&lr->lr_data[0]; /* name follows lr */ size_t namesize = strlen(name) + 1; itx_t *itx; @@ -2043,8 +2043,9 @@ static int ztest_replay_create(void *arg1, void *arg2, boolean_t byteswap) { ztest_ds_t *zd = arg1; - lr_create_t *lr = arg2; - char *name = (void *)(lr + 1); /* name follows lr */ + lr_create_t *lrc = arg2; + _lr_create_t *lr = &lrc->lr_create; + char *name = (char *)&lrc->lr_data[0]; /* name follows lr */ objset_t *os = zd->zd_os; ztest_block_tag_t *bbt; dmu_buf_t *db; @@ -2122,7 +2123,7 @@ ztest_replay_create(void *arg1, void *arg2, boolean_t byteswap) VERIFY0(zap_add(os, lr->lr_doid, name, sizeof (uint64_t), 1, &lr->lr_foid, tx)); - (void) ztest_log_create(zd, tx, lr); + (void) ztest_log_create(zd, tx, lrc); dmu_tx_commit(tx); @@ -2134,7 +2135,7 @@ ztest_replay_remove(void *arg1, void *arg2, boolean_t byteswap) { ztest_ds_t *zd = arg1; lr_remove_t *lr = arg2; - char *name = (void *)(lr + 1); /* name follows lr */ + char *name = (char *)&lr->lr_data[0]; /* name follows lr */ objset_t *os = zd->zd_os; dmu_object_info_t doi; dmu_tx_t *tx; @@ -2188,9 +2189,9 @@ ztest_replay_write(void *arg1, void *arg2, boolean_t byteswap) ztest_ds_t *zd = arg1; lr_write_t *lr = arg2; objset_t *os = zd->zd_os; - void *data = lr + 1; /* data follows lr */ + uint8_t *data = &lr->lr_data[0]; /* data follows lr */ uint64_t offset, length; - ztest_block_tag_t *bt = data; + ztest_block_tag_t *bt = (ztest_block_tag_t *)data; ztest_block_tag_t *bbt; uint64_t gen, txg, lrtxg, crtxg; dmu_object_info_t doi; @@ -2649,7 +2650,8 @@ ztest_create(ztest_ds_t *zd, ztest_od_t *od, int count) continue; } - lr_create_t *lr = ztest_lr_alloc(sizeof (*lr), od->od_name); + lr_create_t *lrc = ztest_lr_alloc(sizeof (*lrc), od->od_name); + _lr_create_t *lr = &lrc->lr_create; lr->lr_doid = od->od_dir; lr->lr_foid = 0; /* 0 to allocate, > 0 to claim */ @@ -2733,7 +2735,7 @@ ztest_write(ztest_ds_t *zd, uint64_t object, uint64_t offset, uint64_t size, lr->lr_blkoff = 0; BP_ZERO(&lr->lr_blkptr); - memcpy(lr + 1, data, size); + memcpy(&lr->lr_data[0], data, size); error = ztest_replay_write(zd, lr, B_FALSE); diff --git a/include/sys/zil.h b/include/sys/zil.h index 384678b22..259f2d03f 100644 --- a/include/sys/zil.h +++ b/include/sys/zil.h @@ -248,6 +248,7 @@ typedef struct { uint32_t lr_attr_masksize; /* number of elements in array */ uint32_t lr_attr_bitmap; /* First entry of array */ /* remainder of array and additional lr_attr_end_t fields */ + uint8_t lr_attr_data[]; } lr_attr_t; /* @@ -264,9 +265,14 @@ typedef struct { uint64_t lr_gen; /* generation (txg of creation) */ uint64_t lr_crtime[2]; /* creation time */ uint64_t lr_rdev; /* rdev of object to create */ +} _lr_create_t; + +typedef struct { + _lr_create_t lr_create; /* common create portion */ /* name of object to create follows this */ /* for symlinks, link content follows name */ /* for creates with xvattr data, the name follows the xvattr info */ + uint8_t lr_data[]; } lr_create_t; /* @@ -293,18 +299,20 @@ typedef struct { * and group will be in lr_create. Name follows ACL data. */ typedef struct { - lr_create_t lr_create; /* common create portion */ + _lr_create_t lr_create; /* common create portion */ uint64_t lr_aclcnt; /* number of ACEs in ACL */ uint64_t lr_domcnt; /* number of unique domains */ uint64_t lr_fuidcnt; /* number of real fuids */ uint64_t lr_acl_bytes; /* number of bytes in ACL */ uint64_t lr_acl_flags; /* ACL flags */ + uint8_t lr_data[]; } lr_acl_create_t; typedef struct { lr_t lr_common; /* common portion of log record */ uint64_t lr_doid; /* obj id of directory */ /* name of object to remove follows this */ + uint8_t lr_data[]; } lr_remove_t; typedef struct { @@ -312,18 +320,24 @@ typedef struct { uint64_t lr_doid; /* obj id of directory */ uint64_t lr_link_obj; /* obj id of link */ /* name of object to link follows this */ + uint8_t lr_data[]; } lr_link_t; typedef struct { lr_t lr_common; /* common portion of log record */ uint64_t lr_sdoid; /* obj id of source directory */ uint64_t lr_tdoid; /* obj id of target directory */ +} _lr_rename_t; + +typedef struct { + _lr_rename_t lr_rename; /* common rename portion */ /* 2 strings: names of source and destination follow this */ + uint8_t lr_data[]; } lr_rename_t; typedef struct { - lr_rename_t lr_rename; /* common rename portion */ - /* members related to the whiteout file (based on lr_create_t) */ + _lr_rename_t lr_rename; /* common rename portion */ + /* members related to the whiteout file (based on _lr_create_t) */ uint64_t lr_wfoid; /* obj id of the new whiteout file */ uint64_t lr_wmode; /* mode of object */ uint64_t lr_wuid; /* uid of whiteout */ @@ -332,6 +346,7 @@ typedef struct { uint64_t lr_wcrtime[2]; /* creation time */ uint64_t lr_wrdev; /* always makedev(0, 0) */ /* 2 strings: names of source and destination follow this */ + uint8_t lr_data[]; } lr_rename_whiteout_t; typedef struct { @@ -342,6 +357,7 @@ typedef struct { uint64_t lr_blkoff; /* no longer used */ blkptr_t lr_blkptr; /* spa block pointer for replay */ /* write data will follow for small writes */ + uint8_t lr_data[]; } lr_write_t; typedef struct { @@ -362,6 +378,7 @@ typedef struct { uint64_t lr_atime[2]; /* access time */ uint64_t lr_mtime[2]; /* modification time */ /* optional attribute lr_attr_t may be here */ + uint8_t lr_data[]; } lr_setattr_t; typedef struct { @@ -369,6 +386,7 @@ typedef struct { uint64_t lr_foid; /* file object to change attributes */ uint64_t lr_size; /* xattr name and value follows */ + uint8_t lr_data[]; } lr_setsaxattr_t; typedef struct { @@ -376,6 +394,7 @@ typedef struct { uint64_t lr_foid; /* obj id of file */ uint64_t lr_aclcnt; /* number of acl entries */ /* lr_aclcnt number of ace_t entries follow this */ + uint8_t lr_data[]; } lr_acl_v0_t; typedef struct { @@ -387,6 +406,7 @@ typedef struct { uint64_t lr_acl_bytes; /* number of bytes in ACL */ uint64_t lr_acl_flags; /* ACL flags */ /* lr_acl_bytes number of variable sized ace's follows */ + uint8_t lr_data[]; } lr_acl_t; typedef struct { @@ -396,8 +416,8 @@ typedef struct { uint64_t lr_length; /* length of the blocks to clone */ uint64_t lr_blksz; /* file's block size */ uint64_t lr_nbps; /* number of block pointers */ - blkptr_t lr_bps[]; /* block pointers of the blocks to clone follows */ + blkptr_t lr_bps[]; } lr_clone_range_t; /* @@ -448,7 +468,7 @@ typedef struct itx { uint64_t itx_oid; /* object id */ uint64_t itx_gen; /* gen number for zfs_get_data */ lr_t itx_lr; /* common part of log record */ - /* followed by type-specific part of lr_xx_t and its immediate data */ + uint8_t itx_lr_data[]; /* type-specific part of lr_xx_t */ } itx_t; /* diff --git a/module/zfs/zfs_log.c b/module/zfs/zfs_log.c index 8d0aebbec..16b07cc0a 100644 --- a/module/zfs/zfs_log.c +++ b/module/zfs/zfs_log.c @@ -300,14 +300,13 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, zfs_fuid_info_t *fuidp, vattr_t *vap) { itx_t *itx; - lr_create_t *lr; - lr_acl_create_t *lracl; + _lr_create_t *lr; + lr_acl_create_t *lracl = NULL; + uint8_t *lrdata; size_t aclsize = 0; size_t xvatsize = 0; size_t txsize; xvattr_t *xvap = (xvattr_t *)vap; - void *end; - size_t lrsize; size_t namesize = strlen(name) + 1; size_t fuidsz = 0; @@ -329,18 +328,21 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, if ((int)txtype == TX_CREATE_ATTR || (int)txtype == TX_MKDIR_ATTR || (int)txtype == TX_CREATE || (int)txtype == TX_MKDIR || (int)txtype == TX_MKXATTR) { - txsize = sizeof (*lr) + namesize + fuidsz + xvatsize; - lrsize = sizeof (*lr); + txsize = sizeof (lr_create_t) + namesize + fuidsz + xvatsize; + itx = zil_itx_create(txtype, txsize); + lr_create_t *lrc = (lr_create_t *)&itx->itx_lr; + lrdata = &lrc->lr_data[0]; } else { txsize = sizeof (lr_acl_create_t) + namesize + fuidsz + ZIL_ACE_LENGTH(aclsize) + xvatsize; - lrsize = sizeof (lr_acl_create_t); + itx = zil_itx_create(txtype, txsize); + lracl = (lr_acl_create_t *)&itx->itx_lr; + lrdata = &lracl->lr_data[0]; } - itx = zil_itx_create(txtype, txsize); - lr = (lr_create_t *)&itx->itx_lr; + lr = (_lr_create_t *)&itx->itx_lr; lr->lr_doid = dzp->z_id; lr->lr_foid = zp->z_id; /* Store dnode slot count in 8 bits above object id. */ @@ -369,16 +371,14 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, * Fill in xvattr info if any */ if (vap->va_mask & ATTR_XVATTR) { - zfs_log_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), xvap); - end = (caddr_t)lr + lrsize + xvatsize; - } else { - end = (caddr_t)lr + lrsize; + zfs_log_xvattr((lr_attr_t *)lrdata, xvap); + lrdata = &lrdata[xvatsize]; } /* Now fill in any ACL info */ if (vsecp) { - lracl = (lr_acl_create_t *)&itx->itx_lr; + ASSERT3P(lracl, !=, NULL); lracl->lr_aclcnt = vsecp->vsa_aclcnt; lracl->lr_acl_bytes = aclsize; lracl->lr_domcnt = fuidp ? fuidp->z_domain_cnt : 0; @@ -388,19 +388,19 @@ zfs_log_create(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, else lracl->lr_acl_flags = 0; - memcpy(end, vsecp->vsa_aclentp, aclsize); - end = (caddr_t)end + ZIL_ACE_LENGTH(aclsize); + memcpy(lrdata, vsecp->vsa_aclentp, aclsize); + lrdata = &lrdata[ZIL_ACE_LENGTH(aclsize)]; } /* drop in FUID info */ if (fuidp) { - end = zfs_log_fuid_ids(fuidp, end); - end = zfs_log_fuid_domains(fuidp, end); + lrdata = zfs_log_fuid_ids(fuidp, lrdata); + lrdata = zfs_log_fuid_domains(fuidp, lrdata); } /* * Now place file name in log record */ - memcpy(end, name, namesize); + memcpy(lrdata, name, namesize); zil_itx_assign(zilog, itx, tx); } @@ -422,7 +422,7 @@ zfs_log_remove(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, itx = zil_itx_create(txtype, sizeof (*lr) + namesize); lr = (lr_remove_t *)&itx->itx_lr; lr->lr_doid = dzp->z_id; - memcpy(lr + 1, name, namesize); + memcpy(&lr->lr_data[0], name, namesize); itx->itx_oid = foid; @@ -458,7 +458,7 @@ zfs_log_link(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, lr = (lr_link_t *)&itx->itx_lr; lr->lr_doid = dzp->z_id; lr->lr_link_obj = zp->z_id; - memcpy(lr + 1, name, namesize); + memcpy(&lr->lr_data[0], name, namesize); zil_itx_assign(zilog, itx, tx); } @@ -471,15 +471,17 @@ zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *dzp, znode_t *zp, const char *name, const char *link) { itx_t *itx; - lr_create_t *lr; + _lr_create_t *lr; + lr_create_t *lrc; size_t namesize = strlen(name) + 1; size_t linksize = strlen(link) + 1; if (zil_replaying(zilog, tx)) return; - itx = zil_itx_create(txtype, sizeof (*lr) + namesize + linksize); - lr = (lr_create_t *)&itx->itx_lr; + itx = zil_itx_create(txtype, sizeof (*lrc) + namesize + linksize); + lrc = (lr_create_t *)&itx->itx_lr; + lr = &lrc->lr_create; lr->lr_doid = dzp->z_id; lr->lr_foid = zp->z_id; lr->lr_uid = KUID_TO_SUID(ZTOUID(zp)); @@ -489,8 +491,8 @@ zfs_log_symlink(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, sizeof (uint64_t)); (void) sa_lookup(zp->z_sa_hdl, SA_ZPL_CRTIME(ZTOZSB(zp)), lr->lr_crtime, sizeof (uint64_t) * 2); - memcpy((char *)(lr + 1), name, namesize); - memcpy((char *)(lr + 1) + namesize, link, linksize); + memcpy(&lrc->lr_data[0], name, namesize); + memcpy(&lrc->lr_data[namesize], link, linksize); zil_itx_assign(zilog, itx, tx); } @@ -500,7 +502,8 @@ do_zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp, const char *sname, znode_t *tdzp, const char *dname, znode_t *szp) { itx_t *itx; - lr_rename_t *lr; + _lr_rename_t *lr; + lr_rename_t *lrr; size_t snamesize = strlen(sname) + 1; size_t dnamesize = strlen(dname) + 1; @@ -508,11 +511,12 @@ do_zfs_log_rename(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, znode_t *sdzp, return; itx = zil_itx_create(txtype, sizeof (*lr) + snamesize + dnamesize); - lr = (lr_rename_t *)&itx->itx_lr; + lrr = (lr_rename_t *)&itx->itx_lr; + lr = &lrr->lr_rename; lr->lr_sdoid = sdzp->z_id; lr->lr_tdoid = tdzp->z_id; - memcpy((char *)(lr + 1), sname, snamesize); - memcpy((char *)(lr + 1) + snamesize, dname, dnamesize); + memcpy(&lrr->lr_data[0], sname, snamesize); + memcpy(&lrr->lr_data[snamesize], dname, dnamesize); itx->itx_oid = szp->z_id; zil_itx_assign(zilog, itx, tx); @@ -590,8 +594,8 @@ zfs_log_rename_whiteout(zilog_t *zilog, dmu_tx_t *tx, uint64_t txtype, (void) sa_lookup(wzp->z_sa_hdl, SA_ZPL_RDEV(ZTOZSB(wzp)), &lr->lr_wrdev, sizeof (lr->lr_wrdev)); - memcpy((char *)(lr + 1), sname, snamesize); - memcpy((char *)(lr + 1) + snamesize, dname, dnamesize); + memcpy(&lr->lr_data[0], sname, snamesize); + memcpy(&lr->lr_data[snamesize], dname, dnamesize); itx->itx_oid = szp->z_id; zil_itx_assign(zilog, itx, tx); @@ -663,8 +667,8 @@ zfs_log_write(zilog_t *zilog, dmu_tx_t *tx, int txtype, if (wr_state == WR_COPIED) { int err; DB_DNODE_ENTER(db); - err = dmu_read_by_dnode(DB_DNODE(db), off, len, lr + 1, - DMU_READ_NO_PREFETCH); + err = dmu_read_by_dnode(DB_DNODE(db), off, len, + &lr->lr_data[0], DMU_READ_NO_PREFETCH); DB_DNODE_EXIT(db); if (err != 0) { zil_itx_destroy(itx); @@ -733,7 +737,7 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, lr_setattr_t *lr; xvattr_t *xvap = (xvattr_t *)vap; size_t recsize = sizeof (lr_setattr_t); - void *start; + uint8_t *start; if (zil_replaying(zilog, tx) || zp->z_unlinked) return; @@ -767,10 +771,10 @@ zfs_log_setattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, lr->lr_size = (uint64_t)vap->va_size; ZFS_TIME_ENCODE(&vap->va_atime, lr->lr_atime); ZFS_TIME_ENCODE(&vap->va_mtime, lr->lr_mtime); - start = (lr_setattr_t *)(lr + 1); + start = &lr->lr_data[0]; if (vap->va_mask & ATTR_XVATTR) { zfs_log_xvattr((lr_attr_t *)start, xvap); - start = (caddr_t)start + ZIL_XVAT_SIZE(xvap->xva_mapsize); + start = &lr->lr_data[ZIL_XVAT_SIZE(xvap->xva_mapsize)]; } /* @@ -794,7 +798,6 @@ zfs_log_setsaxattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, itx_t *itx; lr_setsaxattr_t *lr; size_t recsize = sizeof (lr_setsaxattr_t); - void *xattrstart; int namelen; if (zil_replaying(zilog, tx) || zp->z_unlinked) @@ -805,10 +808,9 @@ zfs_log_setsaxattr(zilog_t *zilog, dmu_tx_t *tx, int txtype, itx = zil_itx_create(txtype, recsize); lr = (lr_setsaxattr_t *)&itx->itx_lr; lr->lr_foid = zp->z_id; - xattrstart = (char *)(lr + 1); - memcpy(xattrstart, name, namelen); + memcpy(&lr->lr_data[0], name, namelen); if (value != NULL) { - memcpy((char *)xattrstart + namelen, value, size); + memcpy(&lr->lr_data[namelen], value, size); lr->lr_size = size; } else { lr->lr_size = 0; @@ -866,13 +868,13 @@ zfs_log_acl(zilog_t *zilog, dmu_tx_t *tx, znode_t *zp, if (txtype == TX_ACL_V0) { lrv0 = (lr_acl_v0_t *)lr; - memcpy(lrv0 + 1, vsecp->vsa_aclentp, aclbytes); + memcpy(&lrv0->lr_data[0], vsecp->vsa_aclentp, aclbytes); } else { - void *start = (ace_t *)(lr + 1); + uint8_t *start = &lr->lr_data[0]; memcpy(start, vsecp->vsa_aclentp, aclbytes); - start = (caddr_t)start + ZIL_ACE_LENGTH(aclbytes); + start = &lr->lr_data[ZIL_ACE_LENGTH(aclbytes)]; if (fuidp) { start = zfs_log_fuid_ids(fuidp, start); diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c index 810550161..80c11d80f 100644 --- a/module/zfs/zfs_replay.c +++ b/module/zfs/zfs_replay.c @@ -293,16 +293,16 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; lr_acl_create_t *lracl = arg2; + _lr_create_t *lr = &lracl->lr_create; char *name = NULL; /* location determined later */ - lr_create_t *lr = (lr_create_t *)lracl; znode_t *dzp; znode_t *zp; xvattr_t xva; int vflg = 0; vsecattr_t vsec = { 0 }; lr_attr_t *lrattr; - void *aclstart; - void *fuidstart; + uint8_t *aclstart; + uint8_t *fuidstart; size_t xvatlen = 0; uint64_t txtype; uint64_t objid; @@ -316,17 +316,18 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) byteswap_uint64_array(lracl, sizeof (*lracl)); if (txtype == TX_CREATE_ACL_ATTR || txtype == TX_MKDIR_ACL_ATTR) { - lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); + lrattr = (lr_attr_t *)&lracl->lr_data[0]; zfs_replay_swap_attrs(lrattr); xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); } - aclstart = (caddr_t)(lracl + 1) + xvatlen; + aclstart = &lracl->lr_data[xvatlen]; zfs_ace_byteswap(aclstart, lracl->lr_acl_bytes, B_FALSE); + /* swap fuids */ if (lracl->lr_fuidcnt) { - byteswap_uint64_array((caddr_t)aclstart + - ZIL_ACE_LENGTH(lracl->lr_acl_bytes), + byteswap_uint64_array( + &aclstart[ZIL_ACE_LENGTH(lracl->lr_acl_bytes)], lracl->lr_fuidcnt * sizeof (uint64_t)); } } @@ -361,28 +362,27 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) vflg |= FIGNORECASE; switch (txtype) { case TX_CREATE_ACL: - aclstart = (caddr_t)(lracl + 1); - fuidstart = (caddr_t)aclstart + - ZIL_ACE_LENGTH(lracl->lr_acl_bytes); + aclstart = &lracl->lr_data[0]; + fuidstart = &aclstart[ZIL_ACE_LENGTH(lracl->lr_acl_bytes)]; zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, lr->lr_uid, lr->lr_gid); zfs_fallthrough; case TX_CREATE_ACL_ATTR: if (name == NULL) { - lrattr = (lr_attr_t *)(caddr_t)(lracl + 1); + lrattr = (lr_attr_t *)&lracl->lr_data[0]; xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); xva.xva_vattr.va_mask |= ATTR_XVATTR; zfs_replay_xvattr(lrattr, &xva); } vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; - vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; + vsec.vsa_aclentp = &lracl->lr_data[xvatlen]; vsec.vsa_aclcnt = lracl->lr_aclcnt; vsec.vsa_aclentsz = lracl->lr_acl_bytes; vsec.vsa_aclflags = lracl->lr_acl_flags; if (zfsvfs->z_fuid_replay == NULL) { - fuidstart = (caddr_t)(lracl + 1) + xvatlen + - ZIL_ACE_LENGTH(lracl->lr_acl_bytes); + fuidstart = &lracl->lr_data[xvatlen + + ZIL_ACE_LENGTH(lracl->lr_acl_bytes)]; zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, @@ -398,9 +398,8 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) #endif break; case TX_MKDIR_ACL: - aclstart = (caddr_t)(lracl + 1); - fuidstart = (caddr_t)aclstart + - ZIL_ACE_LENGTH(lracl->lr_acl_bytes); + aclstart = &lracl->lr_data[0]; + fuidstart = &aclstart[ZIL_ACE_LENGTH(lracl->lr_acl_bytes)]; zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, lr->lr_uid, lr->lr_gid); @@ -412,13 +411,13 @@ zfs_replay_create_acl(void *arg1, void *arg2, boolean_t byteswap) zfs_replay_xvattr(lrattr, &xva); } vsec.vsa_mask = VSA_ACE | VSA_ACE_ACLFLAGS; - vsec.vsa_aclentp = (caddr_t)(lracl + 1) + xvatlen; + vsec.vsa_aclentp = &lracl->lr_data[xvatlen]; vsec.vsa_aclcnt = lracl->lr_aclcnt; vsec.vsa_aclentsz = lracl->lr_acl_bytes; vsec.vsa_aclflags = lracl->lr_acl_flags; if (zfsvfs->z_fuid_replay == NULL) { - fuidstart = (caddr_t)(lracl + 1) + xvatlen + - ZIL_ACE_LENGTH(lracl->lr_acl_bytes); + fuidstart = &lracl->lr_data[xvatlen + + ZIL_ACE_LENGTH(lracl->lr_acl_bytes)]; zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, (void *)&name, lracl->lr_fuidcnt, lracl->lr_domcnt, @@ -456,14 +455,14 @@ static int zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; - lr_create_t *lr = arg2; + lr_create_t *lrc = arg2; + _lr_create_t *lr = &lrc->lr_create; char *name = NULL; /* location determined later */ char *link; /* symlink content follows name */ znode_t *dzp; znode_t *zp = NULL; xvattr_t xva; int vflg = 0; - size_t lrsize = sizeof (lr_create_t); lr_attr_t *lrattr; void *start; size_t xvatlen; @@ -476,9 +475,9 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) txtype = (lr->lr_common.lrc_txtype & ~TX_CI); if (byteswap) { - byteswap_uint64_array(lr, sizeof (*lr)); + byteswap_uint64_array(lrc, sizeof (*lrc)); if (txtype == TX_CREATE_ATTR || txtype == TX_MKDIR_ATTR) - zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); + zfs_replay_swap_attrs((lr_attr_t *)&lrc->lr_data[0]); } @@ -520,7 +519,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) if (txtype != TX_SYMLINK && txtype != TX_MKDIR_ATTR && txtype != TX_CREATE_ATTR) { - start = (lr + 1); + start = (void *)&lrc->lr_data[0]; zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); @@ -528,10 +527,10 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) switch (txtype) { case TX_CREATE_ATTR: - lrattr = (lr_attr_t *)(caddr_t)(lr + 1); + lrattr = (lr_attr_t *)&lrc->lr_data[0]; xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); - zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); - start = (caddr_t)(lr + 1) + xvatlen; + zfs_replay_xvattr(lrattr, &xva); + start = (void *)&lrc->lr_data[xvatlen]; zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); @@ -551,10 +550,10 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) #endif break; case TX_MKDIR_ATTR: - lrattr = (lr_attr_t *)(caddr_t)(lr + 1); + lrattr = (lr_attr_t *)&lrc->lr_data[0]; xvatlen = ZIL_XVAT_SIZE(lrattr->lr_attr_masksize); - zfs_replay_xvattr((lr_attr_t *)((caddr_t)lr + lrsize), &xva); - start = (caddr_t)(lr + 1) + xvatlen; + zfs_replay_xvattr(lrattr, &xva); + start = &lrc->lr_data[xvatlen]; zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); @@ -563,7 +562,7 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) case TX_MKDIR: if (name == NULL) - name = (char *)(lr + 1); + name = (char *)&lrc->lr_data[0]; #if defined(__linux__) error = zfs_mkdir(dzp, name, &xva.xva_vattr, @@ -578,8 +577,8 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap) error = zfs_make_xattrdir(dzp, &xva.xva_vattr, &zp, kcred); break; case TX_SYMLINK: - name = (char *)(lr + 1); - link = name + strlen(name) + 1; + name = &lrc->lr_data[0]; + link = &lrc->lr_data[strlen(name) + 1]; #if defined(__linux__) error = zfs_symlink(dzp, name, &xva.xva_vattr, link, &zp, kcred, vflg, zfs_init_idmap); @@ -612,7 +611,7 @@ zfs_replay_remove(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; lr_remove_t *lr = arg2; - char *name = (char *)(lr + 1); /* name follows lr_remove_t */ + char *name = (char *)&lr->lr_data[0]; /* name follows lr_remove_t */ znode_t *dzp; int error; int vflg = 0; @@ -649,7 +648,7 @@ zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; lr_link_t *lr = arg2; - char *name = (char *)(lr + 1); /* name follows lr_link_t */ + char *name = &lr->lr_data[0]; /* name follows lr_link_t */ znode_t *dzp, *zp; int error; int vflg = 0; @@ -678,7 +677,7 @@ zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap) } static int -do_zfs_replay_rename(zfsvfs_t *zfsvfs, lr_rename_t *lr, char *sname, +do_zfs_replay_rename(zfsvfs_t *zfsvfs, _lr_rename_t *lr, char *sname, char *tname, uint64_t rflags, vattr_t *wo_vap) { znode_t *sdzp, *tdzp; @@ -722,15 +721,17 @@ static int zfs_replay_rename(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; - lr_rename_t *lr = arg2; + lr_rename_t *lrr = arg2; + _lr_rename_t *lr = &lrr->lr_rename; ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr)); if (byteswap) - byteswap_uint64_array(lr, sizeof (*lr)); + byteswap_uint64_array(lrr, sizeof (*lrr)); - char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ - char *tname = sname + strlen(sname) + 1; + /* sname and tname follow lr_rename_t */ + char *sname = (char *)&lrr->lr_data[0]; + char *tname = (char *)&lrr->lr_data[strlen(sname)+1]; return (do_zfs_replay_rename(zfsvfs, lr, sname, tname, 0, NULL)); } @@ -739,15 +740,17 @@ zfs_replay_rename_exchange(void *arg1, void *arg2, boolean_t byteswap) { #ifdef __linux__ zfsvfs_t *zfsvfs = arg1; - lr_rename_t *lr = arg2; + lr_rename_t *lrr = arg2; + _lr_rename_t *lr = &lrr->lr_rename; ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr)); if (byteswap) - byteswap_uint64_array(lr, sizeof (*lr)); + byteswap_uint64_array(lrr, sizeof (*lrr)); - char *sname = (char *)(lr + 1); /* sname and tname follow lr_rename_t */ - char *tname = sname + strlen(sname) + 1; + /* sname and tname follow lr_rename_t */ + char *sname = (char *)&lrr->lr_data[0]; + char *tname = (char *)&lrr->lr_data[strlen(sname)+1]; return (do_zfs_replay_rename(zfsvfs, lr, sname, tname, RENAME_EXCHANGE, NULL)); #else @@ -760,24 +763,26 @@ zfs_replay_rename_whiteout(void *arg1, void *arg2, boolean_t byteswap) { #ifdef __linux__ zfsvfs_t *zfsvfs = arg1; - lr_rename_whiteout_t *lr = arg2; + lr_rename_whiteout_t *lrrw = arg2; + _lr_rename_t *lr = &lrrw->lr_rename; int error; /* For the whiteout file. */ xvattr_t xva; uint64_t objid; uint64_t dnodesize; - ASSERT3U(lr->lr_rename.lr_common.lrc_reclen, >, sizeof (*lr)); + ASSERT3U(lr->lr_common.lrc_reclen, >, sizeof (*lr)); if (byteswap) - byteswap_uint64_array(lr, sizeof (*lr)); + byteswap_uint64_array(lrrw, sizeof (*lrrw)); - objid = LR_FOID_GET_OBJ(lr->lr_wfoid); - dnodesize = LR_FOID_GET_SLOTS(lr->lr_wfoid) << DNODE_SHIFT; + objid = LR_FOID_GET_OBJ(lrrw->lr_wfoid); + dnodesize = LR_FOID_GET_SLOTS(lrrw->lr_wfoid) << DNODE_SHIFT; xva_init(&xva); zfs_init_vattr(&xva.xva_vattr, ATTR_MODE | ATTR_UID | ATTR_GID, - lr->lr_wmode, lr->lr_wuid, lr->lr_wgid, lr->lr_wrdev, objid); + lrrw->lr_wmode, lrrw->lr_wuid, lrrw->lr_wgid, lrrw->lr_wrdev, + objid); /* * As with TX_CREATE, RENAME_WHITEOUT ends up in zfs_mknode(), which @@ -786,8 +791,8 @@ zfs_replay_rename_whiteout(void *arg1, void *arg2, boolean_t byteswap) * attributes, so we smuggle the values inside the vattr's otherwise * unused va_ctime, va_nblocks, and va_fsid fields. */ - ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lr->lr_wcrtime); - xva.xva_vattr.va_nblocks = lr->lr_wgen; + ZFS_TIME_DECODE(&xva.xva_vattr.va_ctime, lrrw->lr_wcrtime); + xva.xva_vattr.va_nblocks = lrrw->lr_wgen; xva.xva_vattr.va_fsid = dnodesize; error = dnode_try_claim(zfsvfs->z_os, objid, dnodesize >> DNODE_SHIFT); @@ -795,9 +800,9 @@ zfs_replay_rename_whiteout(void *arg1, void *arg2, boolean_t byteswap) return (error); /* sname and tname follow lr_rename_whiteout_t */ - char *sname = (char *)(lr + 1); - char *tname = sname + strlen(sname) + 1; - return (do_zfs_replay_rename(zfsvfs, &lr->lr_rename, sname, tname, + char *sname = (char *)&lrrw->lr_data[0]; + char *tname = (char *)&lrrw->lr_data[strlen(sname)+1]; + return (do_zfs_replay_rename(zfsvfs, lr, sname, tname, RENAME_WHITEOUT, &xva.xva_vattr)); #else return (SET_ERROR(ENOTSUP)); @@ -809,7 +814,7 @@ zfs_replay_write(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; lr_write_t *lr = arg2; - char *data = (char *)(lr + 1); /* data follows lr_write_t */ + char *data = &lr->lr_data[0]; /* data follows lr_write_t */ znode_t *zp; int error; uint64_t eod, offset, length; @@ -968,7 +973,7 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) if ((lr->lr_mask & ATTR_XVATTR) && zfsvfs->z_version >= ZPL_VERSION_INITIAL) - zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); + zfs_replay_swap_attrs((lr_attr_t *)&lr->lr_data[0]); } if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) @@ -987,11 +992,11 @@ zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) * Fill in xvattr_t portions if necessary. */ - start = (lr_setattr_t *)(lr + 1); + start = (void *)&lr->lr_data[0]; if (vap->va_mask & ATTR_XVATTR) { zfs_replay_xvattr((lr_attr_t *)start, &xva); - start = (caddr_t)start + - ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); + start = &lr->lr_data[ + ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize)]; } else xva.xva_vattr.va_mask &= ~ATTR_XVATTR; @@ -1049,12 +1054,12 @@ zfs_replay_setsaxattr(void *arg1, void *arg2, boolean_t byteswap) /* Get xattr name, value and size from log record */ size = lr->lr_size; - name = (char *)(lr + 1); + name = (char *)&lr->lr_data[0]; if (size == 0) { value = NULL; error = nvlist_remove(nvl, name, DATA_TYPE_BYTE_ARRAY); } else { - value = name + strlen(name) + 1; + value = &lr->lr_data[strlen(name) + 1]; /* Limited to 32k to keep nvpair memory allocations small */ if (size > DXATTR_MAX_ENTRY_SIZE) { error = SET_ERROR(EFBIG); @@ -1099,7 +1104,7 @@ zfs_replay_acl_v0(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; lr_acl_v0_t *lr = arg2; - ace_t *ace = (ace_t *)(lr + 1); /* ace array follows lr_acl_t */ + ace_t *ace = (ace_t *)&lr->lr_data[0]; vsecattr_t vsa = {0}; znode_t *zp; int error; @@ -1148,7 +1153,7 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; lr_acl_t *lr = arg2; - ace_t *ace = (ace_t *)(lr + 1); + ace_t *ace = (ace_t *)&lr->lr_data[0]; vsecattr_t vsa = {0}; znode_t *zp; int error; @@ -1160,8 +1165,8 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap) byteswap_uint64_array(lr, sizeof (*lr)); zfs_ace_byteswap(ace, lr->lr_acl_bytes, B_FALSE); if (lr->lr_fuidcnt) { - byteswap_uint64_array((caddr_t)ace + - ZIL_ACE_LENGTH(lr->lr_acl_bytes), + byteswap_uint64_array(&lr->lr_data[ + ZIL_ACE_LENGTH(lr->lr_acl_bytes)], lr->lr_fuidcnt * sizeof (uint64_t)); } } @@ -1176,8 +1181,8 @@ zfs_replay_acl(void *arg1, void *arg2, boolean_t byteswap) vsa.vsa_aclflags = lr->lr_acl_flags; if (lr->lr_fuidcnt) { - void *fuidstart = (caddr_t)ace + - ZIL_ACE_LENGTH(lr->lr_acl_bytes); + void *fuidstart = &lr->lr_data[ + ZIL_ACE_LENGTH(lr->lr_acl_bytes)]; zfsvfs->z_fuid_replay = zfs_replay_fuids(fuidstart, &fuidstart,