diff -Nru nfs-ganesha-4.3/debian/changelog nfs-ganesha-4.3/debian/changelog --- nfs-ganesha-4.3/debian/changelog 2024-04-15 07:03:12.000000000 -0700 +++ nfs-ganesha-4.3/debian/changelog 2024-05-16 21:30:16.000000000 -0700 @@ -1,3 +1,9 @@ +nfs-ganesha (4.3-8ubuntu2) noble; urgency=medium + + * Fix null pointer ref in free_state (LP: #2065856) + + -- Nick O'Connor Thu, 16 May 2024 21:30:16 -0700 + nfs-ganesha (4.3-8ubuntu1) noble; urgency=medium * Fix ftbfs with 64bit time_t. diff -Nru nfs-ganesha-4.3/debian/patches/20-fix-null-ptr-ref-in-free-state.diff nfs-ganesha-4.3/debian/patches/20-fix-null-ptr-ref-in-free-state.diff --- nfs-ganesha-4.3/debian/patches/20-fix-null-ptr-ref-in-free-state.diff 1969-12-31 16:00:00.000000000 -0800 +++ nfs-ganesha-4.3/debian/patches/20-fix-null-ptr-ref-in-free-state.diff 2024-05-16 21:30:16.000000000 -0700 @@ -0,0 +1,701 @@ +Description: Fix null pointer ref in free_state + Instead of trying to use the export attached to a state to call the FSAL + free_state, use a function pointer which if non-NULL is used, otherwise we + just gsh_free the state (which works for all in-tree FSALs). + . + nfs-ganesha (4.3-8ubuntu2) noble; urgency=medium + . + * Fix null pointer ref in free_state (LP: #2065856) +Origin: upstream, https://github.com/nfs-ganesha/nfs-ganesha/commit/336abcba0b9e0dae0aadb4657c311d04862f2028 +Bug: https://github.com/nfs-ganesha/nfs-ganesha/issues/904 +Bug-Ubuntu: https://launchpad.net/bugs/2065856 +Author: Frank S. Filz +Reviewed-By: Frank S. Filz +Last-Update: 2024-05-16 + +--- + +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_CEPH/export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_CEPH/export.c +@@ -433,7 +433,6 @@ void export_ops_init(struct export_ops * + ops->create_handle = create_handle; + ops->get_fs_dynamic_info = get_fs_dynamic_info; + ops->alloc_state = ceph_alloc_state; +- ops->free_state = ceph_free_state; + #ifdef CEPHFS_POSIX_ACL + ops->fs_acl_support = fs_acl_support; + #endif /* CEPHFS_POSIX_ACL */ +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_CEPH/handle.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_CEPH/handle.c +@@ -1066,7 +1066,7 @@ struct state_t *ceph_alloc_state(struct + struct ceph_fd *my_fd; + + state = init_state(gsh_calloc(1, sizeof(struct ceph_state_fd)), +- exp_hdl, state_type, related_state); ++ NULL, state_type, related_state); + + my_fd = &container_of(state, struct ceph_state_fd, state)->ceph_fd; + +@@ -1078,25 +1078,6 @@ struct state_t *ceph_alloc_state(struct + } + + /** +- * @brief free a ceph_state_fd structure +- * +- * @param[in] exp_hdl Export state_t will be associated with +- * @param[in] state Related state if appropriate +- * +- */ +-void ceph_free_state(struct fsal_export *exp_hdl, struct state_t *state) +-{ +- struct ceph_state_fd *state_fd = container_of(state, +- struct ceph_state_fd, +- state); +- struct ceph_fd *my_fd = &state_fd->ceph_fd; +- +- PTHREAD_RWLOCK_destroy(&my_fd->fdlock); +- +- gsh_free(state_fd); +-} +- +-/** + * @brief Merge a duplicate handle with an original handle + * + * This function is used if an upper layer detects that a duplicate +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_CEPH/internal.h ++++ nfs-ganesha-4.3/src/FSAL/FSAL_CEPH/internal.h +@@ -213,8 +213,6 @@ struct state_t *ceph_alloc_state(struct + enum state_type state_type, + struct state_t *related_state); + +-void ceph_free_state(struct fsal_export *exp_hdl, struct state_t *state); +- + #ifdef CEPHFS_POSIX_ACL + fsal_status_t ceph_set_acl(struct ceph_export *export, + struct ceph_handle *objhandle, bool is_dir, +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_GLUSTER/export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_GLUSTER/export.c +@@ -394,7 +394,7 @@ struct state_t *glusterfs_alloc_state(st + struct glusterfs_fd *my_fd; + + state = init_state(gsh_calloc(1, sizeof(struct glusterfs_state_fd)), +- exp_hdl, state_type, related_state); ++ NULL, state_type, related_state); + + my_fd = &container_of(state, struct glusterfs_state_fd, + state)->glusterfs_fd; +@@ -406,24 +406,6 @@ struct state_t *glusterfs_alloc_state(st + return state; + } + +-/** +- * @brief free a gluster_state_fd structure +- * +- * @param[in] exp_hdl Export state_t will be associated with +- * @param[in] state Related state if appropriate +- * +- */ +-void glusterfs_free_state(struct fsal_export *exp_hdl, struct state_t *state) +-{ +- struct glusterfs_state_fd *state_fd = +- container_of(state, struct glusterfs_state_fd, state); +- struct glusterfs_fd *my_fd = &state_fd->glusterfs_fd; +- +- PTHREAD_RWLOCK_destroy(&my_fd->fdlock); +- +- gsh_free(state_fd); +-} +- + /** @todo: We have gone POSIX way for the APIs below, can consider the CEPH way + * in case all are constants across all volumes etc. + */ +@@ -460,7 +442,6 @@ void export_ops_init(struct export_ops * + ops->get_fs_dynamic_info = get_dynamic_info; + ops->fs_supported_attrs = fs_supported_attrs; + ops->alloc_state = glusterfs_alloc_state; +- ops->free_state = glusterfs_free_state; + } + + enum transport { +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_GPFS/export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_GPFS/export.c +@@ -343,7 +343,7 @@ gpfs_alloc_state(struct fsal_export *exp + struct gpfs_fd *my_fd; + + state = init_state(gsh_calloc(1, sizeof(struct gpfs_state_fd)), +- exp_hdl, state_type, related_state); ++ NULL, state_type, related_state); + + my_fd = &container_of(state, struct gpfs_state_fd, state)->gpfs_fd; + +@@ -355,25 +355,6 @@ gpfs_alloc_state(struct fsal_export *exp + } + + /** +- * @brief free a gpfs_state_fd structure +- * +- * @param[in] exp_hdl Export state_t will be associated with +- * @param[in] state Related state if appropriate +- * +- */ +-void +-gpfs_free_state(struct fsal_export *exp_hdl, struct state_t *state) +-{ +- struct gpfs_state_fd *state_fd = container_of(state, +- struct gpfs_state_fd, +- state); +- struct gpfs_fd *my_fd = &state_fd->gpfs_fd; +- +- PTHREAD_RWLOCK_destroy(&my_fd->fdlock); +- gsh_free(state_fd); +-} +- +-/** + * @brief overwrite vector entries with the methods that we support + * @param ops type of struct export_ops + */ +@@ -389,7 +370,6 @@ void gpfs_export_ops_init(struct export_ + ops->get_quota = get_quota; + ops->set_quota = set_quota; + ops->alloc_state = gpfs_alloc_state; +- ops->free_state = gpfs_free_state; + } + + static void free_gpfs_filesystem(struct gpfs_filesystem *gpfs_fs) +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_KVSFS/kvsfs_export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_KVSFS/kvsfs_export.c +@@ -136,7 +136,7 @@ static struct state_t *kvsfs_alloc_state + struct kvsfs_fd *my_fd; + + state = init_state(gsh_calloc(1, sizeof(struct kvsfs_state_fd)), +- exp_hdl, state_type, related_state); ++ NULL, state_type, related_state); + + my_fd = &container_of(state, struct kvsfs_state_fd, state)->kvsfs_fd; + +@@ -148,25 +148,6 @@ static struct state_t *kvsfs_alloc_state + + } + +-/** +- * @brief free a gpfs_state_fd structure +- * +- * @param[in] exp_hdl Export state_t will be associated with +- * @param[in] state Related state if appropriate +- * +- */ +-static void kvsfs_free_state(struct fsal_export *exp_hdl, +- struct state_t *state) +-{ +- struct kvsfs_state_fd *state_fd = container_of(state, +- struct kvsfs_state_fd, +- state); +- struct kvsfs_fd *my_fd = &state_fd->kvsfs_fd; +- +- PTHREAD_RWLOCK_destroy(&my_fd->fdlock); +- gsh_free(state_fd); +-} +- + /* kvsfs_export_ops_init + * overwrite vector entries with the methods that we support + */ +@@ -180,7 +161,6 @@ void kvsfs_export_ops_init(struct export + ops->get_fs_dynamic_info = get_dynamic_info; + ops->fs_supported_attrs = kvsfs_supported_attrs; + ops->alloc_state = kvsfs_alloc_state; +- ops->free_state = kvsfs_free_state; + + } + +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_LIZARDFS/export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_LIZARDFS/export.c +@@ -403,18 +403,7 @@ struct state_t *lzfs_fsal_alloc_state(st + struct state_t *related_state) + { + return init_state(gsh_calloc(1, sizeof(struct lzfs_fsal_state_fd)), +- exp_hdl, state_type, related_state); +-} +- +-/*! \brief Free a state_t structure +- * +- * \see fsal_api.h for more information +- */ +-void lzfs_fsal_free_state(struct fsal_export *exp_hdl, struct state_t *state) +-{ +- struct lzfs_fsal_state_fd *state_fd = container_of( +- state, struct lzfs_fsal_state_fd, state); +- gsh_free(state_fd); ++ NULL, state_type, related_state); + } + + void lzfs_fsal_export_ops_init(struct export_ops *ops) +@@ -435,6 +424,5 @@ void lzfs_fsal_export_ops_init(struct ex + ops->fs_supported_attrs = lzfs_fsal_fs_supported_attrs; + ops->fs_umask = lzfs_fsal_fs_umask; + ops->alloc_state = lzfs_fsal_alloc_state; +- ops->free_state = lzfs_fsal_free_state; + lzfs_fsal_export_ops_pnfs(ops); + } +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_MEM/mem_export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_MEM/mem_export.c +@@ -165,7 +165,7 @@ static struct state_t *mem_alloc_state(s + + state = init_state(gsh_calloc(1, sizeof(struct state_t) + + sizeof(struct fsal_fd)), +- exp_hdl, state_type, related_state); ++ NULL, state_type, related_state); + #ifdef USE_LTTNG + tracepoint(fsalmem, mem_alloc_state, __func__, __LINE__, state); + #endif +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_PROXY_V4/export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_PROXY_V4/export.c +@@ -158,7 +158,6 @@ void proxyv4_export_ops_init(struct expo + ops->get_fs_dynamic_info = proxyv4_get_dynamic_info; + ops->fs_supported_attrs = proxyv4_get_supported_attrs; + ops->alloc_state = proxyv4_alloc_state; +- ops->free_state = proxyv4_free_state; + } + + fsal_status_t proxyv4_create_export(struct fsal_module *fsal_hdl, +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_PROXY_V4/handle.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_PROXY_V4/handle.c +@@ -135,18 +135,10 @@ struct state_t *proxyv4_alloc_state(stru + enum state_type state_type, + struct state_t *related_state) + { +- return init_state(gsh_calloc(1, sizeof(struct proxyv4_state)), exp_hdl, +- state_type, related_state); ++ return init_state(gsh_calloc(1, sizeof(struct proxyv4_state)), ++ NULL, state_type, related_state); + } + +-void proxyv4_free_state(struct fsal_export *exp_hdl, struct state_t *state) +-{ +- struct proxyv4_state *proxyv4_state_id = +- container_of(state, struct proxyv4_state, state); +- +- gsh_free(proxyv4_state_id); +-} +- + #define FSAL_VERIFIER_T_TO_VERIFIER4(verif4, fsal_verif) \ + do { \ + BUILD_BUG_ON(sizeof(fsal_verifier_t) != sizeof(verifier4)); \ +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_PROXY_V4/proxyv4_fsal_methods.h ++++ nfs-ganesha-4.3/src/FSAL/FSAL_PROXY_V4/proxyv4_fsal_methods.h +@@ -199,8 +199,6 @@ struct state_t *proxyv4_alloc_state(stru + enum state_type state_type, + struct state_t *related_state); + +-void proxyv4_free_state(struct fsal_export *exp_hdl, struct state_t *state); +- + int proxyv4_close_thread(struct proxyv4_export *proxyv4_exp); + + #endif +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_RGW/handle.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_RGW/handle.c +@@ -1499,7 +1499,7 @@ struct state_t *rgw_alloc_state(struct f + struct state_t *related_state) + { + return init_state(gsh_calloc(1, sizeof(struct rgw_open_state)), +- exp_hdl, state_type, related_state); ++ NULL, state_type, related_state); + } + + /** +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_VFS/export.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_VFS/export.c +@@ -304,7 +304,6 @@ void vfs_export_ops_init(struct export_o + ops->get_quota = get_quota; + ops->set_quota = set_quota; + ops->alloc_state = vfs_alloc_state; +- ops->free_state = vfs_free_state; + } + + int vfs_claim_filesystem(struct fsal_filesystem *fs, +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_VFS/file.c ++++ nfs-ganesha-4.3/src/FSAL/FSAL_VFS/file.c +@@ -200,7 +200,7 @@ struct state_t *vfs_alloc_state(struct f + struct vfs_fd *my_fd; + + state = init_state(gsh_calloc(1, sizeof(struct vfs_state_fd)), +- exp_hdl, state_type, related_state); ++ NULL, state_type, related_state); + + my_fd = &container_of(state, struct vfs_state_fd, state)->vfs_fd; + +@@ -212,24 +212,6 @@ struct state_t *vfs_alloc_state(struct f + } + + /** +- * @brief free a vfs_state_fd structure +- * +- * @param[in] exp_hdl Export state_t will be associated with +- * @param[in] state Related state if appropriate +- * +- */ +-void vfs_free_state(struct fsal_export *exp_hdl, struct state_t *state) +-{ +- struct vfs_state_fd *state_fd = container_of(state, struct vfs_state_fd, +- state); +- struct vfs_fd *my_fd = &state_fd->vfs_fd; +- +- PTHREAD_RWLOCK_destroy(&my_fd->fdlock); +- +- gsh_free(state_fd); +-} +- +-/** + * @brief Merge a duplicate handle with an original handle + * + * This function is used if an upper layer detects that a duplicate +--- nfs-ganesha-4.3.orig/src/FSAL/FSAL_VFS/vfs_methods.h ++++ nfs-ganesha-4.3/src/FSAL/FSAL_VFS/vfs_methods.h +@@ -281,7 +281,6 @@ fsal_status_t vfs_close(struct fsal_obj_ + struct state_t *vfs_alloc_state(struct fsal_export *exp_hdl, + enum state_type state_type, + struct state_t *related_state); +-void vfs_free_state(struct fsal_export *exp_hdl, struct state_t *state); + + fsal_status_t vfs_merge(struct fsal_obj_handle *orig_hdl, + struct fsal_obj_handle *dupe_hdl); +--- nfs-ganesha-4.3.orig/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_export.c ++++ nfs-ganesha-4.3/src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_export.c +@@ -900,23 +900,6 @@ static struct state_t *mdcache_alloc_sta + } + + /** +- * @brief Free state_t structure +- * +- * @param[in] exp_hdl Export state is associated with +- * @param[in] state State to free +- */ +-static void mdcache_free_state(struct fsal_export *exp_hdl, +- struct state_t *state) +-{ +- struct mdcache_fsal_export *exp = mdc_export(exp_hdl); +- struct fsal_export *sub_export = exp->mfe_exp.sub_export; +- +- subcall_raw(exp, +- sub_export->exp_ops.free_state(sub_export, state) +- ); +-} +- +-/** + * @brief Check to see if a user is superuser + * + * @param[in] exp_hdl Export state_t is associated with +@@ -992,7 +975,6 @@ void mdcache_export_ops_init(struct expo + ops->fs_loc_body_size = mdcache_fs_loc_body_size; + ops->get_write_verifier = mdcache_get_write_verifier; + ops->alloc_state = mdcache_alloc_state; +- ops->free_state = mdcache_free_state; + ops->is_superuser = mdcache_is_superuser; + ops->fs_expiretimeparent = mdcache_fs_expiretimeparent; + } +--- nfs-ganesha-4.3.orig/src/FSAL/Stackable_FSALs/FSAL_NULL/export.c ++++ nfs-ganesha-4.3/src/FSAL/Stackable_FSALs/FSAL_NULL/export.c +@@ -319,18 +319,6 @@ static struct state_t *nullfs_alloc_stat + return state; + } + +-static void nullfs_free_state(struct fsal_export *exp_hdl, +- struct state_t *state) +-{ +- struct nullfs_fsal_export *exp = container_of(exp_hdl, +- struct nullfs_fsal_export, export); +- +- op_ctx->fsal_export = exp->export.sub_export; +- exp->export.sub_export->exp_ops.free_state(exp->export.sub_export, +- state); +- op_ctx->fsal_export = &exp->export; +-} +- + static bool nullfs_is_superuser(struct fsal_export *exp_hdl, + const struct user_cred *creds) + { +@@ -423,7 +411,6 @@ void nullfs_export_ops_init(struct expor + ops->get_quota = get_quota; + ops->set_quota = set_quota; + ops->alloc_state = nullfs_alloc_state; +- ops->free_state = nullfs_free_state; + ops->is_superuser = nullfs_is_superuser; + } + +--- nfs-ganesha-4.3.orig/src/FSAL/default_methods.c ++++ nfs-ganesha-4.3/src/FSAL/default_methods.c +@@ -686,20 +686,7 @@ static struct state_t *alloc_state(struc + struct state_t *related_state) + { + return init_state(gsh_calloc(1, sizeof(struct state_t)), +- exp_hdl, state_type, related_state); +-} +- +-/** +- * @brief Free a state_t structure +- * +- * @param[in] state state_t structure to free. +- * +- * @returns NULL on failure otherwise a state structure. +- */ +- +-void free_state(struct fsal_export *exp_hdl, struct state_t *state) +-{ +- gsh_free(state); ++ NULL, state_type, related_state); + } + + /** +@@ -752,7 +739,6 @@ struct export_ops def_export_ops = { + .fs_loc_body_size = fs_loc_body_size, + .get_write_verifier = global_verifier, + .alloc_state = alloc_state, +- .free_state = free_state, + .is_superuser = is_superuser, + .fs_expiretimeparent = fs_expiretimeparent, + }; +--- nfs-ganesha-4.3.orig/src/Protocols/9P/9p_proto_tools.c ++++ nfs-ganesha-4.3/src/Protocols/9P/9p_proto_tools.c +@@ -325,8 +325,7 @@ void free_fid(struct _9p_fid *pfid) + pfid->state); + } + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- pfid->state); ++ free_state(pfid->state); + } + + if (pfid->pentry != NULL) +--- nfs-ganesha-4.3.orig/src/Protocols/NFS/nfs4_op_open.c ++++ nfs-ganesha-4.3/src/Protocols/NFS/nfs4_op_open.c +@@ -1191,8 +1191,7 @@ static void open4_ex(OPEN4args *arg, + if (res_OPEN4->status != NFS4_OK) { + /* Cleanup state on error */ + if (*new_state) +- op_ctx->fsal_export->exp_ops.free_state( +- op_ctx->fsal_export, *file_state); ++ free_state(*file_state); + else if (*file_state != NULL) + dec_state_t_ref(*file_state); + *file_state = NULL; +--- nfs-ganesha-4.3.orig/src/SAL/nfs4_state.c ++++ nfs-ganesha-4.3/src/SAL/nfs4_state.c +@@ -272,8 +272,7 @@ errout: + */ + (void) obj->obj_ops->close2(obj, pnew_state); + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- pnew_state); ++ free_state(pnew_state); + } + + if (got_export_ref) +--- nfs-ganesha-4.3.orig/src/SAL/nfs4_state_id.c ++++ nfs-ganesha-4.3/src/SAL/nfs4_state_id.c +@@ -511,7 +511,7 @@ void dec_nfs4_state_ref(struct state_t * + + PTHREAD_MUTEX_destroy(&state->state_mutex); + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, state); ++ free_state(state); + + if (str_valid) + LogFullDebug(COMPONENT_STATE, "Deleted %s", str); +--- nfs-ganesha-4.3.orig/src/SAL/nlm_state.c ++++ nfs-ganesha-4.3/src/SAL/nlm_state.c +@@ -317,7 +317,7 @@ void dec_nlm_state_ref(state_t *state) + /* We need to close the state before freeing the state. */ + (void) obj->obj_ops->close2(obj, state); + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, state); ++ free_state(state); + + /* Release 2 refs: our sentinel one, plus the one from + * get_state_obj_ref() */ +@@ -479,8 +479,7 @@ int get_nlm_state(enum state_type state_ + /* Free the ref taken above and the state. + * No need to close here, the state was never opened. + */ +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- state); ++ free_state(state); + state_obj->obj_ops->put_ref(state_obj); + + *pstate = NULL; +--- nfs-ganesha-4.3.orig/src/gtest/fsal_api/test_close2_latency.cc ++++ nfs-ganesha-4.3/src/gtest/fsal_api/test_close2_latency.cc +@@ -91,8 +91,7 @@ namespace { + + virtual void TearDown() { + for (int i = 0; i < LOOP_COUNT; ++i) { +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- file_state[i]); ++ free_state(file_state[i]); + } + + Close2EmptyLatencyTest::TearDown(); +@@ -128,7 +127,7 @@ TEST_F(Close2EmptyLatencyTest, SIMPLE) + status = fsal_remove(test_root, TEST_FILE); + ASSERT_EQ(status.major, 0); + obj->obj_ops->put_ref(obj); +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, file_state); ++ free_state(file_state); + } + + TEST_F(Close2EmptyLatencyTest, SIMPLE_BYPASS) +@@ -159,7 +158,7 @@ TEST_F(Close2EmptyLatencyTest, SIMPLE_BY + status = fsal_remove(test_root, TEST_FILE); + ASSERT_EQ(status.major, 0); + obj->obj_ops->put_ref(obj); +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, file_state); ++ free_state(file_state); + } + + TEST_F(Close2LoopLatencyTest, LOOP) +--- nfs-ganesha-4.3.orig/src/gtest/fsal_api/test_commit2_latency.cc ++++ nfs-ganesha-4.3/src/gtest/fsal_api/test_commit2_latency.cc +@@ -94,8 +94,7 @@ namespace { + status = test_file->obj_ops->close2(test_file, test_file_state); + EXPECT_EQ(0, status.major); + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- test_file_state); ++ free_state(test_file_state); + EXPECT_EQ(0, status.major); + + status = fsal_remove(test_root, TEST_FILE); +--- nfs-ganesha-4.3.orig/src/gtest/fsal_api/test_open2_latency.cc ++++ nfs-ganesha-4.3/src/gtest/fsal_api/test_open2_latency.cc +@@ -97,8 +97,7 @@ namespace { + + virtual void TearDown() { + for (int i = 0; i < LOOP_COUNT; ++i) { +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- file_state[i]); ++ free_state(file_state[i]); + } + + Open2EmptyLatencyTest::TearDown(); +@@ -135,7 +134,7 @@ TEST_F(Open2EmptyLatencyTest, SIMPLE) + status = fsal_remove(test_root, TEST_FILE); + ASSERT_EQ(status.major, 0); + obj->obj_ops->put_ref(obj); +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, file_state); ++ free_state(file_state); + } + + TEST_F(Open2EmptyLatencyTest, SIMPLE_BYPASS) +@@ -170,7 +169,7 @@ TEST_F(Open2EmptyLatencyTest, SIMPLE_BYP + status = fsal_remove(sub_hdl, TEST_FILE); + ASSERT_EQ(status.major, 0); + obj->obj_ops->put_ref(obj); +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, file_state); ++ free_state(file_state); + } + + TEST_F(Open2LoopLatencyTest, FSAL_OPEN2) +--- nfs-ganesha-4.3.orig/src/gtest/fsal_api/test_read2_latency.cc ++++ nfs-ganesha-4.3/src/gtest/fsal_api/test_read2_latency.cc +@@ -93,8 +93,7 @@ namespace { + status = test_file->obj_ops->close2(test_file, test_file_state); + EXPECT_EQ(0, status.major); + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- test_file_state); ++ free_state(test_file_state); + + status = fsal_remove(test_root, TEST_FILE); + EXPECT_EQ(status.major, 0); +--- nfs-ganesha-4.3.orig/src/gtest/fsal_api/test_reopen2_latency.cc ++++ nfs-ganesha-4.3/src/gtest/fsal_api/test_reopen2_latency.cc +@@ -91,8 +91,7 @@ namespace { + status = test_file->obj_ops->close2(test_file, test_file_state); + EXPECT_EQ(0, status.major); + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- test_file_state); ++ free_state(test_file_state); + + status = fsal_remove(test_root, TEST_FILE); + EXPECT_EQ(status.major, 0); +--- nfs-ganesha-4.3.orig/src/gtest/fsal_api/test_write2_latency.cc ++++ nfs-ganesha-4.3/src/gtest/fsal_api/test_write2_latency.cc +@@ -93,8 +93,7 @@ namespace { + status = test_file->obj_ops->close2(test_file, test_file_state); + EXPECT_EQ(0, status.major); + +- op_ctx->fsal_export->exp_ops.free_state(op_ctx->fsal_export, +- test_file_state); ++ free_state(test_file_state); + + status = fsal_remove(test_root, TEST_FILE); + EXPECT_EQ(status.major, 0); +--- nfs-ganesha-4.3.orig/src/include/FSAL/fsal_commonlib.h ++++ nfs-ganesha-4.3/src/include/FSAL/fsal_commonlib.h +@@ -197,11 +197,12 @@ fsal_status_t fsal_find_fd(struct fsal_f + */ + + static inline struct state_t *init_state(struct state_t *state, +- struct fsal_export *exp_hdl, ++ state_free_t state_free, + enum state_type state_type, + struct state_t *related_state) + { + state->state_type = state_type; ++ state->state_free = state_free; + + if (related_state) { + memcpy(state->state_data.lock.openstate_key, +--- nfs-ganesha-4.3.orig/src/include/fsal_api.h ++++ nfs-ganesha-4.3/src/include/fsal_api.h +@@ -1310,17 +1310,6 @@ struct export_ops { + struct state_t *related_state); + + /** +- * @brief Free a state_t structure +- * +- * @param[in] exp_hdl Export state_t is associated with +- * @param[in] state state_t structure to free. +- * +- * @returns NULL on failure otherwise a state structure. +- */ +- +- void (*free_state)(struct fsal_export *exp_hdl, struct state_t *state); +- +-/** + * @brief Check to see if a user is superuser + * + * @param[in] exp_hdl Export state_t is associated with +--- nfs-ganesha-4.3.orig/src/include/sal_data.h ++++ nfs-ganesha-4.3/src/include/sal_data.h +@@ -406,6 +406,7 @@ union state_data { + * + * The lists are protected by the st_lock + */ ++typedef void (state_free_t) (struct state_t *state); + + struct state_t { + struct glist_head state_list; /**< List of states on a file */ +@@ -416,6 +417,8 @@ struct state_t { + struct glist_head state_list_all; /**< Global list of all stateids */ + #endif + pthread_mutex_t state_mutex; /**< Mutex protecting following pointers */ ++ state_free_t *state_free; /**< function to free if default gsh_free ++ doesn't work. */ + struct gsh_export *state_export; /**< Export this entry belongs to */ + /* Don't re-order or move these next two. They are used for hashing */ + state_owner_t *state_owner; /**< State Owner related to state */ +@@ -431,6 +434,14 @@ struct state_t { + state. */ + }; + ++static inline void free_state(struct state_t *state) ++{ ++ if (state->state_free != NULL) ++ state->state_free(state); ++ else ++ gsh_free(state); ++} ++ + /* Macros to compare and copy state_t to a struct stateid4 */ + #define SAME_STATEID(id4, state) \ + ((id4)->seqid == (state)->state_seqid && \ diff -Nru nfs-ganesha-4.3/debian/patches/series nfs-ganesha-4.3/debian/patches/series --- nfs-ganesha-4.3/debian/patches/series 2024-04-15 07:01:59.000000000 -0700 +++ nfs-ganesha-4.3/debian/patches/series 2024-05-16 21:30:16.000000000 -0700 @@ -3,3 +3,4 @@ add-latomic-linking-as-needed.patch spelling.patch time-64.diff +20-fix-null-ptr-ref-in-free-state.diff