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
This commit is contained in:
Rick Macklem 2023-02-24 07:36:28 -08:00
parent 70960bb86a
commit 4036fcb805

View File

@ -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 *);