Merge from vendor branch ZLIB:
[dragonfly.git] / sys / kern / vfs_nlookup.c
1 /*
2  * Copyright (c) 2004 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  * 
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  * 
34  * $DragonFly: src/sys/kern/vfs_nlookup.c,v 1.6 2004/10/07 20:18:33 dillon Exp $
35  */
36 /*
37  * nlookup() is the 'new' namei interface.  Rather then return directory and
38  * leaf vnodes (in various lock states) the new interface instead deals in
39  * namecache records.  Namecache records may represent both a positive or
40  * a negative hit.  The namespace is locked via the namecache record instead
41  * of via the vnode, and only the leaf namecache record (representing the
42  * filename) needs to be locked.
43  *
44  * This greatly improves filesystem parallelism and is a huge simplification
45  * of the API verses the old vnode locking / namei scheme.
46  *
47  * Filesystems must actively control the caching aspects of the namecache,
48  * and since namecache pointers are used as handles they are non-optional
49  * even for filesystems which do not generally wish to cache things.  It is
50  * intended that a separate cache coherency API will be constructed to handle
51  * these issues.
52  */
53
54 #include "opt_ktrace.h"
55
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/kernel.h>
59 #include <sys/vnode.h>
60 #include <sys/mount.h>
61 #include <sys/filedesc.h>
62 #include <sys/proc.h>
63 #include <sys/namei.h>
64 #include <sys/nlookup.h>
65 #include <sys/malloc.h>
66 #include <sys/stat.h>
67 #include <vm/vm_zone.h>
68
69 #ifdef KTRACE
70 #include <sys/ktrace.h>
71 #endif
72
73 /*
74  * Initialize a nlookup() structure, early error return for copyin faults
75  * or a degenerate empty string (which is not allowed).
76  */
77 int
78 nlookup_init(struct nlookupdata *nd, 
79              const char *path, enum uio_seg seg, int flags)
80 {
81     size_t pathlen;
82     struct proc *p;
83     thread_t td;
84     int error;
85
86     td = curthread;
87     p = td->td_proc;
88
89     /*
90      * note: the pathlen set by copy*str() includes the terminating \0.
91      */
92     bzero(nd, sizeof(struct nlookupdata));
93     nd->nl_path = zalloc(namei_zone);
94     nd->nl_flags |= NLC_HASBUF;
95     if (seg == UIO_SYSSPACE) 
96         error = copystr(path, nd->nl_path, MAXPATHLEN, &pathlen);
97     else
98         error = copyinstr(path, nd->nl_path, MAXPATHLEN, &pathlen);
99
100     /*
101      * Don't allow empty pathnames.
102      * POSIX.1 requirement: "" is not a vaild file name.
103      */
104     if (error == 0 && pathlen <= 1)
105         error = ENOENT;
106
107     if (error == 0) {
108         if (p && p->p_fd) {
109             nd->nl_ncp = cache_hold(p->p_fd->fd_ncdir);
110             nd->nl_rootncp = cache_hold(p->p_fd->fd_nrdir);
111             if (p->p_fd->fd_njdir)
112                 nd->nl_jailncp = cache_hold(p->p_fd->fd_njdir);
113             nd->nl_cred = crhold(p->p_ucred);
114         } else {
115             nd->nl_ncp = cache_hold(rootncp);
116             nd->nl_rootncp = cache_hold(nd->nl_ncp);
117             nd->nl_jailncp = cache_hold(nd->nl_ncp);
118             nd->nl_cred = crhold(proc0.p_ucred);
119         }
120         nd->nl_td = td;
121         nd->nl_flags |= flags;
122     } else {
123         nlookup_done(nd);
124     }
125     return(error);
126 }
127
128 /*
129  * Cleanup a nlookupdata structure after we are through with it.  This may
130  * be called on any nlookupdata structure initialized with nlookup_init().
131  * Calling nlookup_done() is mandatory in all cases except where nlookup_init()
132  * returns an error, even if as a consumer you believe you have taken all
133  * dynamic elements out of the nlookupdata structure.
134  */
135 void
136 nlookup_done(struct nlookupdata *nd)
137 {
138     if (nd->nl_ncp) {
139         if (nd->nl_flags & NLC_NCPISLOCKED) {
140             nd->nl_flags &= ~NLC_NCPISLOCKED;
141             cache_unlock(nd->nl_ncp);
142         }
143         cache_drop(nd->nl_ncp);
144         nd->nl_ncp = NULL;
145     }
146     if (nd->nl_rootncp) {
147         cache_drop(nd->nl_rootncp);
148         nd->nl_rootncp = NULL;
149     }
150     if (nd->nl_jailncp) {
151         cache_drop(nd->nl_jailncp);
152         nd->nl_jailncp = NULL;
153     }
154     if ((nd->nl_flags & NLC_HASBUF) && nd->nl_path) {
155         zfree(namei_zone, nd->nl_path);
156         nd->nl_path = NULL;
157     }
158     if (nd->nl_cred) {
159         crfree(nd->nl_cred);
160         nd->nl_cred = NULL;
161     }
162     nd->nl_flags = 0;
163 }
164
165 /*
166  * Simple all-in-one nlookup.  Returns a locked namecache structure or NULL
167  * if an error occured. 
168  *
169  * Note that the returned ncp is not checked for permissions, though VEXEC
170  * is checked on the directory path leading up to the result.  The caller
171  * must call naccess() to check the permissions of the returned leaf.
172  */
173 struct namecache *
174 nlookup_simple(const char *str, enum uio_seg seg,
175                int niflags, int *error)
176 {
177     struct nlookupdata nd;
178     struct namecache *ncp;
179
180     *error = nlookup_init(&nd, str, seg, niflags);
181     if (*error == 0) {
182             if ((*error = nlookup(&nd)) == 0) {
183                     ncp = nd.nl_ncp;    /* keep hold ref from structure */
184                     nd.nl_ncp = NULL;   /* and NULL out */
185             } else {
186                     ncp = NULL;
187             }
188             nlookup_done(&nd);
189     } else {
190             ncp = NULL;
191     }
192     return(ncp);
193 }
194
195 /*
196  * Do a generic nlookup.  Note that the passed nd is not nlookup_done()'d
197  * on return, even if an error occurs.  If no error occurs the returned
198  * nl_ncp is always referenced and locked, otherwise it may or may not be.
199  *
200  * Intermediate directory elements, including the current directory, require
201  * execute (search) permission.  nlookup does not examine the access 
202  * permissions on the returned element.
203  */
204 int
205 nlookup(struct nlookupdata *nd)
206 {
207     struct nlcomponent nlc;
208     struct namecache *ncp;
209     char *ptr;
210     int error;
211     int len;
212
213 #ifdef KTRACE
214     if (KTRPOINT(nd->nl_td, KTR_NAMEI))
215         ktrnamei(nd->nl_td->td_proc->p_tracep, nd->nl_path);
216 #endif
217     bzero(&nlc, sizeof(nlc));
218
219     /*
220      * Setup for the loop.  The current working namecache element must
221      * be in a refd + unlocked state.  This typically the case on entry except
222      * when stringing nlookup()'s along in a chain, since nlookup() always
223      * returns nl_ncp in a locked state.
224      */
225     nd->nl_loopcnt = 0;
226     if (nd->nl_flags & NLC_NCPISLOCKED) {
227         nd->nl_flags &= ~NLC_NCPISLOCKED;
228         cache_unlock(nd->nl_ncp);
229     }
230     ptr = nd->nl_path;
231
232     /*
233      * Loop on the path components.  At the top of the loop nd->nl_ncp
234      * is ref'd and unlocked and represents our current position.
235      */
236     for (;;) {
237         /*
238          * Check if the root directory should replace the current
239          * directory.  This is done at the start of a translation
240          * or after a symbolic link has been found.  In other cases
241          * ptr will never be pointing at a '/'.
242          */
243         if (*ptr == '/') {
244             do {
245                 ++ptr;
246             } while (*ptr == '/');
247             ncp = cache_hold(nd->nl_rootncp);
248             cache_drop(nd->nl_ncp);
249             nd->nl_ncp = ncp;
250             if (*ptr == 0) {
251                 cache_lock(nd->nl_ncp);
252                 nd->nl_flags |= NLC_NCPISLOCKED;
253                 error = 0;
254                 break;
255             }
256             continue;
257         }
258
259         /*
260          * Check directory search permissions
261          */
262         if ((error = naccess(nd->nl_ncp, VEXEC, nd->nl_cred)) != 0)
263             break;
264
265         /*
266          * Extract the path component
267          */
268         nlc.nlc_nameptr = ptr;
269         while (*ptr && *ptr != '/')
270             ++ptr;
271         nlc.nlc_namelen = ptr - nlc.nlc_nameptr;
272
273         /*
274          * Lookup the path component in the cache, creating an unresolved
275          * entry if necessary.  We have to handle "." and ".." as special
276          * cases.
277          *
278          * When handling ".." we have to detect a traversal back through a
279          * mount point and skip the mount-under node.  If we are at the root
280          * ".." just returns the root.
281          *
282          * This subsection returns a locked, refd 'ncp'.
283          */
284         if (nlc.nlc_namelen == 1 && nlc.nlc_nameptr[0] == '.') {
285             ncp = cache_get(nd->nl_ncp);
286         } else if (nlc.nlc_namelen == 2 && 
287                    nlc.nlc_nameptr[0] == '.' && nlc.nlc_nameptr[1] == '.') {
288             ncp = nd->nl_ncp;
289             if (ncp == nd->nl_rootncp) {
290                 ncp = cache_get(ncp);
291             } else {
292                 while ((ncp->nc_flag & NCF_MOUNTPT) && ncp != nd->nl_rootncp) {
293                     /* ignore NCF_REVALPARENT on a mount point */
294                     ncp = ncp->nc_parent;       /* get to underlying node */
295                     KKASSERT(ncp != NULL && 1);
296                 }
297                 if (ncp->nc_flag & NCF_REVALPARENT) {
298                     printf("[diagnostic] nlookup can't .. past a renamed directory: %*.*s\n", ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
299                     error = EINVAL;
300                     break;
301                 }
302                 if (ncp != nd->nl_rootncp)
303                         ncp = ncp->nc_parent;
304                 KKASSERT(ncp != NULL && 2);
305                 ncp = cache_get(ncp);
306             }
307         } else {
308             ncp = cache_nlookup(nd->nl_ncp, &nlc);
309             while ((error = cache_resolve(ncp, nd->nl_cred)) == EAGAIN) {
310                 printf("[diagnostic] nlookup: relookup %*.*s\n", 
311                         ncp->nc_nlen, ncp->nc_nlen, ncp->nc_name);
312                 cache_put(ncp);
313                 ncp = cache_nlookup(nd->nl_ncp, &nlc);
314             }
315         }
316         /*
317          * [end of subsection] ncp is locked and ref'd.  nd->nl_ncp is ref'd
318          */
319
320         /*
321          * Resolve the namespace if necessary.  The ncp returned by
322          * cache_nlookup() is referenced and locked.
323          *
324          * XXX neither '.' nor '..' should return EAGAIN since they were
325          * previously resolved and thus cannot be newly created ncp's.
326          */
327         if (ncp->nc_flag & NCF_UNRESOLVED) {
328             error = cache_resolve(ncp, nd->nl_cred);
329             KKASSERT(error != EAGAIN);
330         } else {
331             error = ncp->nc_error;
332         }
333
334         /*
335          * Early completion
336          */
337         if (error) {
338             cache_put(ncp);
339             break;
340         }
341
342         /*
343          * If the element is a symlink and it is either not the last
344          * element or it is the last element and we are allowed to
345          * follow symlinks, resolve the symlink.
346          */
347         if ((ncp->nc_flag & NCF_ISSYMLINK) &&
348             (*ptr || (nd->nl_flags & NLC_FOLLOW))
349         ) {
350             if (nd->nl_loopcnt++ >= MAXSYMLINKS) {
351                 error = ELOOP;
352                 cache_put(ncp);
353                 break;
354             }
355             error = nreadsymlink(nd, ncp, &nlc);
356             cache_put(ncp);
357             if (error)
358                 break;
359
360             /*
361              * Concatenate trailing path elements onto the returned symlink.
362              * Note that if the path component (ptr) is not exhausted, it
363              * will being with a '/', so we do not have to add another one.
364              *
365              * The symlink may not be empty.
366              */
367             len = strlen(ptr);
368             if (nlc.nlc_namelen == 0 || nlc.nlc_namelen + len >= MAXPATHLEN) {
369                 error = nlc.nlc_namelen ? ENAMETOOLONG : ENOENT;
370                 zfree(namei_zone, nlc.nlc_nameptr);
371                 break;
372             }
373             bcopy(ptr, nlc.nlc_nameptr + nlc.nlc_namelen, len + 1);
374             if (nd->nl_flags & NLC_HASBUF)
375                 zfree(namei_zone, nd->nl_path);
376             nd->nl_path = nlc.nlc_nameptr;
377             nd->nl_flags |= NLC_HASBUF;
378             ptr = nd->nl_path;
379
380             /*
381              * Go back up to the top to resolve any initial '/'s in the
382              * symlink.
383              */
384             continue;
385         }
386
387         /*
388          * If the element is a directory and we are crossing a mount point,
389          * retrieve the root of the mounted filesystem from mnt_ncp and
390          * resolve it if necessary.
391          *
392          * XXX mnt_ncp should really be resolved in the mount code.
393          * NOTE!  the normal nresolve() code cannot resolve mount point ncp's!
394          *
395          * XXX NOCROSSMOUNT
396          */
397         while ((ncp->nc_flag & NCF_ISDIR) && ncp->nc_vp->v_mountedhere &&
398                 (nd->nl_flags & NLC_NOCROSSMOUNT) == 0
399         ) {
400             struct mount *mp;
401             struct vnode *tdp;
402
403             mp = ncp->nc_vp->v_mountedhere;
404             cache_put(ncp);
405             ncp = cache_get(mp->mnt_ncp);
406
407             if (ncp->nc_flag & NCF_UNRESOLVED) {
408                 while (vfs_busy(mp, 0, NULL, nd->nl_td))
409                     ;
410                 error = VFS_ROOT(mp, &tdp);
411                 vfs_unbusy(mp, nd->nl_td);
412                 if (error)
413                     break;
414                 cache_setvp(ncp, tdp);
415                 vput(tdp);
416             }
417         }
418         if (error) {
419             cache_put(ncp);
420             break;
421         }
422             
423         /*
424          * Skip any slashes to get to the next element.  If there 
425          * are any slashes at all the current element must be a
426          * directory.  If it isn't we break without incrementing
427          * ptr and fall through to the failure case below.
428          */
429         while (*ptr == '/') {
430             if ((ncp->nc_flag & NCF_ISDIR) == 0)
431                 break;
432             ++ptr;
433         }
434
435         /*
436          * Continuation case: additional elements and the current
437          * element is a directory.
438          */
439         if (*ptr && (ncp->nc_flag & NCF_ISDIR)) {
440             cache_drop(nd->nl_ncp);
441             cache_unlock(ncp);
442             nd->nl_ncp = ncp;
443             continue;
444         }
445
446         /*
447          * Failure case: additional elements and the current element
448          * is not a directory
449          */
450         if (*ptr) {
451             cache_put(ncp);
452             error = ENOTDIR;
453             break;
454         }
455
456         /*
457          * XXX vnode canvmio (test in mmap(), read(), and write())
458          */
459
460         /*
461          * Termination: no more elements.
462          */
463         cache_drop(nd->nl_ncp);
464         nd->nl_ncp = ncp;
465         nd->nl_flags |= NLC_NCPISLOCKED;
466         error = 0;
467         break;
468     }
469     return(error);
470 }
471
472 /*
473  * Resolve a mount point's glue ncp.  This ncp connects creates the illusion
474  * of continuity in the namecache tree by connecting the ncp related to the
475  * vnode under the mount to the ncp related to the mount's root vnode.
476  *
477  * If no error occured a locked, ref'd ncp is stored in *ncpp.
478  */
479 int
480 nlookup_mp(struct mount *mp, struct namecache **ncpp)
481 {
482     struct namecache *ncp;
483     struct vnode *vp;
484     int error;
485
486     error = 0;
487     ncp = mp->mnt_ncp;
488     cache_get(ncp);
489     if (ncp->nc_flag & NCF_UNRESOLVED) {
490         while (vfs_busy(mp, 0, NULL, curthread))
491             ;
492         error = VFS_ROOT(mp, &vp);
493         vfs_unbusy(mp, curthread);
494         if (error) {
495             cache_put(ncp);
496             ncp = NULL;
497         } else {
498             cache_setvp(ncp, vp);
499             vput(vp);
500         }
501     }
502     *ncpp = ncp;
503     return(error);
504 }
505
506 /*
507  * Read the contents of a symlink, allocate a path buffer out of the
508  * namei_zone and initialize the supplied nlcomponent with the result.
509  *
510  * If an error occurs no buffer will be allocated or returned in the nlc.
511  */
512 int
513 nreadsymlink(struct nlookupdata *nd, struct namecache *ncp, 
514                 struct nlcomponent *nlc)
515 {
516     struct vnode *vp;
517     struct iovec aiov;
518     struct uio auio;
519     int linklen;
520     int error;
521     char *cp;
522
523     nlc->nlc_nameptr = NULL;
524     nlc->nlc_namelen = 0;
525     if (ncp->nc_vp == NULL)
526         return(ENOENT);
527     if ((error = cache_vget(ncp, nd->nl_cred, LK_SHARED, &vp)) != 0)
528         return(error);
529     cp = zalloc(namei_zone);
530     aiov.iov_base = cp;
531     aiov.iov_len = MAXPATHLEN;
532     auio.uio_iov = &aiov;
533     auio.uio_iovcnt = 1;
534     auio.uio_offset = 0;
535     auio.uio_rw = UIO_READ;
536     auio.uio_segflg = UIO_SYSSPACE;
537     auio.uio_td = nd->nl_td;
538     auio.uio_resid = MAXPATHLEN - 1;
539     error = VOP_READLINK(vp, &auio, nd->nl_cred);
540     if (error)
541         goto fail;
542     linklen = MAXPATHLEN - 1 - auio.uio_resid;
543     if (varsym_enable) {
544         linklen = varsymreplace(cp, linklen, MAXPATHLEN - 1);
545         if (linklen < 0) {
546             error = ENAMETOOLONG;
547             goto fail;
548         }
549     }
550     cp[linklen] = 0;
551     nlc->nlc_nameptr = cp;
552     nlc->nlc_namelen = linklen;
553     vput(vp);
554     return(0);
555 fail:
556     zfree(namei_zone, cp);
557     vput(vp);
558     return(error);
559 }
560
561 /*
562  * Check access [XXX cache vattr!] [XXX quota]
563  *
564  * Generally check the V* access bits from sys/vnode.h.  All specified bits
565  * must pass for this function to return 0.
566  *
567  * If VCREATE is specified and the target ncp represents a non-existant
568  * file or dir, or if VDELETE is specified and the target exists, the parent
569  * directory is checked for VWRITE.  If VEXCL is specified and the target
570  * ncp represents a positive hit, an error is returned.
571  *
572  * If VCREATE is not specified and the target does not exist (negative hit),
573  * ENOENT is returned.  Note that nlookup() does not (and should not) return
574  * ENOENT for non-existant leafs.
575  *
576  * The passed ncp may or may not be locked.  The caller should use a
577  * locked ncp on leaf lookups, especially for VCREATE, VDELETE, and VEXCL
578  * checks.
579  */
580 int
581 naccess(struct namecache *ncp, int vmode, struct ucred *cred)
582 {
583     struct namecache *par;
584     struct vnode *vp;
585     struct vattr va;
586     int error;
587
588     if (ncp->nc_flag & NCF_UNRESOLVED) {
589         cache_lock(ncp);
590         cache_resolve(ncp, cred);
591         cache_unlock(ncp);
592     }
593     error = ncp->nc_error;
594     if (vmode & (VDELETE|VCREATE|VEXCL)) {
595         if (((vmode & VCREATE) && ncp->nc_vp == NULL) ||
596             ((vmode & VDELETE) && ncp->nc_vp != NULL)
597         ) {
598             if ((par = ncp->nc_parent) == NULL) {
599                 if (error != EAGAIN)
600                         error = EROFS;
601             } else {
602                 cache_hold(par);
603                 error = naccess(par, VWRITE, cred);
604                 cache_drop(par);
605             }
606         }
607         if ((vmode & VEXCL) && ncp->nc_vp != NULL)
608             error = EEXIST;
609     }
610     if (error == 0) {
611         error = cache_vget(ncp, cred, LK_SHARED, &vp);
612         if (error == ENOENT) {
613             if (vmode & VCREATE)
614                 error = 0;
615         } else if (error == 0) {
616             /* XXX cache the va in the namecache or in the vnode */
617             if ((error = VOP_GETATTR(vp, &va, curthread)) == 0) {
618                 if ((vmode & VWRITE) && vp->v_mount) {
619                     if (vp->v_mount->mnt_flag & MNT_RDONLY)
620                         error = EROFS;
621                 }
622             }
623             vput(vp);
624             if (error == 0)
625                 error = naccess_va(&va, vmode, cred);
626         }
627     }
628     return(error);
629 }
630
631 /*
632  * Check the requested access against the given vattr using cred.
633  */
634 int
635 naccess_va(struct vattr *va, int vmode, struct ucred *cred)
636 {
637     int i;
638
639     /*
640      * Test the immutable bit for files, directories, and softlinks.
641      */
642     if (vmode & (VWRITE|VDELETE)) {
643         if (va->va_type == VDIR || va->va_type == VLNK || va->va_type == VREG) {
644             if (va->va_flags & IMMUTABLE)
645                 return (EPERM);
646         }
647     }
648
649     /*
650      * root gets universal access
651      */
652     if (cred->cr_uid == 0)
653         return(0);
654
655     /*
656      * Check owner perms, group perms, and world perms
657      */
658     vmode &= S_IRWXU;
659     if (cred->cr_uid == va->va_uid) {
660         if ((vmode & va->va_mode) != vmode)
661             return(EACCES);
662         return(0);
663     }
664
665     vmode >>= 3;
666     for (i = 0; i < cred->cr_ngroups; ++i) {
667         if (va->va_gid == cred->cr_groups[i]) {
668             if ((vmode & va->va_mode) != vmode)
669                 return(EACCES);
670             return(0);
671         }
672     }
673
674     vmode >>= 3;
675     if ((vmode & va->va_mode) != vmode)
676         return(EACCES);
677     return(0);
678 }
679