Module Name: src
Committed By: bouyer
Date: Fri Apr 10 18:58:51 UTC 2009
Modified Files:
src/sys/nfs: nfs_serv.c nfsm_subs.h
Log Message:
PR kern/41158: nfs_rename() locking against myself
nfsrv_rename() can exit without calling genfs_renamelock_exit() because
the nfsm_reply() can do return (0) on error.
Change nfsm_reply to use 'error = 0; goto nfsmout' instead.
Fix a few place so it's safe to goto nfsmout from nfsm_reply, or other
macros calling it.
As a side effect it could fix a missing vrele(dirp) in various place where
nfsm_reply could return(0).
To generate a diff of this commit:
cvs rdiff -u -r1.143 -r1.144 src/sys/nfs/nfs_serv.c
cvs rdiff -u -r1.50 -r1.51 src/sys/nfs/nfsm_subs.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/nfs/nfs_serv.c
diff -u src/sys/nfs/nfs_serv.c:1.143 src/sys/nfs/nfs_serv.c:1.144
--- src/sys/nfs/nfs_serv.c:1.143 Sat Mar 14 15:36:24 2009
+++ src/sys/nfs/nfs_serv.c Fri Apr 10 18:58:50 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: nfs_serv.c,v 1.143 2009/03/14 15:36:24 dsl Exp $ */
+/* $NetBSD: nfs_serv.c,v 1.144 2009/04/10 18:58:50 bouyer Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.143 2009/03/14 15:36:24 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.144 2009/04/10 18:58:50 bouyer Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1392,7 +1392,7 @@
int32_t t1;
char *bpos;
int error = 0, cache = 0, len, tsize, dirfor_ret = 1, diraft_ret = 1;
- int rdev = 0;
+ int rdev = 0, abort = 0;
int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
char *cp2;
struct mbuf *mb, *mreq;
@@ -1419,6 +1419,7 @@
vrele(dirp);
return (0);
}
+ abort = 1;
VATTR_NULL(&va);
if (v3) {
va.va_mode = 0;
@@ -1494,6 +1495,7 @@
KAUTH_SYSTEM_MKNOD, 0, NULL, NULL, NULL))) {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
vput(nd.ni_dvp);
+ abort = 0;
nfsm_reply(0);
return (error);
} else
@@ -1509,12 +1511,14 @@
vrele(nd.ni_dvp);
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
error = EINVAL;
+ abort = 0;
nfsm_reply(0);
}
} else {
VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
vput(nd.ni_dvp);
error = ENXIO;
+ abort = 0;
}
vp = nd.ni_vp;
} else {
@@ -1524,6 +1528,7 @@
vrele(nd.ni_dvp);
else
vput(nd.ni_dvp);
+ abort = 0;
if (!error && va.va_size != -1) {
error = nfsrv_access(vp, VWRITE, cred,
(nd.ni_cnd.cn_flags & RDONLY), lwp, 0);
@@ -1561,7 +1566,9 @@
}
if (dirp) {
vrele(dirp);
+ dirp = NULL;
}
+ abort = 0;
nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
if (v3) {
if (!error) {
@@ -1578,13 +1585,15 @@
nfsmout:
if (dirp)
vrele(dirp);
- VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- if (nd.ni_vp)
- vput(nd.ni_vp);
+ if (abort) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (nd.ni_vp)
+ vput(nd.ni_vp);
+ }
return (error);
}
@@ -1604,6 +1613,7 @@
int32_t t1;
char *bpos;
int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1;
+ int abort = 0;
u_int32_t major, minor;
enum vtype vtyp;
char *cp2;
@@ -1629,6 +1639,7 @@
vrele(dirp);
return (0);
}
+ abort = 1;
nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
vtyp = nfsv3tov_type(*tl);
if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
@@ -1700,7 +1711,9 @@
if (dirp) {
diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
vrele(dirp);
+ dirp = NULL;
}
+ abort = 0;
nfsm_reply(NFSX_SRVFH(&nsfh, true) + NFSX_POSTOPATTR(1) +
NFSX_WCCDATA(1));
if (!error) {
@@ -1710,13 +1723,15 @@
nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
return (0);
nfsmout:
- VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- if (nd.ni_vp)
- vput(nd.ni_vp);
+ if (abort) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (nd.ni_vp)
+ vput(nd.ni_vp);
+ }
if (dirp)
vrele(dirp);
return (error);
@@ -2006,21 +2021,26 @@
}
vrele(tond.ni_startdir);
PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
+ tond.ni_cnd.cn_nameiop = 0;
out1:
if (fdirp) {
if (v3) {
fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred);
}
vrele(fdirp);
+ fdirp = NULL;
}
if (tdirp) {
if (v3) {
tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred);
}
vrele(tdirp);
+ tdirp = NULL;
}
vrele(fromnd.ni_startdir);
PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
+ fromnd.ni_cnd.cn_nameiop = 0;
+ localfs = NULL;
nfsm_reply(2 * NFSX_WCCDATA(v3));
if (v3) {
nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
@@ -2159,7 +2179,7 @@
char *bpos, *pathcp = NULL, *cp2;
struct uio io;
struct iovec iv;
- int error = 0, cache = 0, dirfor_ret = 1, diraft_ret = 1;
+ int error = 0, cache = 0, dirfor_ret = 1, diraft_ret = 1, abort = 0;
uint32_t len, len2;
int v3 = (nfsd->nd_flag & ND_NFSV3);
struct mbuf *mb, *mreq;
@@ -2180,6 +2200,7 @@
}
if (error)
goto out;
+ abort = 1;
VATTR_NULL(&va);
va.va_type = VLNK;
if (v3) {
@@ -2244,7 +2265,9 @@
diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
}
vrele(dirp);
+ dirp = NULL;
}
+ abort = 0;
nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_POSTOPATTR(v3) +
NFSX_WCCDATA(v3));
if (v3) {
@@ -2256,13 +2279,15 @@
}
return (0);
nfsmout:
- VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- if (nd.ni_vp)
- vrele(nd.ni_vp);
+ if (abort) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (nd.ni_vp)
+ vrele(nd.ni_vp);
+ }
if (dirp)
vrele(dirp);
if (pathcp)
@@ -2288,6 +2313,7 @@
int32_t t1;
char *bpos;
int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1;
+ int abort = 0;
int v3 = (nfsd->nd_flag & ND_NFSV3);
char *cp2;
struct mbuf *mb, *mreq;
@@ -2312,6 +2338,7 @@
vrele(dirp);
return (0);
}
+ abort = 1;
VATTR_NULL(&va);
if (v3) {
va.va_mode = 0;
@@ -2347,7 +2374,9 @@
diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
}
vrele(dirp);
+ dirp = NULL;
}
+ abort = 0;
nfsm_reply(NFSX_SRVFH(&nsfh, v3) + NFSX_POSTOPATTR(v3) +
NFSX_WCCDATA(v3));
if (v3) {
@@ -2363,13 +2392,15 @@
}
return (0);
nfsmout:
- VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
- if (nd.ni_dvp == nd.ni_vp)
- vrele(nd.ni_dvp);
- else
- vput(nd.ni_dvp);
- if (nd.ni_vp)
- vrele(nd.ni_vp);
+ if (abort) {
+ VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+ if (nd.ni_dvp == nd.ni_vp)
+ vrele(nd.ni_dvp);
+ else
+ vput(nd.ni_dvp);
+ if (nd.ni_vp)
+ vrele(nd.ni_vp);
+ }
if (dirp)
vrele(dirp);
return (error);
@@ -3353,6 +3384,7 @@
u_quad_t frev;
nfsm_reply(0);
+nfsmout:
return (0);
}
@@ -3375,6 +3407,7 @@
else
error = EPROCUNAVAIL;
nfsm_reply(0);
+nfsmout:
return (0);
}
Index: src/sys/nfs/nfsm_subs.h
diff -u src/sys/nfs/nfsm_subs.h:1.50 src/sys/nfs/nfsm_subs.h:1.51
--- src/sys/nfs/nfsm_subs.h:1.50 Sun Mar 4 06:03:38 2007
+++ src/sys/nfs/nfsm_subs.h Fri Apr 10 18:58:50 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: nfsm_subs.h,v 1.50 2007/03/04 06:03:38 christos Exp $ */
+/* $NetBSD: nfsm_subs.h,v 1.51 2009/04/10 18:58:50 bouyer Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -444,8 +444,10 @@
} \
mreq = *mrq; \
if (error && (!(nfsd->nd_flag & ND_NFSV3) || \
- error == EBADRPC)) \
- return(0); \
+ error == EBADRPC)) {\
+ error = 0; \
+ goto nfsmout; \
+ } \
}
#define nfsm_writereply(s, v3) \