summaryrefslogtreecommitdiff
path: root/sys/nfs
diff options
context:
space:
mode:
authorAlexander Bluhm <bluhm@cvs.openbsd.org>2018-05-04 11:16:05 +0000
committerAlexander Bluhm <bluhm@cvs.openbsd.org>2018-05-04 11:16:05 +0000
commite52902e4aa718e14d540a7cf10b1ac6e9a105e1b (patch)
treee3855fdb9fffe617a2577c72ffc60f01330abf13 /sys/nfs
parent77f35fd1a333ed6f5036269ec2f8de076fca5f25 (diff)
After unmount nfs_timer() could access the freed memory of struct
nfsmount. Delay the free(9) of the nfs mount point data until pending or sleeping timeouts have finished by running it on the softclock thread. OK visa@
Diffstat (limited to 'sys/nfs')
-rw-r--r--sys/nfs/nfs_vfsops.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c
index 3d850004a8c..ae0b858104d 100644
--- a/sys/nfs/nfs_vfsops.c
+++ b/sys/nfs/nfs_vfsops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_vfsops.c,v 1.119 2018/05/02 02:24:56 visa Exp $ */
+/* $OpenBSD: nfs_vfsops.c,v 1.120 2018/05/04 11:16:04 bluhm Exp $ */
/* $NetBSD: nfs_vfsops.c,v 1.46.4.1 1996/05/25 22:40:35 fvdl Exp $ */
/*
@@ -84,6 +84,7 @@ int nfs_start(struct mount *, int, struct proc *);
int nfs_statfs(struct mount *, struct statfs *, struct proc *);
int nfs_sync(struct mount *, int, int, struct ucred *, struct proc *);
int nfs_unmount(struct mount *, int, struct proc *);
+void nfs_reaper(void *);
int nfs_vget(struct mount *, ino_t, struct vnode **);
int nfs_vptofh(struct vnode *, struct fid *);
int nfs_mountroot(void);
@@ -746,12 +747,24 @@ nfs_unmount(struct mount *mp, int mntflags, struct proc *p)
nfs_disconnect(nmp);
m_freem(nmp->nm_nam);
timeout_del(&nmp->nm_rtimeout);
- free(nmp, M_NFSMNT, sizeof(*nmp));
+ timeout_set_proc(&nmp->nm_rtimeout, nfs_reaper, nmp);
+ timeout_add(&nmp->nm_rtimeout, 0);
mp->mnt_data = NULL;
return (0);
}
/*
+ * Delay nfs mount point free until pending or sleeping timeouts have finished.
+ */
+void
+nfs_reaper(void *arg)
+{
+ struct nfsmount *nmp = arg;
+
+ free(nmp, M_NFSMNT, sizeof(*nmp));
+}
+
+/*
* Return root of a filesystem
*/
int