| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: vfs_lookup.c,v 1.218 2020/04/21 21:42:47 ad Exp $ */ | | 1 | /* $NetBSD: vfs_lookup.c,v 1.219 2020/04/22 21:35:52 ad Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1982, 1986, 1989, 1993 | | 4 | * Copyright (c) 1982, 1986, 1989, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * (c) UNIX System Laboratories, Inc. | | 6 | * (c) UNIX System Laboratories, Inc. |
7 | * All or some portions of this file are derived from material licensed | | 7 | * All or some portions of this file are derived from material licensed |
8 | * to the University of California by American Telephone and Telegraph | | 8 | * to the University of California by American Telephone and Telegraph |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
10 | * the permission of UNIX System Laboratories, Inc. | | 10 | * the permission of UNIX System Laboratories, Inc. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -27,27 +27,27 @@ | | | @@ -27,27 +27,27 @@ |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | * SUCH DAMAGE. | | 34 | * SUCH DAMAGE. |
35 | * | | 35 | * |
36 | * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95 | | 36 | * @(#)vfs_lookup.c 8.10 (Berkeley) 5/27/95 |
37 | */ | | 37 | */ |
38 | | | 38 | |
39 | #include <sys/cdefs.h> | | 39 | #include <sys/cdefs.h> |
40 | __KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.218 2020/04/21 21:42:47 ad Exp $"); | | 40 | __KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.219 2020/04/22 21:35:52 ad Exp $"); |
41 | | | 41 | |
42 | #ifdef _KERNEL_OPT | | 42 | #ifdef _KERNEL_OPT |
43 | #include "opt_magiclinks.h" | | 43 | #include "opt_magiclinks.h" |
44 | #endif | | 44 | #endif |
45 | | | 45 | |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/systm.h> | | 47 | #include <sys/systm.h> |
48 | #include <sys/kernel.h> | | 48 | #include <sys/kernel.h> |
49 | #include <sys/syslimits.h> | | 49 | #include <sys/syslimits.h> |
50 | #include <sys/time.h> | | 50 | #include <sys/time.h> |
51 | #include <sys/namei.h> | | 51 | #include <sys/namei.h> |
52 | #include <sys/vnode.h> | | 52 | #include <sys/vnode.h> |
53 | #include <sys/vnode_impl.h> | | 53 | #include <sys/vnode_impl.h> |
| @@ -1276,72 +1276,79 @@ lookup_fastforward(struct namei_state *s | | | @@ -1276,72 +1276,79 @@ lookup_fastforward(struct namei_state *s |
1276 | | | 1276 | |
1277 | /* | | 1277 | /* |
1278 | * Get the next component name. There should be no slashes | | 1278 | * Get the next component name. There should be no slashes |
1279 | * here, and we shouldn't have looped around if we were | | 1279 | * here, and we shouldn't have looped around if we were |
1280 | * done. | | 1280 | * done. |
1281 | */ | | 1281 | */ |
1282 | KASSERT(cnp->cn_nameptr[0] != '/'); | | 1282 | KASSERT(cnp->cn_nameptr[0] != '/'); |
1283 | KASSERT(cnp->cn_nameptr[0] != '\0'); | | 1283 | KASSERT(cnp->cn_nameptr[0] != '\0'); |
1284 | if ((error = lookup_parsepath(state)) != 0) { | | 1284 | if ((error = lookup_parsepath(state)) != 0) { |
1285 | break; | | 1285 | break; |
1286 | } | | 1286 | } |
1287 | | | 1287 | |
1288 | /* | | 1288 | /* |
1289 | * Can't deal with dotdot lookups, because it means lock | | 1289 | * Can't deal with DOTDOT lookups if NOCROSSMOUNT or the |
1290 | * order reversal, and there are checks in lookup_once() | | 1290 | * lookup is chrooted. |
1291 | * that need to be made. Also check for missing mountpoints. | | | |
1292 | */ | | 1291 | */ |
1293 | if ((cnp->cn_flags & ISDOTDOT) != 0 || | | 1292 | if ((cnp->cn_flags & ISDOTDOT) != 0) { |
1294 | searchdir->v_mount == NULL) { | | 1293 | if ((searchdir->v_vflag & VV_ROOT) != 0 && |
1295 | error = EOPNOTSUPP; | | 1294 | (cnp->cn_flags & NOCROSSMOUNT)) { |
1296 | break; | | 1295 | error = EOPNOTSUPP; |
| | | 1296 | break; |
| | | 1297 | } |
| | | 1298 | if (ndp->ni_rootdir != rootvnode) { |
| | | 1299 | error = EOPNOTSUPP; |
| | | 1300 | break; |
| | | 1301 | } |
1297 | } | | 1302 | } |
1298 | | | 1303 | |
1299 | /* | | 1304 | /* |
1300 | * Can't deal with last component when modifying; this needs | | 1305 | * Can't deal with last component when modifying; this needs |
1301 | * searchdir locked and VOP_LOOKUP() called (which can and | | 1306 | * searchdir locked and VOP_LOOKUP() called (which can and |
1302 | * does modify state, despite the name). | | 1307 | * does modify state, despite the name). |
1303 | */ | | 1308 | */ |
1304 | if ((cnp->cn_flags & ISLASTCN) != 0) { | | 1309 | if ((cnp->cn_flags & ISLASTCN) != 0) { |
1305 | if (cnp->cn_nameiop != LOOKUP || | | 1310 | if (cnp->cn_nameiop != LOOKUP || |
1306 | (cnp->cn_flags & LOCKPARENT) != 0) { | | 1311 | (cnp->cn_flags & LOCKPARENT) != 0) { |
1307 | error = EOPNOTSUPP; | | 1312 | error = EOPNOTSUPP; |
1308 | break; | | 1313 | break; |
1309 | } | | 1314 | } |
1310 | } | | 1315 | } |
1311 | | | 1316 | |
1312 | /* Can't deal with -o union lookups. */ | | | |
1313 | if ((searchdir->v_vflag & VV_ROOT) != 0 && | | | |
1314 | (searchdir->v_mount->mnt_flag & MNT_UNION) != 0) { | | | |
1315 | error = EOPNOTSUPP; | | | |
1316 | break; | | | |
1317 | } | | | |
1318 | | | | |
1319 | /* | | 1317 | /* |
1320 | * Good, now look for it in cache. cache_lookup_linked() | | 1318 | * Good, now look for it in cache. cache_lookup_linked() |
1321 | * will fail if there's nothing there, or if there's no | | 1319 | * will fail if there's nothing there, or if there's no |
1322 | * ownership info for the directory, or if the user doesn't | | 1320 | * ownership info for the directory, or if the user doesn't |
1323 | * have permission to look up files in this directory. | | 1321 | * have permission to look up files in this directory. |
1324 | */ | | 1322 | */ |
1325 | if (!cache_lookup_linked(searchdir, cnp->cn_nameptr, | | 1323 | if (!cache_lookup_linked(searchdir, cnp->cn_nameptr, |
1326 | cnp->cn_namelen, &foundobj, &plock, cnp->cn_cred)) { | | 1324 | cnp->cn_namelen, &foundobj, &plock, cnp->cn_cred)) { |
1327 | error = EOPNOTSUPP; | | 1325 | error = EOPNOTSUPP; |
1328 | break; | | 1326 | break; |
1329 | } | | 1327 | } |
1330 | KASSERT(plock != NULL && rw_lock_held(plock)); | | 1328 | KASSERT(plock != NULL && rw_lock_held(plock)); |
1331 | | | 1329 | |
1332 | /* Scored a hit. Negative is good too (ENOENT). */ | | 1330 | /* |
| | | 1331 | * Scored a hit. Negative is good too (ENOENT). If there's |
| | | 1332 | * a '-o union' mount here, punt and let lookup_once() deal |
| | | 1333 | * with it. |
| | | 1334 | */ |
1333 | if (foundobj == NULL) { | | 1335 | if (foundobj == NULL) { |
1334 | error = ENOENT; | | 1336 | if ((searchdir->v_vflag & VV_ROOT) != 0 && |
| | | 1337 | (searchdir->v_mount->mnt_flag & MNT_UNION) != 0) { |
| | | 1338 | error = EOPNOTSUPP; |
| | | 1339 | } else { |
| | | 1340 | error = ENOENT; |
| | | 1341 | } |
1335 | break; | | 1342 | break; |
1336 | } | | 1343 | } |
1337 | | | 1344 | |
1338 | /* | | 1345 | /* |
1339 | * Stop and get a hold on the vnode if there's something | | 1346 | * Stop and get a hold on the vnode if there's something |
1340 | * that can't be handled here: | | 1347 | * that can't be handled here: |
1341 | * | | 1348 | * |
1342 | * - we've reached the last component. | | 1349 | * - we've reached the last component. |
1343 | * - or encountered a mount point that needs to be crossed. | | 1350 | * - or encountered a mount point that needs to be crossed. |
1344 | * - or encountered something other than a directory. | | 1351 | * - or encountered something other than a directory. |
1345 | */ | | 1352 | */ |
1346 | if ((cnp->cn_flags & ISLASTCN) != 0 || | | 1353 | if ((cnp->cn_flags & ISLASTCN) != 0 || |
1347 | foundobj->v_type != VDIR || | | 1354 | foundobj->v_type != VDIR || |