Module Name: src Committed By: dholland Date: Mon Apr 11 01:35:00 UTC 2011
Modified Files: src/sys/kern: vfs_lookup.c Log Message: ZZmsg To generate a diff of this commit: cvs rdiff -u -r1.133 -r1.134 src/sys/kern/vfs_lookup.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/vfs_lookup.c diff -u src/sys/kern/vfs_lookup.c:1.133 src/sys/kern/vfs_lookup.c:1.134 --- src/sys/kern/vfs_lookup.c:1.133 Mon Apr 11 01:33:04 2011 +++ src/sys/kern/vfs_lookup.c Mon Apr 11 01:35:00 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_lookup.c,v 1.133 2011/04/11 01:33:04 dholland Exp $ */ +/* $NetBSD: vfs_lookup.c,v 1.134 2011/04/11 01:35:00 dholland Exp $ */ /* * Copyright (c) 1982, 1986, 1989, 1993 @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.133 2011/04/11 01:33:04 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.134 2011/04/11 01:35:00 dholland Exp $"); #include "opt_magiclinks.h" @@ -591,7 +591,7 @@ * appropriate. */ static int -namei_start(struct namei_state *state, int isnfsd, struct vnode *forcecwd) +namei_start(struct namei_state *state, struct vnode *forcecwd) { struct nameidata *ndp = state->ndp; @@ -609,7 +609,7 @@ ndp->ni_loopcnt = 0; /* Get starting directory, set up root, and ktrace. */ - if (isnfsd) { + if (forcecwd != NULL) { state->namei_startdir = namei_getstartdir_for_nfsd(state, forcecwd); /* no ktrace */ @@ -645,7 +645,7 @@ * Follow a symlink. */ static inline int -namei_follow(struct namei_state *state) +namei_follow(struct namei_state *state, int inhibitmagic) { struct nameidata *ndp = state->ndp; struct componentname *cnp = state->cnp; @@ -690,8 +690,11 @@ /* * Do symlink substitution, if appropriate, and * check length for potential overflow. + * + * Inhibit symlink substitution for nfsd. + * XXX: This is how it was before; is that a bug or a feature? */ - if ((vfs_magiclinks && + if ((!inhibitmagic && vfs_magiclinks && symlink_magic(self->l_proc, cp, &linklen)) || (linklen + ndp->ni_pathlen >= MAXPATHLEN)) { PNBUF_PUT(cp); @@ -1230,7 +1233,8 @@ ////////////////////////////// static int -do_namei(struct namei_state *state) +do_namei(struct namei_state *state, struct vnode *forcecwd, + int neverfollow, int inhibitmagic) { int error; @@ -1253,7 +1257,7 @@ savepath = NULL; } - error = namei_start(state, 0/*not nfsd*/, NULL); + error = namei_start(state, forcecwd); if (error) { if (savepath != NULL) { pathbuf_stringcopy_put(ndp->ni_pathbuf, savepath); @@ -1302,7 +1306,11 @@ * aren't supposed to. */ if (namei_atsymlink(state)) { - error = namei_follow(state); + if (neverfollow) { + error = EINVAL; + } else { + error = namei_follow(state, inhibitmagic); + } if (error) { KASSERT(ndp->ni_dvp != ndp->ni_vp); vput(ndp->ni_dvp); @@ -1349,7 +1357,7 @@ int error; namei_init(&state, ndp); - error = do_namei(&state); + error = do_namei(&state, NULL, 0/*!neverfollow*/, 0/*!inhibitmagic*/); namei_cleanup(&state); return error; @@ -1366,122 +1374,70 @@ * affecting the other. */ -int -lookup_for_nfsd(struct nameidata *ndp, struct vnode *dp, int neverfollow) +static int +do_lookup_for_nfsd(struct namei_state *state, struct vnode *forcecwd, + int neverfollow, int inhibitmagic) { - struct namei_state state; int error; - struct iovec aiov; - struct uio auio; - int linklen; - char *cp; - - namei_init(&state, ndp); + struct nameidata *ndp = state->ndp; + //struct componentname *cnp = state->cnp; - namei_start(&state, 1/*nfsd*/, dp); + error = namei_start(state, forcecwd); + if (error) { + return error; + } for (;;) { - error = do_lookup(&state, dp); + error = do_lookup(state, state->namei_startdir); if (error) { - /* BEGIN from nfsd */ if (ndp->ni_dvp) { vput(ndp->ni_dvp); } - /* END from nfsd */ - namei_cleanup(&state); return error; } /* - * BEGIN wodge of code from nfsd - */ - - /* * Check for encountering a symbolic link */ - if ((state.cnp->cn_flags & ISSYMLINK) == 0) { - if ((state.cnp->cn_flags & LOCKPARENT) == 0 && state.ndp->ni_dvp) { - if (state.ndp->ni_dvp == state.ndp->ni_vp) { - vrele(state.ndp->ni_dvp); - } else { - vput(state.ndp->ni_dvp); - } - } - return (0); - } else { + if (namei_atsymlink(state)) { if (neverfollow) { error = EINVAL; - goto out; - } - if (state.ndp->ni_loopcnt++ >= MAXSYMLINKS) { - error = ELOOP; - goto out; - } - if (state.ndp->ni_vp->v_mount->mnt_flag & MNT_SYMPERM) { - error = VOP_ACCESS(ndp->ni_vp, VEXEC, state.cnp->cn_cred); - if (error != 0) - goto out; - } - cp = PNBUF_GET(); - aiov.iov_base = cp; - aiov.iov_len = MAXPATHLEN; - auio.uio_iov = &aiov; - auio.uio_iovcnt = 1; - auio.uio_offset = 0; - auio.uio_rw = UIO_READ; - auio.uio_resid = MAXPATHLEN; - UIO_SETUP_SYSSPACE(&auio); - error = VOP_READLINK(ndp->ni_vp, &auio, state.cnp->cn_cred); - if (error) { - PNBUF_PUT(cp); - goto out; - } - linklen = MAXPATHLEN - auio.uio_resid; - if (linklen == 0) { - PNBUF_PUT(cp); - error = ENOENT; - goto out; - } - if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { - PNBUF_PUT(cp); - error = ENAMETOOLONG; - goto out; - } - if (ndp->ni_pathlen > 1) { - /* includes a null-terminator */ - memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen); } else { - cp[linklen] = '\0'; + error = namei_follow(state, inhibitmagic); } - state.ndp->ni_pathlen += linklen; - memcpy(state.ndp->ni_pnbuf, cp, state.ndp->ni_pathlen); - PNBUF_PUT(cp); - vput(state.ndp->ni_vp); - dp = state.ndp->ni_dvp; - - /* - * Check if root directory should replace current directory. - */ - if (state.ndp->ni_pnbuf[0] == '/') { - vput(dp); - dp = ndp->ni_rootdir; - vref(dp); - vn_lock(dp, LK_EXCLUSIVE | LK_RETRY); + if (error) { + KASSERT(ndp->ni_dvp != ndp->ni_vp); + vput(state->ndp->ni_vp); + vput(state->ndp->ni_dvp); + state->ndp->ni_vp = NULL; + return error; } + } else { + break; } + } + if ((state->cnp->cn_flags & LOCKPARENT) == 0 && state->ndp->ni_dvp) { + if (state->ndp->ni_dvp == state->ndp->ni_vp) { + vrele(state->ndp->ni_dvp); + } else { + vput(state->ndp->ni_dvp); + } } - out: - vput(state.ndp->ni_vp); - vput(state.ndp->ni_dvp); - state.ndp->ni_vp = NULL; + return (0); +} - /* - * END wodge of code from nfsd - */ +int +lookup_for_nfsd(struct nameidata *ndp, struct vnode *dp, int neverfollow) +{ + struct namei_state state; + int error; + + namei_init(&state, ndp); + error = do_lookup_for_nfsd(&state, dp, neverfollow, 1/*inhibitmagic*/); namei_cleanup(&state); return error;