aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Macklem <rmacklem@FreeBSD.org>2023-02-24 15:36:28 +0000
committerRick Macklem <rmacklem@FreeBSD.org>2023-02-24 15:36:28 +0000
commit4036fcb8053adf3ac54c8428eef0dd076dfc1718 (patch)
treea05bf66d234b3b2b6dea7973558127f6fc791924
parent70960bb86a3ba5b6f5c4652e613e6313a7ed1ac1 (diff)
downloadsrc-4036fcb8053adf3ac54c8428eef0dd076dfc1718.tar.gz
src-4036fcb8053adf3ac54c8428eef0dd076dfc1718.zip
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
-rw-r--r--sys/fs/nfs/nfs_commonport.c8
1 files 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 *);