summaryrefslogtreecommitdiffstats
path: root/sys/nfs
diff options
context:
space:
mode:
authorblambert <blambert@openbsd.org>2015-06-11 08:39:51 +0000
committerblambert <blambert@openbsd.org>2015-06-11 08:39:51 +0000
commit3db678b80e3fd17a6522173c1fbf8171ea7ce4a3 (patch)
treea03a363d5ee302165fe3af34633ca4ba45eb1447 /sys/nfs
parentremove uneeded pci includes (diff)
downloadwireguard-openbsd-3db678b80e3fd17a6522173c1fbf8171ea7ce4a3.tar.xz
wireguard-openbsd-3db678b80e3fd17a6522173c1fbf8171ea7ce4a3.zip
Avoid double-free in error path by cribbing the HASBUF flag
logic from the rest of the kernel that deals with filename lookups. In snaps for some time. Initially found by jsg@ Prodded by deraadt@
Diffstat (limited to 'sys/nfs')
-rw-r--r--sys/nfs/nfs_serv.c29
1 files changed, 21 insertions, 8 deletions
diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c
index e4eaaec0375..5649c1866a8 100644
--- a/sys/nfs/nfs_serv.c
+++ b/sys/nfs/nfs_serv.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: nfs_serv.c,v 1.103 2015/05/06 02:19:40 jsg Exp $ */
+/* $OpenBSD: nfs_serv.c,v 1.104 2015/06/11 08:39:51 blambert Exp $ */
/* $NetBSD: nfs_serv.c,v 1.34 1997/05/12 23:37:12 fvdl Exp $ */
/*
@@ -879,7 +879,6 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
info.nmi_dpos = nfsd->nd_dpos;
info.nmi_v3 = (nfsd->nd_flag & ND_NFSV3);
- nd.ni_cnd.cn_nameiop = 0;
fhp = &nfh.fh_generic;
nfsm_srvmtofh(fhp);
nfsm_srvnamesiz(len);
@@ -979,7 +978,10 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
if (va.va_type != VFIFO &&
(error = suser_ucred(cred))) {
vrele(nd.ni_startdir);
- pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ if (nd.ni_cnd.cn_flags & HASBUF) {
+ pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ nd.ni_cnd.cn_flags &= ~HASBUF;
+ }
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
vput(nd.ni_dvp);
nfsm_reply(0);
@@ -991,7 +993,10 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
&va);
if (error) {
vrele(nd.ni_startdir);
- pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ if (nd.ni_cnd.cn_flags & HASBUF) {
+ pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ nd.ni_cnd.cn_flags &= ~HASBUF;
+ }
nfsm_reply(0);
error = 0;
goto nfsmout;
@@ -1001,12 +1006,15 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nd.ni_cnd.cn_proc = procp;
nd.ni_cnd.cn_cred = cred;
if ((error = vfs_lookup(&nd)) != 0) {
- pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ if (nd.ni_cnd.cn_flags & HASBUF) {
+ pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ nd.ni_cnd.cn_flags &= ~HASBUF;
+ }
nfsm_reply(0);
error = 0;
goto nfsmout;
}
-
+
pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
if (nd.ni_cnd.cn_flags & ISSYMLINK) {
vrele(nd.ni_dvp);
@@ -1020,6 +1028,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
} else {
vrele(nd.ni_startdir);
pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ nd.ni_cnd.cn_flags &= ~HASBUF;
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
vput(nd.ni_dvp);
error = ENXIO;
@@ -1028,6 +1037,7 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
} else {
vrele(nd.ni_startdir);
pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ nd.ni_cnd.cn_flags &= ~HASBUF;
vp = nd.ni_vp;
if (nd.ni_dvp == vp)
vrele(nd.ni_dvp);
@@ -1081,9 +1091,12 @@ nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
nfsmout:
if (dirp)
vrele(dirp);
- if (nd.ni_cnd.cn_nameiop) {
+ if (nd.ni_cnd.cn_nameiop != LOOKUP) {
vrele(nd.ni_startdir);
- pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ if (nd.ni_cnd.cn_flags & HASBUF) {
+ pool_put(&namei_pool, nd.ni_cnd.cn_pnbuf);
+ nd.ni_cnd.cn_flags &= ~HASBUF;
+ }
}
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
if (nd.ni_dvp == nd.ni_vp)