From 4036fcb8053adf3ac54c8428eef0dd076dfc1718 Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Fri, 24 Feb 2023 07:36:28 -0800 Subject: [PATCH] nfsd: Fix a use after free when vnet prisons are deleted The Kasan tests show the nfsrvd_cleancache() results in a modify after free. I think this occurs because the nfsrv_cleanup() function gets executed after nfs_cleanup() which free's the nfsstatsv1_p. This patch makes them use the same subsystem and sets SI_ORDER_FIRST for nfs_cleanup(), so that it will be called after nfsrv_cleanup() via VNET_SYSUNINIT(). The patch also sets nfsstatsv1_p NULL after free'ng it, so that a crash will result if it is used after free'ng. Tested by: markj Reviewed by: markj MFC after: 3 months Differential Revision: https://reviews.freebsd.org/D38750 --- sys/fs/nfs/nfs_commonport.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c index 212b498e6328..be5fc688b7eb 100644 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -885,7 +885,7 @@ nfs_vnetinit(const void *unused __unused) mtx_init(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx, "nfsuserd", NULL, MTX_DEF); } -VNET_SYSINIT(nfs_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY, +VNET_SYSINIT(nfs_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_FIRST, nfs_vnetinit, NULL); static void @@ -893,12 +893,14 @@ nfs_cleanup(void *unused __unused) { mtx_destroy(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx); - if (!IS_DEFAULT_VNET(curvnet)) + if (!IS_DEFAULT_VNET(curvnet)) { free(NFSD_VNET(nfsstatsv1_p), M_TEMP); + NFSD_VNET(nfsstatsv1_p) = NULL; + } /* Clean out the name<-->id cache. */ nfsrv_cleanusergroup(); } -VNET_SYSUNINIT(nfs_cleanup, SI_SUB_VNET_DONE, SI_ORDER_ANY, +VNET_SYSUNINIT(nfs_cleanup, SI_SUB_VNET_DONE, SI_ORDER_FIRST, nfs_cleanup, NULL); extern int (*nfsd_call_nfscommon)(struct thread *, struct nfssvc_args *);