From d3e35db9c36892ef70c72ccc500b0921642e39fc Mon Sep 17 00:00:00 2001 From: Thomas Lamprecht Date: Wed, 23 Oct 2024 18:33:25 +0200 Subject: [PATCH] cherry-pick patches for Linux 6.11 compat All merged already into upstream, only one conflict with (missing) change in context had to be resolved for the flex-array in ZFS log patch. Signed-off-by: Thomas Lamprecht --- ...-guard-access-to-freshly-introduced-.patch | 1 + ...runcate_shares-without-etc-exports.d.patch | 1 + ...0-compat-Fix-tracepoints-definitions.patch | 229 ++++ ...x-array-fields-to-log-record-structs.patch | 979 ++++++++++++++++++ ...add-flex-array-field-to-TString-type.patch | 103 ++ debian/patches/series | 3 + 6 files changed, 1316 insertions(+) create mode 100644 debian/patches/0012-Linux-6.10-compat-Fix-tracepoints-definitions.patch create mode 100644 debian/patches/0013-zfs_log-add-flex-array-fields-to-log-record-structs.patch create mode 100644 debian/patches/0014-lua-add-flex-array-field-to-TString-type.patch diff --git a/debian/patches/0009-arc-stat-summary-guard-access-to-freshly-introduced-.patch b/debian/patches/0009-arc-stat-summary-guard-access-to-freshly-introduced-.patch index bc7db2a..75e68c8 100644 --- a/debian/patches/0009-arc-stat-summary-guard-access-to-freshly-introduced-.patch +++ b/debian/patches/0009-arc-stat-summary-guard-access-to-freshly-introduced-.patch @@ -31,6 +31,7 @@ These are present in the current kernel, but lead to an exception, if running the new user-space with an old kernel module. Signed-off-by: Stoiko Ivanov +Signed-off-by: Thomas Lamprecht --- cmd/arc_summary | 132 ++++++++++++++++++++++++------------------------ cmd/arcstat.in | 48 +++++++++--------- diff --git a/debian/patches/0010-Fix-nfs_truncate_shares-without-etc-exports.d.patch b/debian/patches/0010-Fix-nfs_truncate_shares-without-etc-exports.d.patch index 7eb9721..3fa7220 100644 --- a/debian/patches/0010-Fix-nfs_truncate_shares-without-etc-exports.d.patch +++ b/debian/patches/0010-Fix-nfs_truncate_shares-without-etc-exports.d.patch @@ -30,6 +30,7 @@ Closes #15369 Closes #15468 (cherry picked from commit 41e55b476bcfc90f1ad81c02c5375367fdace9e9) Signed-off-by: Stoiko Ivanov +Signed-off-by: Thomas Lamprecht --- lib/libshare/os/linux/nfs.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/debian/patches/0012-Linux-6.10-compat-Fix-tracepoints-definitions.patch b/debian/patches/0012-Linux-6.10-compat-Fix-tracepoints-definitions.patch new file mode 100644 index 0000000..189eb06 --- /dev/null +++ b/debian/patches/0012-Linux-6.10-compat-Fix-tracepoints-definitions.patch @@ -0,0 +1,229 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Pavel Snajdr +Date: Tue, 17 Sep 2024 22:38:02 +0200 +Subject: [PATCH] Linux 6.10 compat: Fix tracepoints definitions + +__string field definition includes the source variable for a value +of the string when the TP hits; in 6.10+ kernels, __assign_str() +uses that to copy a value from src to the string, with older +kernels, __assign_str still accepted src as a second parameter. + +Reviewed-by: Brian Behlendorf +Signed-off-by: Pavel Snajdr +Co-authored-by: Tony Hutter +Closes #16475 +Closes #16515 +Signed-off-by: Thomas Lamprecht +--- + config/kernel-assign_str.m4 | 62 +++++++++++++++++++++++++ + config/kernel.m4 | 1 + + include/os/linux/spl/sys/types.h | 6 +++ + include/os/linux/zfs/sys/trace_dbgmsg.h | 3 +- + include/os/linux/zfs/sys/trace_dbuf.h | 29 +++++------- + 5 files changed, 82 insertions(+), 19 deletions(-) + create mode 100644 config/kernel-assign_str.m4 + +diff --git a/config/kernel-assign_str.m4 b/config/kernel-assign_str.m4 +new file mode 100644 +index 000000000..cf4b00e7c +--- /dev/null ++++ b/config/kernel-assign_str.m4 +@@ -0,0 +1,62 @@ ++dnl # ++dnl # 6.10 kernel, check number of args of __assign_str() for trace: ++dnl ++dnl # 6.10+: one arg ++dnl # 6.9 and older: two args ++dnl # ++dnl # More specifically, this will test to see if __assign_str() takes one ++dnl # arg. If __assign_str() takes two args, or is not defined, then ++dnl # HAVE_1ARG_ASSIGN_STR will not be set. ++dnl # ++AC_DEFUN([ZFS_AC_KERNEL_1ARG_ASSIGN_STR], [ ++ AC_MSG_CHECKING([whether __assign_str() has one arg]) ++ ZFS_LINUX_TRY_COMPILE_HEADER([ ++ #include ++ MODULE_LICENSE("$ZFS_META_LICENSE"); ++ ++ #define CREATE_TRACE_POINTS ++ #include "conftest.h" ++ ],[ ++ trace_zfs_autoconf_event_one("1"); ++ trace_zfs_autoconf_event_two("2"); ++ ],[ ++ AC_MSG_RESULT(yes) ++ AC_DEFINE(HAVE_1ARG_ASSIGN_STR, 1, ++ [__assign_str() has one arg]) ++ ],[ ++ AC_MSG_RESULT(no) ++ ],[ ++ #if !defined(_CONFTEST_H) || defined(TRACE_HEADER_MULTI_READ) ++ #define _CONFTEST_H ++ ++ #undef TRACE_SYSTEM ++ #define TRACE_SYSTEM zfs ++ #include ++ ++ DECLARE_EVENT_CLASS(zfs_autoconf_event_class, ++ TP_PROTO(char *string), ++ TP_ARGS(string), ++ TP_STRUCT__entry( ++ __string(str, string) ++ ), ++ TP_fast_assign( ++ __assign_str(str); ++ ), ++ TP_printk("str = %s", __get_str(str)) ++ ); ++ ++ #define DEFINE_AUTOCONF_EVENT(name) \ ++ DEFINE_EVENT(zfs_autoconf_event_class, name, \ ++ TP_PROTO(char * str), \ ++ TP_ARGS(str)) ++ DEFINE_AUTOCONF_EVENT(zfs_autoconf_event_one); ++ DEFINE_AUTOCONF_EVENT(zfs_autoconf_event_two); ++ ++ #endif /* _CONFTEST_H */ ++ ++ #undef TRACE_INCLUDE_PATH ++ #define TRACE_INCLUDE_PATH . ++ #define TRACE_INCLUDE_FILE conftest ++ #include ++ ]) ++]) +diff --git a/config/kernel.m4 b/config/kernel.m4 +index f0cd76fd7..17d8694ce 100644 +--- a/config/kernel.m4 ++++ b/config/kernel.m4 +@@ -326,6 +326,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ + ZFS_AC_KERNEL_SYNC_BDEV + ZFS_AC_KERNEL_MM_PAGE_SIZE + ZFS_AC_KERNEL_MM_PAGE_MAPPING ++ ZFS_AC_KERNEL_1ARG_ASSIGN_STR + case "$host_cpu" in + powerpc*) + ZFS_AC_KERNEL_CPU_HAS_FEATURE +diff --git a/include/os/linux/spl/sys/types.h b/include/os/linux/spl/sys/types.h +index 94ba7b6ad..d3aefb184 100644 +--- a/include/os/linux/spl/sys/types.h ++++ b/include/os/linux/spl/sys/types.h +@@ -83,4 +83,10 @@ typedef struct user_namespace zidmap_t; + + extern zidmap_t *zfs_init_idmap; + ++#ifdef HAVE_1ARG_ASSIGN_STR ++#define __assign_str_impl(a, b) __assign_str(a) ++#else ++#define __assign_str_impl(a, b) __assign_str(a, b) ++#endif ++ + #endif /* _SPL_TYPES_H */ +diff --git a/include/os/linux/zfs/sys/trace_dbgmsg.h b/include/os/linux/zfs/sys/trace_dbgmsg.h +index 19f533baa..58081d64c 100644 +--- a/include/os/linux/zfs/sys/trace_dbgmsg.h ++++ b/include/os/linux/zfs/sys/trace_dbgmsg.h +@@ -32,6 +32,7 @@ + #define _TRACE_DBGMSG_H + + #include ++#include + + /* + * This file defines tracepoint events for use by the dbgmsg(), +@@ -59,7 +60,7 @@ DECLARE_EVENT_CLASS(zfs_dprintf_class, + __string(msg, msg) + ), + TP_fast_assign( +- __assign_str(msg, msg); ++ __assign_str_impl(msg, msg); + ), + TP_printk("%s", __get_str(msg)) + ); +diff --git a/include/os/linux/zfs/sys/trace_dbuf.h b/include/os/linux/zfs/sys/trace_dbuf.h +index 0e9cbdd72..b61807744 100644 +--- a/include/os/linux/zfs/sys/trace_dbuf.h ++++ b/include/os/linux/zfs/sys/trace_dbuf.h +@@ -45,9 +45,13 @@ + * dmu_buf_impl_t *, ..., + * zio_t *, ...); + */ ++#define DBUF_TP_STRUCT_ENTRY_OS_SPA \ ++ (db != NULL && \ ++ POINTER_IS_VALID(DB_DNODE(db)->dn_objset)) \ ++ ? spa_name(DB_DNODE(db)->dn_objset->os_spa) : "NULL" + + #define DBUF_TP_STRUCT_ENTRY \ +- __dynamic_array(char, os_spa, TRACE_DBUF_MSG_MAX) \ ++ __string(os_spa, DBUF_TP_STRUCT_ENTRY_OS_SPA) \ + __field(uint64_t, ds_object) \ + __field(uint64_t, db_object) \ + __field(uint64_t, db_level) \ +@@ -55,18 +59,11 @@ + __field(uint64_t, db_offset) \ + __field(uint64_t, db_size) \ + __field(uint64_t, db_state) \ +- __field(int64_t, db_holds) \ +- __dynamic_array(char, msg, TRACE_DBUF_MSG_MAX) ++ __field(int64_t, db_holds) + + #define DBUF_TP_FAST_ASSIGN \ + if (db != NULL) { \ +- if (POINTER_IS_VALID(DB_DNODE(db)->dn_objset)) { \ +- __assign_str(os_spa, \ +- spa_name(DB_DNODE(db)->dn_objset->os_spa)); \ +- } else { \ +- __assign_str(os_spa, "NULL"); \ +- } \ +- \ ++ __assign_str_impl(os_spa, DBUF_TP_STRUCT_ENTRY_OS_SPA); \ + __entry->ds_object = db->db_objset->os_dsl_dataset ? \ + db->db_objset->os_dsl_dataset->ds_object : 0; \ + \ +@@ -77,10 +74,8 @@ + __entry->db_size = db->db.db_size; \ + __entry->db_state = db->db_state; \ + __entry->db_holds = zfs_refcount_count(&db->db_holds); \ +- snprintf(__get_str(msg), TRACE_DBUF_MSG_MAX, \ +- DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS); \ + } else { \ +- __assign_str(os_spa, "NULL"); \ ++ __assign_str_impl(os_spa, DBUF_TP_STRUCT_ENTRY_OS_SPA); \ + __entry->ds_object = 0; \ + __entry->db_object = 0; \ + __entry->db_level = 0; \ +@@ -89,8 +84,6 @@ + __entry->db_size = 0; \ + __entry->db_state = 0; \ + __entry->db_holds = 0; \ +- snprintf(__get_str(msg), TRACE_DBUF_MSG_MAX, \ +- "dbuf { NULL }"); \ + } + + #define DBUF_TP_PRINTK_FMT \ +@@ -109,7 +102,7 @@ DECLARE_EVENT_CLASS(zfs_dbuf_class, + TP_ARGS(db, zio), + TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY), + TP_fast_assign(DBUF_TP_FAST_ASSIGN), +- TP_printk("%s", __get_str(msg)) ++ TP_printk(DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS) + ); + + DECLARE_EVENT_CLASS(zfs_dbuf_state_class, +@@ -117,7 +110,7 @@ DECLARE_EVENT_CLASS(zfs_dbuf_state_class, + TP_ARGS(db, why), + TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY), + TP_fast_assign(DBUF_TP_FAST_ASSIGN), +- TP_printk("%s", __get_str(msg)) ++ TP_printk(DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS) + ); + /* END CSTYLED */ + +@@ -139,7 +132,7 @@ DECLARE_EVENT_CLASS(zfs_dbuf_evict_one_class, + TP_ARGS(db, mls), + TP_STRUCT__entry(DBUF_TP_STRUCT_ENTRY), + TP_fast_assign(DBUF_TP_FAST_ASSIGN), +- TP_printk("%s", __get_str(msg)) ++ TP_printk(DBUF_TP_PRINTK_FMT, DBUF_TP_PRINTK_ARGS) + ); + /* END CSTYLED */ + diff --git a/debian/patches/0013-zfs_log-add-flex-array-fields-to-log-record-structs.patch b/debian/patches/0013-zfs_log-add-flex-array-fields-to-log-record-structs.patch new file mode 100644 index 0000000..3d95080 --- /dev/null +++ b/debian/patches/0013-zfs_log-add-flex-array-fields-to-log-record-structs.patch @@ -0,0 +1,979 @@ +From 0000000000000000000000000000000000000000 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 +(cherry picked from commit 6f50f8e16b7c4a3f1925b41e3d47b479cd7b2d9f) + [ TL: resolved context conflict stemming from not having commit + 72ef6b06a ("Cleanup DB_DNODE() macros usage") ] +Signed-off-by: Thomas Lamprecht +--- + 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 63d95dded..88b85f989 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 ca3105ffb..66b9c06bd 100644 +--- a/cmd/ztest.c ++++ b/cmd/ztest.c +@@ -1861,7 +1861,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; + +@@ -1869,7 +1869,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); +@@ -1878,7 +1878,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; + +@@ -1964,8 +1964,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; +@@ -2043,7 +2044,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); + +@@ -2055,7 +2056,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; +@@ -2109,9 +2110,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; +@@ -2563,7 +2564,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 */ +@@ -2647,7 +2649,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 4747ecc06..bbe973bce 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 006b91198..f50801130 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); +@@ -668,8 +672,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); + if (err != 0) { + zil_itx_destroy(itx); + itx = zil_itx_create(txtype, sizeof (*lr)); +@@ -741,7 +745,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; +@@ -775,10 +779,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)]; + } + + /* +@@ -802,7 +806,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) +@@ -813,10 +816,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; +@@ -874,13 +876,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 2e0af60f6..3d735b5fb 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, diff --git a/debian/patches/0014-lua-add-flex-array-field-to-TString-type.patch b/debian/patches/0014-lua-add-flex-array-field-to-TString-type.patch new file mode 100644 index 0000000..9edf54b --- /dev/null +++ b/debian/patches/0014-lua-add-flex-array-field-to-TString-type.patch @@ -0,0 +1,103 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Rob Norris +Date: Tue, 1 Oct 2024 03:30:03 +1000 +Subject: [PATCH] lua: add flex array field to TString type + +Linux 6.10+ with CONFIG_FORTIFY_SOURCE notices memcpy() accessing past +the end of TString, because it has no indication that there there may be +an additional allocation there. + +There's no appropriate upstream change for this (ancient) version of +Lua, so this is the narrowest change I could come up with to add a flex +array field to the end of TString to satisfy the check. It's loosely +based on changes from lua/lua@ca41b43f and lua/lua@9514abc2. + +Sponsored-by: https://despairlabs.com/sponsor/ +Reviewed-by: Alexander Motin +Reviewed-by: Brian Behlendorf +Signed-off-by: Rob Norris +Closes #16541 +Closes #16583 +Signed-off-by: Thomas Lamprecht +--- + module/lua/lobject.h | 21 ++++++++++++--------- + module/lua/lstate.h | 2 +- + module/lua/lstring.c | 2 +- + module/lua/lstring.h | 2 +- + 4 files changed, 15 insertions(+), 12 deletions(-) + +diff --git a/module/lua/lobject.h b/module/lua/lobject.h +index b7c6b41ac..06fdcdcbc 100644 +--- a/module/lua/lobject.h ++++ b/module/lua/lobject.h +@@ -404,19 +404,22 @@ typedef TValue *StkId; /* index to stack elements */ + /* + ** Header for string value; string bytes follow the end of this structure + */ +-typedef union TString { +- L_Umaxalign dummy; /* ensures maximum alignment for strings */ +- struct { +- CommonHeader; +- lu_byte extra; /* reserved words for short strings; "has hash" for longs */ +- unsigned int hash; +- size_t len; /* number of characters in string */ +- } tsv; ++typedef struct TString { ++ union { ++ L_Umaxalign dummy; /* ensures maximum alignment for strings */ ++ struct { ++ CommonHeader; ++ lu_byte extra; /* reserved words for short strings; "has hash" for longs */ ++ unsigned int hash; ++ size_t len; /* number of characters in string */ ++ } tsv; ++ }; ++ char contents[]; + } TString; + + + /* get the actual string (array of bytes) from a TString */ +-#define getstr(ts) cast(const char *, (ts) + 1) ++#define getstr(ts) ((ts)->contents) + + /* get the actual string (array of bytes) from a Lua value */ + #define svalue(o) getstr(rawtsvalue(o)) +diff --git a/module/lua/lstate.h b/module/lua/lstate.h +index 75c6ceda6..c5fa59335 100644 +--- a/module/lua/lstate.h ++++ b/module/lua/lstate.h +@@ -185,7 +185,7 @@ struct lua_State { + */ + union GCObject { + GCheader gch; /* common header */ +- union TString ts; ++ struct TString ts; + union Udata u; + union Closure cl; + struct Table h; +diff --git a/module/lua/lstring.c b/module/lua/lstring.c +index 15a73116b..149a4ffc5 100644 +--- a/module/lua/lstring.c ++++ b/module/lua/lstring.c +@@ -103,7 +103,7 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.extra = 0; +- sbuf = (char *)(TString *)(ts + 1); ++ sbuf = ts->contents; + memcpy(sbuf, str, l*sizeof(char)); + sbuf[l] = '\0'; /* ending 0 */ + return ts; +diff --git a/module/lua/lstring.h b/module/lua/lstring.h +index 260e7f169..257b38417 100644 +--- a/module/lua/lstring.h ++++ b/module/lua/lstring.h +@@ -12,7 +12,7 @@ + #include "lstate.h" + + +-#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) ++#define sizestring(s) (sizeof(struct TString)+((s)->len+1)*sizeof(char)) + + #define sizeudata(u) (sizeof(union Udata)+(u)->len) + diff --git a/debian/patches/series b/debian/patches/series index 229027f..f69eeed 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -9,3 +9,6 @@ 0009-arc-stat-summary-guard-access-to-freshly-introduced-.patch 0010-Fix-nfs_truncate_shares-without-etc-exports.d.patch 0011-zpool-status-tighten-bounds-for-noalloc-stat-availab.patch +0012-Linux-6.10-compat-Fix-tracepoints-definitions.patch +0013-zfs_log-add-flex-array-fields-to-log-record-structs.patch +0014-lua-add-flex-array-field-to-TString-type.patch