Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Move a big wodge of symlink-following code from nfsd to inside



details:   https://anonhg.NetBSD.org/src/rev/c6d59022fb64
branches:  trunk
changeset: 747693:c6d59022fb64
user:      dholland <dholland%NetBSD.org@localhost>
date:      Sun Sep 27 17:23:53 2009 +0000

description:
Move a big wodge of symlink-following code from nfsd to inside
lookup_for_nfsd(). This code is, or at least should be, the same as
the regular symlink-following code plus an extra flag nfsd needs.

The two lots of code can/will be merged in the future.

diffstat:

 share/man/man9/namei.9 |   20 ++++--
 sys/kern/vfs_lookup.c  |  136 +++++++++++++++++++++++++++++++++++++++++++++++-
 sys/nfs/nfs_srvsubs.c  |  109 ++------------------------------------
 sys/sys/namei.src      |    4 +-
 4 files changed, 155 insertions(+), 114 deletions(-)

diffs (truncated from 379 to 300 lines):

diff -r efa4a6175d56 -r c6d59022fb64 share/man/man9/namei.9
--- a/share/man/man9/namei.9    Sun Sep 27 17:21:22 2009 +0000
+++ b/share/man/man9/namei.9    Sun Sep 27 17:23:53 2009 +0000
@@ -1,4 +1,4 @@
-.\"     $NetBSD: namei.9,v 1.22 2009/09/27 17:19:07 dholland Exp $
+.\"     $NetBSD: namei.9,v 1.23 2009/09/27 17:23:53 dholland Exp $
 .\"
 .\" Copyright (c) 2001, 2005, 2006 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -46,7 +46,8 @@
 .Ft int
 .Fn namei "struct nameidata *ndp"
 .Ft int
-.Fn lookup_for_nfsd "struct nameidata *ndp"
+.Fn lookup_for_nfsd "struct nameidata *ndp" "struct vnode *startdir" \
+"int neverfollow"
 .Ft int
 .Fn lookup_for_nfsd_index "struct nameidata *ndp"
 .Ft int
@@ -288,11 +289,19 @@
 is comparable to the historic
 .Fn lookup
 but this code is slated for refactoring.
-.It Fn lookup_for_nfsd "ndp"
+.It Fn lookup_for_nfsd "ndp" "startdir" "neverfollow"
 This is a private entry point into
 .Nm
 used by the NFS server code.
-Its semantics are similar to the historic
+It looks up a path starting from
+.Fa startdir .
+If
+.Fa neverfollow
+is set,
+.Em any
+symbolic link (not just at the end of the path) will cause an error.
+Otherwise, it follows symlinks normally.
+Its semantics are similar to a symlink-following loop around the historic
 .Fn lookup
 function described above.
 It should not be used by new code.
@@ -304,9 +313,6 @@
 .Fn lookup
 function described above.
 It should not be used by new code.
-(For now it differs from the preceding private entry point in that it
-has a different call site with a different context and different
-custom initialization of what ought to be private namei state.)
 .It Fn relookup "dvp" "vpp" "cnp"
 Reacquire a path name component is a directory.
 This is a quicker way to lookup a pathname component when the parent
diff -r efa4a6175d56 -r c6d59022fb64 sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c     Sun Sep 27 17:21:22 2009 +0000
+++ b/sys/kern/vfs_lookup.c     Sun Sep 27 17:23:53 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vfs_lookup.c,v 1.119 2009/09/27 17:19:07 dholland Exp $        */
+/*     $NetBSD: vfs_lookup.c,v 1.120 2009/09/27 17:23:54 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.119 2009/09/27 17:19:07 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.120 2009/09/27 17:23:54 dholland Exp $");
 
 #include "opt_magiclinks.h"
 
@@ -1158,14 +1158,144 @@
  */
 
 int
