diff options
author | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2009-08-11 11:07:37 +0000 |
---|---|---|
committer | Thordur I. Bjornsson <thib@cvs.openbsd.org> | 2009-08-11 11:07:37 +0000 |
commit | eaa5cc3a729723b87f770e5319d57549e6bd9bcc (patch) | |
tree | 029ab802ca62fed8ba906e255df3a25b3129f232 | |
parent | e90e1b5a69a87fae8c01ce2bd524a3a254dda719 (diff) |
Fix a few bugs in nfsrv_rename() error recovery code.
- Prevent a double vrele() by setting the vnode pointer to NULL.
- Check if vnode pointers have been set to NULL before trying to
vrele().
- don't double free the component path name buffer.
- Add a workaround for multiple vnode pointers all pointing to the
same vnode and the code doing vrele() on all of them, leading to
botched refcounts. This is a horrible hack, but a real fix is being
worked on.
OK blambert@
-rw-r--r-- | sys/nfs/nfs_serv.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c index 5497237d817..85c3a6a592f 100644 --- a/sys/nfs/nfs_serv.c +++ b/sys/nfs/nfs_serv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nfs_serv.c,v 1.83 2009/08/10 09:44:44 blambert Exp $ */ +/* $OpenBSD: nfs_serv.c,v 1.84 2009/08/11 11:07:36 thib Exp $ */ /* $NetBSD: nfs_serv.c,v 1.34 1997/05/12 23:37:12 fvdl Exp $ */ /* @@ -1161,8 +1161,10 @@ nfsrv_mknod(nfsd, slp, procp, mrq) nfsm_reply(NFSX_WCCDATA(1)); nfsm_srvwcc(nfsd, dirfor_ret, &dirfor, diraft_ret, &diraft, &info.nmi_mb); - if (dirp) + if (dirp) { vrele(dirp); + dirp = NULL; + } error = 0; goto nfsmout; } @@ -1419,8 +1421,6 @@ nfsrv_rename(nfsd, slp, procp, mrq) &info.nmi_mb); nfsm_srvwcc(nfsd, tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft, &info.nmi_mb); - if (fdirp) - vrele(fdirp); error = 0; goto nfsmout; } @@ -1533,11 +1533,19 @@ nfsmout: pool_put(&namei_pool, tond.ni_cnd.cn_pnbuf); } if (fromnd.ni_cnd.cn_nameiop) { - vrele(fromnd.ni_startdir); - pool_put(&namei_pool, fromnd.ni_cnd.cn_pnbuf); + if (fromnd.ni_startdir) + vrele(fromnd.ni_startdir); VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); - vrele(fromnd.ni_dvp); - vrele(fvp); + + /* + * XXX: Workaround the fact that fromnd.ni_dvp can point + * to the same vnode as fdirp. The real fix is to not have + * multiple pointers to the same object. + */ + if (fromnd.ni_dvp != NULL && fromnd.ni_dvp != fdirp) + vrele(fromnd.ni_dvp); + if (fvp) + vrele(fvp); } return (error); } |