-lookup_for_nfsd(struct nameidata *ndp)
+lookup_for_nfsd(struct nameidata *ndp, struct vnode *dp, int neverfollow)
 {
        struct namei_state state;
        int error;
 
+       struct iovec aiov;
+       struct uio auio;
+       int linklen;
+       char *cp;
+
        /* For now at least we don't have to frob the state */
        namei_init(&state, ndp);
+
+       /*
+        * BEGIN wodge of code from nfsd
+        */
+
+       VREF(dp);
+       vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
+
+    for (;;) {
+
+       state.cnp->cn_nameptr = state.cnp->cn_pnbuf;
+       state.ndp->ni_startdir = dp;
+
+       /*
+        * END wodge of code from nfsd
+        */
+
        error = do_lookup(&state);
+       if (error) {
+               /* BEGIN from nfsd */
+               if (ndp->ni_dvp) {
+                       vput(ndp->ni_dvp);
+               }
+               PNBUF_PUT(state.cnp->cn_pnbuf);
+               /* 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);
+                       }
+               }
+               if (state.cnp->cn_flags & (SAVENAME | SAVESTART)) {
+                       state.cnp->cn_flags |= HASBUF;
+               } else {
+                       PNBUF_PUT(state.cnp->cn_pnbuf);
+#if defined(DIAGNOSTIC)
+                       state.cnp->cn_pnbuf = NULL;
+#endif /* defined(DIAGNOSTIC) */
+               }
+               return (0);
+       } else {
+               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;
+               }
+               if (state.ndp->ni_pathlen > 1)
+                       cp = PNBUF_GET();
+               else
+                       cp = state.cnp->cn_pnbuf;
+               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) {
+badlink:
+                       if (ndp->ni_pathlen > 1)
+                               PNBUF_PUT(cp);
+                       goto out;
+               }
+               linklen = MAXPATHLEN - auio.uio_resid;
+               if (linklen == 0) {
+                       error = ENOENT;
+                       goto badlink;
+               }
+               if (linklen + ndp->ni_pathlen >= MAXPATHLEN) {
+                       error = ENAMETOOLONG;
+                       goto badlink;
+               }
+               if (ndp->ni_pathlen > 1) {
+                       memcpy(cp + linklen, ndp->ni_next, ndp->ni_pathlen);
+                       PNBUF_PUT(state.cnp->cn_pnbuf);
+                       state.cnp->cn_pnbuf = cp;
+               } else
+                       state.cnp->cn_pnbuf[linklen] = '\0';
+               state.ndp->ni_pathlen += linklen;
+               vput(state.ndp->ni_vp);
+               dp = state.ndp->ni_dvp;
+
+               /*
+                * Check if root directory should replace current directory.
+                */
+               if (state.cnp->cn_pnbuf[0] == '/') {
+                       vput(dp);
+                       dp = ndp->ni_rootdir;
+                       VREF(dp);
+                       vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
+               }
+       }
+
+    }
+ out:
+       vput(state.ndp->ni_vp);
+       vput(state.ndp->ni_dvp);
+       state.ndp->ni_vp = NULL;
+       PNBUF_PUT(state.cnp->cn_pnbuf);
+
+       /*
+        * END wodge of code from nfsd
+        */
        namei_cleanup(&state);
 
        return error;
diff -r efa4a6175d56 -r c6d59022fb64 sys/nfs/nfs_srvsubs.c
--- a/sys/nfs/nfs_srvsubs.c     Sun Sep 27 17:21:22 2009 +0000
+++ b/sys/nfs/nfs_srvsubs.c     Sun Sep 27 17:23:53 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: nfs_srvsubs.c,v 1.4 2009/09/27 17:19:07 dholland Exp $ */
+/*     $NetBSD: nfs_srvsubs.c,v 1.5 2009/09/27 17:23:54 dholland Exp $ */
 
 /*
  * Copyright (c) 1989, 1993
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.4 2009/09/27 17:19:07 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_srvsubs.c,v 1.5 2009/09/27 17:23:54 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -121,10 +121,9 @@
        int i, rem;
        struct mbuf *md;
        char *fromcp, *tocp, *cp;
-       struct iovec aiov;
-       struct uio auio;
        struct vnode *dp;
-       int error, rdonly, linklen;
+       int error, rdonly;
+       int neverfollow;
        struct componentname *cnp = &ndp->ni_cnd;
 
        *retdirp = NULL;
@@ -254,111 +253,17 @@
                cnp->cn_flags |= NOCROSSMOUNT;
        }
 
-       VREF(dp);
-       vn_lock(dp, LK_EXCLUSIVE | LK_RETRY);
-
-    for (;;) {
-       cnp->cn_nameptr = cnp->cn_pnbuf;
-       ndp->ni_startdir = dp;
+       neverfollow = !pubflag;
 
        /*
         * And call lookup() to do the real work
         */
-       error = lookup_for_nfsd(ndp);
+       error = lookup_for_nfsd(ndp, dp, neverfollow);
        if (error) {
-               if (ndp->ni_dvp) {
-                       vput(ndp->ni_dvp);
-               }
-               PNBUF_PUT(cnp->cn_pnbuf);
                return (error);
        }
+       return 0;
 
-       /*
-        * Check for encountering a symbolic link
-        */
-       if ((cnp->cn_flags & ISSYMLINK) == 0) {
-               if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp) {
-                       if (ndp->ni_dvp == ndp->ni_vp) {
-                               vrele(ndp->ni_dvp);
-                       } else {
-                               vput(ndp->ni_dvp);
-                       }
-               }
-               if (cnp->cn_flags & (SAVENAME | SAVESTART)) {
-                       cnp->cn_flags |= HASBUF;
-               } else {
-                       PNBUF_PUT(cnp->cn_pnbuf);
-#if defined(DIAGNOSTIC)
-                       cnp->cn_pnbuf = NULL;
-#endif /* defined(DIAGNOSTIC) */
-               }
-               return (0);
-       } else {
-               if (!pubflag) {
-                       error = EINVAL;
-                       break;
-               }
-               if (ndp->ni_loopcnt++ >= MAXSYMLINKS) {
-                       error = ELOOP;
-                       break;



Home | Main Index | Thread Index | Old Index