Module Name:    src
Committed By:   dholland
Date:           Tue Jun 29 22:40:54 UTC 2021

Modified Files:
        src/external/cddl/osnet/sys/sys: vnode.h
        src/share/man/man9: errno.9 vnsubr.9
        src/sys/dev: firmload.c fss.c kloader.c vnd.c
        src/sys/kern: kern_acct.c kern_core.c kern_descrip.c kern_ktrace_vfs.c
            kern_module_vfs.c subr_exec_fd.c subr_kobj_vfs.c tty_ptm.c
            vfs_syscalls.c vfs_vnops.c
        src/sys/miscfs/fdesc: fdesc_vnops.c
        src/sys/modules/lua: lua.c
        src/sys/sys: filedesc.h vnode.h
        src/sys/ufs/lfs: ulfs_extattr.c ulfs_quota1.c
        src/sys/ufs/ufs: ufs_extattr.c ufs_quota1.c

Log Message:
Add containment for the cloning devices hack in vn_open.

Cloning devices (and also things like /dev/stderr) work by allocating
a struct file, stuffing it in the file table (which is a layer
violation), stuffing the file descriptor number for it in a magic
field of struct lwp (which is gross), and then "failing" with one of
two magic errnos, EDUPFD or EMOVEFD.

Before this commit, all callers of vn_open in the kernel (there are
quite a few) were expected to check for these errors and handle the
situation. Needless to say, none of them except for open() itself did,
resulting in internal negative errnos being returned to userspace.

This hack is fairly deeply rooted and cannot be eliminated all at
once. This commit adds logic to handle the magic errnos inside
vn_open; now on success vn_open returns either a vnode or an integer
file descriptor, along with a flag that says whether the underlying
code requested EDUPFD or EMOVEFD. Callers not prepared to cope with
file descriptors can pass NULL for the extra return values, in which
case if a file descriptor would be produced vn_open fails with
EOPNOTSUPP.

Since I'm rearranging vn_open's signature anyway, stop exposing struct
nameidata. Instead, take three arguments: an optional vnode to use as
the starting point (like openat()), the path, and additional namei
flags to use, restricted to NOCHROOT and TRYEMULROOT. (Other namei
behavior, e.g. NOFOLLOW, can be requested via the open flags.)

This change requires a kernel bump. Ride the one an hour ago.
(That was supposed to be coordinated; did not intend to let an hour
slip by. My fault.)


To generate a diff of this commit:
cvs rdiff -u -r1.18 -r1.19 src/external/cddl/osnet/sys/sys/vnode.h
cvs rdiff -u -r1.5 -r1.6 src/share/man/man9/errno.9
cvs rdiff -u -r1.47 -r1.48 src/share/man/man9/vnsubr.9
cvs rdiff -u -r1.22 -r1.23 src/sys/dev/firmload.c
cvs rdiff -u -r1.110 -r1.111 src/sys/dev/fss.c
cvs rdiff -u -r1.28 -r1.29 src/sys/dev/kloader.c
cvs rdiff -u -r1.281 -r1.282 src/sys/dev/vnd.c
cvs rdiff -u -r1.97 -r1.98 src/sys/kern/kern_acct.c
cvs rdiff -u -r1.34 -r1.35 src/sys/kern/kern_core.c
cvs rdiff -u -r1.250 -r1.251 src/sys/kern/kern_descrip.c
cvs rdiff -u -r1.2 -r1.3 src/sys/kern/kern_ktrace_vfs.c
cvs rdiff -u -r1.17 -r1.18 src/sys/kern/kern_module_vfs.c
cvs rdiff -u -r1.11 -r1.12 src/sys/kern/subr_exec_fd.c \
    src/sys/kern/subr_kobj_vfs.c
cvs rdiff -u -r1.42 -r1.43 src/sys/kern/tty_ptm.c
cvs rdiff -u -r1.549 -r1.550 src/sys/kern/vfs_syscalls.c
cvs rdiff -u -r1.215 -r1.216 src/sys/kern/vfs_vnops.c
cvs rdiff -u -r1.137 -r1.138 src/sys/miscfs/fdesc/fdesc_vnops.c
cvs rdiff -u -r1.24 -r1.25 src/sys/modules/lua/lua.c
cvs rdiff -u -r1.68 -r1.69 src/sys/sys/filedesc.h
cvs rdiff -u -r1.296 -r1.297 src/sys/sys/vnode.h
cvs rdiff -u -r1.16 -r1.17 src/sys/ufs/lfs/ulfs_extattr.c
cvs rdiff -u -r1.11 -r1.12 src/sys/ufs/lfs/ulfs_quota1.c
cvs rdiff -u -r1.52 -r1.53 src/sys/ufs/ufs/ufs_extattr.c
cvs rdiff -u -r1.23 -r1.24 src/sys/ufs/ufs/ufs_quota1.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/external/cddl/osnet/sys/sys/vnode.h
diff -u src/external/cddl/osnet/sys/sys/vnode.h:1.18 src/external/cddl/osnet/sys/sys/vnode.h:1.19
--- src/external/cddl/osnet/sys/sys/vnode.h:1.18	Thu Apr 15 06:59:57 2021
+++ src/external/cddl/osnet/sys/sys/vnode.h	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnode.h,v 1.18 2021/04/15 06:59:57 christos Exp $	*/
+/*	$NetBSD: vnode.h,v 1.19 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*
  * CDDL HEADER START
@@ -239,7 +239,6 @@ zfs_vn_open(const char *pnamep, enum uio
     vnode_t **vpp, enum create crwhy, mode_t umask)
 {
 	struct pathbuf *pb;
-	struct nameidata nd;
 	int error;
 
 	ASSERT(seg == UIO_SYSSPACE);
@@ -247,12 +246,12 @@ zfs_vn_open(const char *pnamep, enum uio
 	ASSERT(crwhy == CRCREAT);
 	ASSERT(umask == 0);
 
+	filemode |= O_NOFOLLOW;
+
 	pb = pathbuf_create(pnamep);
-	NDINIT(&nd, LOOKUP, NOFOLLOW, pb);
-	error = vn_open(&nd, filemode, createmode);
+	error = vn_open(NULL, pb, 0, filemode, createmode, vpp, NULL, NULL);
 	if (error == 0) {
-		VOP_UNLOCK(nd.ni_vp, 0);
-		*vpp = nd.ni_vp;
+		VOP_UNLOCK(*vpp, 0);
 	}
 	pathbuf_destroy(pb);
 	return (error);

Index: src/share/man/man9/errno.9
diff -u src/share/man/man9/errno.9:1.5 src/share/man/man9/errno.9:1.6
--- src/share/man/man9/errno.9:1.5	Mon Mar 22 18:58:33 2010
+++ src/share/man/man9/errno.9	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-.\"	$NetBSD: errno.9,v 1.5 2010/03/22 18:58:33 joerg Exp $
+.\"	$NetBSD: errno.9,v 1.6 2021/06/29 22:40:53 dholland Exp $
 .\"
 .\" Copyright (c) 2004 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -97,7 +97,8 @@ to that new file descriptor and return
 .Xr vn_open 9
 takes the file descriptor pointed to by
 .Ar l_dupfd
-and copies it to the file descriptor that the open call will return.
+and arranges for it to be copied to the file descriptor that the open
+call will return.
 .It Er \-6 EMOVEFD Em "Move file descriptor."
 This error is similar to
 .Er EDUPFD

Index: src/share/man/man9/vnsubr.9
diff -u src/share/man/man9/vnsubr.9:1.47 src/share/man/man9/vnsubr.9:1.48
--- src/share/man/man9/vnsubr.9:1.47	Sun Nov 17 11:46:38 2019
+++ src/share/man/man9/vnsubr.9	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-.\"     $NetBSD: vnsubr.9,v 1.47 2019/11/17 11:46:38 wiz Exp $
+.\"     $NetBSD: vnsubr.9,v 1.48 2021/06/29 22:40:53 dholland Exp $
 .\"
 .\" Copyright (c) 2001, 2005, 2006 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -27,7 +27,7 @@
 .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd January 2, 2017
+.Dd June 28, 2021
 .Dt VNSUBR 9
 .Os
 .Sh NAME
@@ -65,7 +65,11 @@
 .Ft void
 .Fn vn_marktext "struct vnode *vp"
 .Ft int
-.Fn vn_open "struct nameidata *ndp" "int fmode" "int cmode"
+.Fo vn_open
+.Fa "struct vnode *at_dvp" "struct pathbuf *pb"
+.Fa "int nmode" "int fmode" "int cmode" 
+.Fa "struct vnode **ret_vp" "bool *ret_domove" "int *ret_fd"
+.Fc
 .Ft int
 .Fn vn_bdev_open "dev_t dev" "struct vnode **vpp" "struct lwp *l"
 .Ft int
@@ -160,25 +164,81 @@ as containing executable code of a runni
 Common code to mark the vnode
 .Fa vp
 as being the text of a running process.
-.It Fn vn_open "ndp" "fmode" "cmode"
+.It Fn vn_open "at_dvp" "pb" "nmode" "fmode" "cmode" "ret_vp" "ret_domove" "ret_fd"
 Common code for vnode open operations.
-The pathname is described in the nameidata pointer (see
-.Xr namei 9 ) .
+The
+.Fa at_dvp
+argument, if not NULL, provides the directory relative paths start
+from, as per
+.Xr openat 2 .
+The
+.Fa pb
+argument gives the pathname.
 The arguments
+.Fa nmode ,
 .Fa fmode
 and
 .Fa cmode
-specify the
+specify additional
+.Xr namei 9
+flags, the
 .Xr open 2
-file mode and the access permissions for creation.
+flags (converted to
+.Dv F*
+from
+.Dv O_*
+form)
+and the access mode (permissions) for creation, respectively.
+The
+.Fa nmode
+argument is restricted to one or perhaps both of the flags
+.Dv TRYEMULROOT
+and
+.Dv NOCHROOT .
+Other
+.Xr name 9
+modes should be selected via
+.Fn fmode .
+The
+.Fa ret_vp ,
+.Fa ret_domove ,
+and
+.Fa ret_fd
+arguments encode the possible return values.
+When called,
 .Fn vn_open
-checks  permissions and invokes the
+checks permissions and invokes the
 .Xr VOP_OPEN 9
 or
 .Xr VOP_CREATE 9
 vnode operations.
-If the operation is successful zero is returned and the vnode is locked,
-otherwise an appropriate error code is returned.
+If the operation is unsuccessful an appropriate error code is returned.
+Otherwise, zero is returned.
+If a vnode is produced, it is returned locked via
+.Fa ret_vp .
+If a file descriptor number is produced instead, the pointer passed via
+.Fa ret_vp
+is NULL, the file descriptor is returned via
+.Fa ret_fd ,
+and the
+.Fa ret_domove
+returns a value that is true if the file descriptor should be moved
+rather than copied.
+These cases correspond to the internal errors
+.Dv EMOVEFD
+and
+.Dv EDUPFD
+respectively.
+See
+.Xr errno 9
+for further information.
+Callers unprepared to handle file descriptors can set
+.Fa ret_fd
+and
+.Fa ret_domove
+to NULL, in which case an operation that would produce a file descriptor
+will instead fail with
+.Dv EOPNOTSUPP .
 .It Fn vn_bdev_open "dev" "vpp" "l"
 Opens a block device by its device number for reading and writing, and
 stores the vnode pointer into

Index: src/sys/dev/firmload.c
diff -u src/sys/dev/firmload.c:1.22 src/sys/dev/firmload.c:1.23
--- src/sys/dev/firmload.c:1.22	Mon May 30 02:33:49 2016
+++ src/sys/dev/firmload.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: firmload.c,v 1.22 2016/05/30 02:33:49 dholland Exp $	*/
+/*	$NetBSD: firmload.c,v 1.23 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2005, 2006 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: firmload.c,v 1.22 2016/05/30 02:33:49 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: firmload.c,v 1.23 2021/06/29 22:40:53 dholland Exp $");
 
 /*
  * The firmload API provides an interface for device drivers to access
@@ -204,7 +204,6 @@ int
 firmware_open(const char *drvname, const char *imgname, firmware_handle_t *fhp)
 {
 	struct pathbuf *pb;
-	struct nameidata nd;
 	struct vattr va;
 	char *pnbuf, *path, *prefix;
 	firmware_handle_t fh;
@@ -236,8 +235,7 @@ firmware_open(const char *drvname, const
 			error = ENOMEM;
 			break;
 		}
-		NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, pb);
-		error = vn_open(&nd, FREAD, 0);
+		error = vn_open(NULL, pb, NOCHROOT, FREAD, 0, &vp, NULL, NULL);
 		pathbuf_destroy(pb);
 		if (error == ENOENT) {
 			continue;
@@ -251,8 +249,6 @@ firmware_open(const char *drvname, const
 		return (error);
 	}
 
-	vp = nd.ni_vp;
-
 	error = VOP_GETATTR(vp, &va, kauth_cred_get());
 	if (error) {
 		VOP_UNLOCK(vp);

Index: src/sys/dev/fss.c
diff -u src/sys/dev/fss.c:1.110 src/sys/dev/fss.c:1.111
--- src/sys/dev/fss.c:1.110	Sat Dec 26 14:50:50 2020
+++ src/sys/dev/fss.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: fss.c,v 1.110 2020/12/26 14:50:50 nia Exp $	*/
+/*	$NetBSD: fss.c,v 1.111 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.110 2020/12/26 14:50:50 nia Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fss.c,v 1.111 2021/06/29 22:40:53 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -699,10 +699,9 @@ fss_create_files(struct fss_softc *sc, s
 	uint64_t numsec;
 	unsigned int secsize;
 	struct timespec ts;
-	/* nd -> nd2 to reduce mistakes while updating only some namei calls */
+	/* distinguish lookup 1 from lookup 2 to reduce mistakes */
 	struct pathbuf *pb2;
-	struct nameidata nd2;
-	struct vnode *vp;
+	struct vnode *vp, *vp2;
 
 	/*
 	 * Get the mounted file system.
@@ -789,16 +788,17 @@ fss_create_files(struct fss_softc *sc, s
 	if (error) {
  		return error;
 	}
-	NDINIT(&nd2, LOOKUP, FOLLOW, pb2);
-	if ((error = vn_open(&nd2, FREAD|FWRITE, 0)) != 0) {
+	error = vn_open(NULL, pb2, 0, FREAD|FWRITE, 0, &vp2, NULL, NULL);
+	if (error != 0) {
 		pathbuf_destroy(pb2);
 		return error;
 	}
-	VOP_UNLOCK(nd2.ni_vp);
+	VOP_UNLOCK(vp2);
 
-	sc->sc_bs_vp = nd2.ni_vp;
+	sc->sc_bs_vp = vp2;
 
-	if (nd2.ni_vp->v_type != VREG && nd2.ni_vp->v_type != VCHR) {
+	if (vp2->v_type != VREG && vp2->v_type != VCHR) {
+		vrele(vp2);
 		pathbuf_destroy(pb2);
 		return EINVAL;
 	}

Index: src/sys/dev/kloader.c
diff -u src/sys/dev/kloader.c:1.28 src/sys/dev/kloader.c:1.29
--- src/sys/dev/kloader.c:1.28	Sat Sep  5 16:30:11 2020
+++ src/sys/dev/kloader.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kloader.c,v 1.28 2020/09/05 16:30:11 riastradh Exp $	*/
+/*	$NetBSD: kloader.c,v 1.29 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2002, 2004 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kloader.c,v 1.28 2020/09/05 16:30:11 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kloader.c,v 1.29 2021/06/29 22:40:53 dholland Exp $");
 
 #include "debug_kloader.h"
 
@@ -586,6 +586,7 @@ kloader_open(const char *filename)
 {
 	struct pathbuf *pb;
 	struct nameidata nid;
+	struct vnode *vp;
 	int error;
 
 	pb = pathbuf_create(filename);
@@ -594,8 +595,11 @@ kloader_open(const char *filename)
 		return (NULL);
 	}
 
-	NDINIT(&nid, LOOKUP, FOLLOW, pb);
+	/*
+	 * XXX why does this call both namei and vn_open?
+	 */
 
+	NDINIT(&nid, LOOKUP, FOLLOW, pb);
 	error = namei(&nid);
 	if (error != 0) {
 		PRINTF("%s: namei failed, errno=%d\n", filename, error);
@@ -603,7 +607,7 @@ kloader_open(const char *filename)
 		return (NULL);
 	}
 
-	error = vn_open(&nid, FREAD, 0);
+	error = vn_open(NULL, pb, 0, FREAD, 0, &vp, NULL, NULL);
 	if (error != 0) {
 		PRINTF("%s: open failed, errno=%d\n", filename, error);
 		pathbuf_destroy(pb);
@@ -611,7 +615,7 @@ kloader_open(const char *filename)
 	}
 
 	pathbuf_destroy(pb);
-	return (nid.ni_vp);
+	return vp;
 }
 
 void

Index: src/sys/dev/vnd.c
diff -u src/sys/dev/vnd.c:1.281 src/sys/dev/vnd.c:1.282
--- src/sys/dev/vnd.c:1.281	Sun Jun 13 10:01:43 2021
+++ src/sys/dev/vnd.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnd.c,v 1.281 2021/06/13 10:01:43 mlelstv Exp $	*/
+/*	$NetBSD: vnd.c,v 1.282 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2008, 2020 The NetBSD Foundation, Inc.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.281 2021/06/13 10:01:43 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vnd.c,v 1.282 2021/06/29 22:40:53 dholland Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_vnd.h"
@@ -1145,7 +1145,7 @@ vndioctl(dev_t dev, u_long cmd, void *da
 	struct vnd_ioctl *vio;
 	struct vattr vattr;
 	struct pathbuf *pb;
-	struct nameidata nd;
+	struct vnode *vp;
 	int error, part, pmask;
 	uint64_t geomsize;
 	int fflags;
@@ -1273,20 +1273,20 @@ vndioctl(dev_t dev, u_long cmd, void *da
 		if (error) {
 			goto unlock_and_exit;
 		}
-		NDINIT(&nd, LOOKUP, FOLLOW, pb);
-		if ((error = vn_open(&nd, fflags, 0)) != 0) {
+		error = vn_open(NULL, pb, 0, fflags, 0, &vp, NULL, NULL);
+		if (error != 0) {
 			pathbuf_destroy(pb);
 			goto unlock_and_exit;
 		}
 		KASSERT(l);
-		error = VOP_GETATTR(nd.ni_vp, &vattr, l->l_cred);
-		if (!error && nd.ni_vp->v_type != VREG)
+		error = VOP_GETATTR(vp, &vattr, l->l_cred);
+		if (!error && vp->v_type != VREG)
 			error = EOPNOTSUPP;
 		if (!error && vattr.va_bytes < vattr.va_size)
 			/* File is definitely sparse, use vn_rdwr() */
 			vnd->sc_flags |= VNF_USE_VN_RDWR;
 		if (error) {
-			VOP_UNLOCK(nd.ni_vp);
+			VOP_UNLOCK(vp);
 			goto close_and_exit;
 		}
 
@@ -1304,19 +1304,19 @@ vndioctl(dev_t dev, u_long cmd, void *da
 			    M_TEMP, M_WAITOK);
 
 			/* read compressed file header */
-			error = vn_rdwr(UIO_READ, nd.ni_vp, (void *)ch,
+			error = vn_rdwr(UIO_READ, vp, (void *)ch,
 			    sizeof(struct vnd_comp_header), 0, UIO_SYSSPACE,
 			    IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL);
 			if (error) {
 				free(ch, M_TEMP);
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				goto close_and_exit;
 			}
 
 			if (be32toh(ch->block_size) == 0 ||
 			    be32toh(ch->num_blocks) > UINT32_MAX - 1) {
 				free(ch, M_TEMP);
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				goto close_and_exit;
 			}
 
@@ -1326,7 +1326,7 @@ vndioctl(dev_t dev, u_long cmd, void *da
 			vnd->sc_comp_numoffs = be32toh(ch->num_blocks) + 1;
 			free(ch, M_TEMP);
 			if (!DK_DEV_BSIZE_OK(vnd->sc_comp_blksz)) {
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				error = EINVAL;
 				goto close_and_exit;
 			}
@@ -1340,7 +1340,7 @@ vndioctl(dev_t dev, u_long cmd, void *da
 			 */
 #if SIZE_MAX <= UINT32_MAX*(64/CHAR_BIT)
 			if (SIZE_MAX/sizeof(uint64_t) < vnd->sc_comp_numoffs) {
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				error = EINVAL;
 				goto close_and_exit;
 			}
@@ -1350,7 +1350,7 @@ vndioctl(dev_t dev, u_long cmd, void *da
 				sizeof(uint64_t)*vnd->sc_comp_numoffs) ||
 			    (UQUAD_MAX/vnd->sc_comp_blksz <
 				vnd->sc_comp_numoffs - 1)) {
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				error = EINVAL;
 				goto close_and_exit;
 			}
@@ -1369,13 +1369,13 @@ vndioctl(dev_t dev, u_long cmd, void *da
 				M_DEVBUF, M_WAITOK);
 
 			/* read in the offsets */
-			error = vn_rdwr(UIO_READ, nd.ni_vp,
+			error = vn_rdwr(UIO_READ, vp,
 			    (void *)vnd->sc_comp_offsets,
 			    sizeof(uint64_t) * vnd->sc_comp_numoffs,
 			    sizeof(struct vnd_comp_header), UIO_SYSSPACE,
 			  IO_UNIT|IO_NODELOCKED, l->l_cred, NULL, NULL);
 			if (error) {
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				goto close_and_exit;
 			}
 			/*
@@ -1414,21 +1414,21 @@ vndioctl(dev_t dev, u_long cmd, void *da
 				if (vnd->sc_comp_stream.msg)
 					printf("vnd%d: compressed file, %s\n",
 					    unit, vnd->sc_comp_stream.msg);
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				error = EINVAL;
 				goto close_and_exit;
 			}
 
 			vnd->sc_flags |= VNF_COMP | VNF_READONLY;
 #else /* !VND_COMPRESSION */
-			VOP_UNLOCK(nd.ni_vp);
+			VOP_UNLOCK(vp);
 			error = EOPNOTSUPP;
 			goto close_and_exit;
 #endif /* VND_COMPRESSION */
 		}
 
-		VOP_UNLOCK(nd.ni_vp);
-		vnd->sc_vp = nd.ni_vp;
+		VOP_UNLOCK(vp);
+		vnd->sc_vp = vp;
 		vnd->sc_size = btodb(vattr.va_size);	/* note truncation */
 
 		/* get smallest I/O size for underlying device, fall back to
@@ -1553,7 +1553,7 @@ vndioctl(dev_t dev, u_long cmd, void *da
 		break;
 
 close_and_exit:
-		(void) vn_close(nd.ni_vp, fflags, l->l_cred);
+		(void) vn_close(vp, fflags, l->l_cred);
 		pathbuf_destroy(pb);
 unlock_and_exit:
 #ifdef VND_COMPRESSION

Index: src/sys/kern/kern_acct.c
diff -u src/sys/kern/kern_acct.c:1.97 src/sys/kern/kern_acct.c:1.98
--- src/sys/kern/kern_acct.c:1.97	Sat May 23 23:42:43 2020
+++ src/sys/kern/kern_acct.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_acct.c,v 1.97 2020/05/23 23:42:43 ad Exp $	*/
+/*	$NetBSD: kern_acct.c,v 1.98 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -71,7 +71,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_acct.c,v 1.97 2020/05/23 23:42:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_acct.c,v 1.98 2021/06/29 22:40:53 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -297,7 +297,7 @@ sys_acct(struct lwp *l, const struct sys
 		syscallarg(const char *) path;
 	} */
 	struct pathbuf *pb;
-	struct nameidata nd;
+	struct vnode *vp;
 	int error;
 
 	/* Make sure that the caller is root. */
@@ -317,18 +317,19 @@ sys_acct(struct lwp *l, const struct sys
 		if (error) {
 			return error;
 		}
-		NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, pb);
-		if ((error = vn_open(&nd, FWRITE|O_APPEND, 0)) != 0) {
+		error = vn_open(NULL, pb, TRYEMULROOT, FWRITE|O_APPEND, 0,
+		    &vp, NULL, NULL);
+		if (error != 0) {
 			pathbuf_destroy(pb);
 			return error;
 		}
-		if (nd.ni_vp->v_type != VREG) {
-			VOP_UNLOCK(nd.ni_vp);
+		if (vp->v_type != VREG) {
+			VOP_UNLOCK(vp);
 			error = EACCES;
 			goto bad;
 		}
-		if ((error = VOP_GETATTR(nd.ni_vp, &va, l->l_cred)) != 0) {
-			VOP_UNLOCK(nd.ni_vp);
+		if ((error = VOP_GETATTR(vp, &va, l->l_cred)) != 0) {
+			VOP_UNLOCK(vp);
 			goto bad;
 		}
 
@@ -341,13 +342,13 @@ sys_acct(struct lwp *l, const struct sys
 #endif
 			vattr_null(&va);
 			va.va_size = size;
-			error = VOP_SETATTR(nd.ni_vp, &va, l->l_cred);
+			error = VOP_SETATTR(vp, &va, l->l_cred);
 			if (error != 0) {
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				goto bad;
 			}
 		}
-		VOP_UNLOCK(nd.ni_vp);
+		VOP_UNLOCK(vp);
 	}
 
 	rw_enter(&acct_lock, RW_WRITER);
@@ -366,7 +367,7 @@ sys_acct(struct lwp *l, const struct sys
 	 * and schedule the new free space watcher.
 	 */
 	acct_state = ACCT_ACTIVE;
-	acct_vp = nd.ni_vp;
+	acct_vp = vp;
 	acct_cred = l->l_cred;
 	kauth_cred_hold(acct_cred);
 
@@ -389,7 +390,7 @@ sys_acct(struct lwp *l, const struct sys
 	rw_exit(&acct_lock);
 	return (error);
  bad:
-	vn_close(nd.ni_vp, FWRITE, l->l_cred);
+	vn_close(vp, FWRITE, l->l_cred);
 	pathbuf_destroy(pb);
 	return error;
 }

Index: src/sys/kern/kern_core.c
diff -u src/sys/kern/kern_core.c:1.34 src/sys/kern/kern_core.c:1.35
--- src/sys/kern/kern_core.c:1.34	Sun Nov  1 18:51:02 2020
+++ src/sys/kern/kern_core.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_core.c,v 1.34 2020/11/01 18:51:02 pgoyette Exp $	*/
+/*	$NetBSD: kern_core.c,v 1.35 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_core.c,v 1.34 2020/11/01 18:51:02 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_core.c,v 1.35 2021/06/29 22:40:53 dholland Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_execfmt.h"
@@ -123,7 +123,6 @@ coredump(struct lwp *l, const char *patt
 	struct vmspace		*vm;
 	kauth_cred_t		cred;
 	struct pathbuf		*pb;
-	struct nameidata	nd;
 	struct vattr		vattr;
 	struct coredump_iostate	io;
 	struct plimit		*lim;
@@ -240,13 +239,12 @@ coredump(struct lwp *l, const char *patt
 		error = ENOMEM;
 		goto done;
 	}
-	NDINIT(&nd, LOOKUP, NOFOLLOW, pb);
-	if ((error = vn_open(&nd, O_CREAT | O_NOFOLLOW | FWRITE,
-	    S_IRUSR | S_IWUSR)) != 0) {
+	error = vn_open(NULL, pb, 0, O_CREAT | O_NOFOLLOW | FWRITE,
+	    S_IRUSR | S_IWUSR, &vp, NULL, NULL);
+	if (error != 0) {
 		pathbuf_destroy(pb);
 		goto done;
 	}
-	vp = nd.ni_vp;
 	pathbuf_destroy(pb);
 
 	/*

Index: src/sys/kern/kern_descrip.c
diff -u src/sys/kern/kern_descrip.c:1.250 src/sys/kern/kern_descrip.c:1.251
--- src/sys/kern/kern_descrip.c:1.250	Thu Dec 24 12:14:50 2020
+++ src/sys/kern/kern_descrip.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_descrip.c,v 1.250 2020/12/24 12:14:50 nia Exp $	*/
+/*	$NetBSD: kern_descrip.c,v 1.251 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.250 2020/12/24 12:14:50 nia Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.251 2021/06/29 22:40:53 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1646,14 +1646,32 @@ filedescopen(dev_t dev, int mode, int ty
 
 /*
  * Duplicate the specified descriptor to a free descriptor.
+ *
+ * old is the original fd.
+ * moveit is true if we should move rather than duplicate.
+ * flags are the open flags (converted from O_* to F*).
+ * newp returns the new fd on success.
+ *
+ * These two cases are produced by the EDUPFD and EMOVEFD magic
+ * errnos, but in the interest of removing that regrettable interface,
+ * vn_open has been changed to intercept them. Now vn_open returns
+ * either a vnode or a filehandle, and the filehandle is accompanied
+ * by a boolean that says whether we should dup (moveit == false) or
+ * move (moveit == true) the fd.
+ *
+ * The dup case is used by /dev/stderr, /proc/self/fd, and such. The
+ * move case is used by cloner devices that allocate a fd of their
+ * own (a layering violation that should go away eventually) that
+ * then needs to be put in the place open() expects it.
  */
 int
-fd_dupopen(int old, int *newp, int mode, int error)
+fd_dupopen(int old, bool moveit, int flags, int *newp)
 {
 	filedesc_t *fdp;
 	fdfile_t *ff;
 	file_t *fp;
 	fdtab_t *dt;
+	int error;
 
 	if ((fp = fd_getfile(old)) == NULL) {
 		return EBADF;
@@ -1665,35 +1683,30 @@ fd_dupopen(int old, int *newp, int mode,
 	/*
 	 * There are two cases of interest here.
 	 *
-	 * For EDUPFD simply dup (old) to file descriptor
-	 * (new) and return.
-	 *
-	 * For EMOVEFD steal away the file structure from (old) and
-	 * store it in (new).  (old) is effectively closed by
-	 * this operation.
+	 * 1. moveit == false (used to be the EDUPFD magic errno):
+	 *    simply dup (old) to file descriptor (new) and return.
 	 *
-	 * Any other error code is just returned.
+	 * 2. moveit == true (used to be the EMOVEFD magic errno):
+	 *    steal away the file structure from (old) and store it in
+	 *    (new).  (old) is effectively closed by this operation.
 	 */
-	switch (error) {
-	case EDUPFD:
+	if (moveit == false) {
 		/*
 		 * Check that the mode the file is being opened for is a
 		 * subset of the mode of the existing descriptor.
 		 */
-		if (((mode & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
+		if (((flags & (FREAD|FWRITE)) | fp->f_flag) != fp->f_flag) {
 			error = EACCES;
-			break;
+			goto out;
 		}
 
 		/* Copy it. */
 		error = fd_dup(fp, 0, newp, ff->ff_exclose);
-		break;
-
-	case EMOVEFD:
+	} else {
 		/* Copy it. */
 		error = fd_dup(fp, 0, newp, ff->ff_exclose);
 		if (error != 0) {
-			break;
+			goto out;
 		}
 
 		/* Steal away the file pointer from 'old'. */
@@ -1701,6 +1714,7 @@ fd_dupopen(int old, int *newp, int mode,
 		return 0;
 	}
 
+out:
 	fd_putfile(old);
 	return error;
 }

Index: src/sys/kern/kern_ktrace_vfs.c
diff -u src/sys/kern/kern_ktrace_vfs.c:1.2 src/sys/kern/kern_ktrace_vfs.c:1.3
--- src/sys/kern/kern_ktrace_vfs.c:1.2	Fri Sep  5 09:20:59 2014
+++ src/sys/kern/kern_ktrace_vfs.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_ktrace_vfs.c,v 1.2 2014/09/05 09:20:59 matt Exp $	*/
+/*	$NetBSD: kern_ktrace_vfs.c,v 1.3 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_ktrace_vfs.c,v 1.2 2014/09/05 09:20:59 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_ktrace_vfs.c,v 1.3 2021/06/29 22:40:53 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -93,7 +93,6 @@ sys_ktrace(struct lwp *l, const struct s
 	struct vnode *vp = NULL;
 	file_t *fp = NULL;
 	struct pathbuf *pb;
-	struct nameidata nd;
 	int error = 0;
 	int fd;
 
@@ -109,13 +108,12 @@ sys_ktrace(struct lwp *l, const struct s
 			ktrexit(l);
 			return (error);
 		}
-		NDINIT(&nd, LOOKUP, FOLLOW, pb);
-		if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
+		error = vn_open(NULL, pb, 0, FREAD|FWRITE, 0, &vp, NULL, NULL);
+		if (error != 0) {
 			pathbuf_destroy(pb);
 			ktrexit(l);
 			return (error);
 		}
-		vp = nd.ni_vp;
 		pathbuf_destroy(pb);
 		VOP_UNLOCK(vp);
 		if (vp->v_type != VREG) {

Index: src/sys/kern/kern_module_vfs.c
diff -u src/sys/kern/kern_module_vfs.c:1.17 src/sys/kern/kern_module_vfs.c:1.18
--- src/sys/kern/kern_module_vfs.c:1.17	Sun Jan 27 02:08:43 2019
+++ src/sys/kern/kern_module_vfs.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_module_vfs.c,v 1.17 2019/01/27 02:08:43 pgoyette Exp $	*/
+/*	$NetBSD: kern_module_vfs.c,v 1.18 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_module_vfs.c,v 1.17 2019/01/27 02:08:43 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_module_vfs.c,v 1.18 2021/06/29 22:40:53 dholland Exp $");
 
 #define _MODULE_INTERNAL
 #include <sys/param.h>
@@ -150,7 +150,7 @@ module_load_plist_vfs(const char *modpat
     prop_dictionary_t *filedictp)
 {
 	struct pathbuf *pb;
-	struct nameidata nd;
+	struct vnode *vp;
 	struct stat sb;
 	void *base;
 	char *proppath;
@@ -181,14 +181,13 @@ module_load_plist_vfs(const char *modpat
 	}
 	module_print("Loading plist from %s", proppath);
 	
-	NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), pb);
-
-	error = vn_open(&nd, FREAD, 0);
+	error = vn_open(NULL, pb, (nochroot ? NOCHROOT : 0), FREAD, 0,
+	    &vp, NULL, NULL);
  	if (error != 0) {
 	 	goto out2;
 	}
 
-	error = vn_stat(nd.ni_vp, &sb);
+	error = vn_stat(vp, &sb);
 	if (error != 0) {
 		goto out3;
 	}
@@ -198,7 +197,7 @@ module_load_plist_vfs(const char *modpat
 	}
 
 	base = kmem_alloc(plistsize, KM_SLEEP);
-	error = vn_rdwr(UIO_READ, nd.ni_vp, base, sb.st_size, 0,
+	error = vn_rdwr(UIO_READ, vp, base, sb.st_size, 0,
 	    UIO_SYSSPACE, IO_NODELOCKED, curlwp->l_cred, &resid, curlwp);
 	*((uint8_t *)base + sb.st_size) = '\0';
 	if (error == 0 && resid != 0) {
@@ -219,8 +218,8 @@ module_load_plist_vfs(const char *modpat
 	KASSERT(error == 0);
 
 out3:
-	VOP_UNLOCK(nd.ni_vp);
-	vn_close(nd.ni_vp, FREAD, kauth_cred_get());
+	VOP_UNLOCK(vp);
+	vn_close(vp, FREAD, kauth_cred_get());
 
 out2:
 	pathbuf_destroy(pb);

Index: src/sys/kern/subr_exec_fd.c
diff -u src/sys/kern/subr_exec_fd.c:1.11 src/sys/kern/subr_exec_fd.c:1.12
--- src/sys/kern/subr_exec_fd.c:1.11	Sat May 23 23:42:43 2020
+++ src/sys/kern/subr_exec_fd.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_exec_fd.c,v 1.11 2020/05/23 23:42:43 ad Exp $	*/
+/*	$NetBSD: subr_exec_fd.c,v 1.12 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_exec_fd.c,v 1.11 2020/05/23 23:42:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_exec_fd.c,v 1.12 2021/06/29 22:40:53 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -81,7 +81,7 @@ fd_checkstd(void)
 {
 	struct proc *p;
 	struct pathbuf *pb;
-	struct nameidata nd;
+	struct vnode *vp;
 	filedesc_t *fdp;
 	file_t *fp;
 	fdtab_t *dt;
@@ -108,17 +108,17 @@ fd_checkstd(void)
 		if (pb == NULL) {
 			return ENOMEM;
 		}
-		NDINIT(&nd, LOOKUP, FOLLOW, pb);
-		if ((error = vn_open(&nd, flags, 0)) != 0) {
+		error = vn_open(NULL, pb, 0, flags, 0, &vp, NULL, NULL);
+		if (error != 0) {
 			pathbuf_destroy(pb);
 			fd_abort(p, fp, fd);
 			return (error);
 		}
 		fp->f_type = DTYPE_VNODE;
-		fp->f_vnode = nd.ni_vp;
+		fp->f_vnode = vp;
 		fp->f_flag = flags;
 		fp->f_ops = &vnops;
-		VOP_UNLOCK(nd.ni_vp);
+		VOP_UNLOCK(vp);
 		fd_affix(p, fp, fd);
 		pathbuf_destroy(pb);
 	}
Index: src/sys/kern/subr_kobj_vfs.c
diff -u src/sys/kern/subr_kobj_vfs.c:1.11 src/sys/kern/subr_kobj_vfs.c:1.12
--- src/sys/kern/subr_kobj_vfs.c:1.11	Thu Jun  1 02:45:13 2017
+++ src/sys/kern/subr_kobj_vfs.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_kobj_vfs.c,v 1.11 2017/06/01 02:45:13 chs Exp $	*/
+/*	$NetBSD: subr_kobj_vfs.c,v 1.12 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -75,7 +75,7 @@
 #include <sys/vnode.h>
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_kobj_vfs.c,v 1.11 2017/06/01 02:45:13 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_kobj_vfs.c,v 1.12 2021/06/29 22:40:53 dholland Exp $");
 
 static void
 kobj_close_vfs(kobj_t ko)
@@ -150,8 +150,8 @@ kobj_read_vfs(kobj_t ko, void **basep, s
 int
 kobj_load_vfs(kobj_t *kop, const char *path, const bool nochroot)
 {
-	struct nameidata nd;
 	struct pathbuf *pb;
+	struct vnode *vp;
 	int error;
 	kobj_t ko;
 
@@ -166,8 +166,8 @@ kobj_load_vfs(kobj_t *kop, const char *p
 		return ENOMEM;
 	}
 
-	NDINIT(&nd, LOOKUP, FOLLOW | (nochroot ? NOCHROOT : 0), pb);
-	error = vn_open(&nd, FREAD, 0);
+	error = vn_open(NULL, pb, (nochroot ? NOCHROOT : 0), FREAD, 0,
+	    &vp, NULL, NULL);
 
  	if (error != 0) {
 		pathbuf_destroy(pb);
@@ -177,7 +177,7 @@ kobj_load_vfs(kobj_t *kop, const char *p
 
 	ko->ko_type = KT_VNODE;
 	kobj_setname(ko, path);
-	ko->ko_source = nd.ni_vp;
+	ko->ko_source = vp;
 	ko->ko_read = kobj_read_vfs;
 	ko->ko_close = kobj_close_vfs;
 	pathbuf_destroy(pb);

Index: src/sys/kern/tty_ptm.c
diff -u src/sys/kern/tty_ptm.c:1.42 src/sys/kern/tty_ptm.c:1.43
--- src/sys/kern/tty_ptm.c:1.42	Sat May 23 22:16:17 2020
+++ src/sys/kern/tty_ptm.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty_ptm.c,v 1.42 2020/05/23 22:16:17 ad Exp $	*/
+/*	$NetBSD: tty_ptm.c,v 1.43 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2004, 2020 The NetBSD Foundation, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tty_ptm.c,v 1.42 2020/05/23 22:16:17 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tty_ptm.c,v 1.43 2021/06/29 22:40:53 dholland Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -141,6 +141,8 @@ pty_vn_open(struct vnode *vp, struct lwp
 	error = VOP_OPEN(vp, FREAD|FWRITE, lwp0.l_cred);
 
 	if (error) {
+		/* only ptys mean we can't get these */
+		KASSERT(error != EDUPFD && error != EMOVEFD);
 		vput(vp);
 		return error;
 	}

Index: src/sys/kern/vfs_syscalls.c
diff -u src/sys/kern/vfs_syscalls.c:1.549 src/sys/kern/vfs_syscalls.c:1.550
--- src/sys/kern/vfs_syscalls.c:1.549	Wed Feb 17 17:39:08 2021
+++ src/sys/kern/vfs_syscalls.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_syscalls.c,v 1.549 2021/02/17 17:39:08 dholland Exp $	*/
+/*	$NetBSD: vfs_syscalls.c,v 1.550 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009, 2019, 2020 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.549 2021/02/17 17:39:08 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.550 2021/06/29 22:40:53 dholland Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_fileassoc.h"
@@ -1635,9 +1635,10 @@ do_open(lwp_t *l, struct vnode *dvp, str
 	struct cwdinfo *cwdi = p->p_cwdi;
 	file_t *fp;
 	struct vnode *vp;
+	int dupfd;
+	bool dupfd_move;
 	int flags, cmode;
 	int indx, error;
-	struct nameidata nd;
 
 	if (open_flags & O_SEARCH) {
 		open_flags &= ~(int)O_SEARCH;
@@ -1660,34 +1661,32 @@ do_open(lwp_t *l, struct vnode *dvp, str
 
 	/* We're going to read cwdi->cwdi_cmask unlocked here. */
 	cmode = ((open_mode &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT;
-	NDINIT(&nd, LOOKUP, FOLLOW | TRYEMULROOT, pb);
-	if (dvp != NULL)
-		NDAT(&nd, dvp);
 	
-	l->l_dupfd = -indx - 1;			/* XXX check for fdopen */
-	if ((error = vn_open(&nd, flags, cmode)) != 0) {
+	error = vn_open(dvp, pb, TRYEMULROOT, flags, cmode,
+	    &vp, &dupfd_move, &dupfd);
+	if (error != 0) {
 		fd_abort(p, fp, indx);
-		if ((error == EDUPFD || error == EMOVEFD) &&
-		    l->l_dupfd >= 0 &&			/* XXX from fdopen */
-		    (error =
-			fd_dupopen(l->l_dupfd, &indx, flags, error)) == 0) {
-			*fd = indx;
-			return 0;
-		}
 		if (error == ERESTART)
 			error = EINTR;
 		return error;
 	}
 
-	l->l_dupfd = 0;
-	vp = nd.ni_vp;
-
-	if ((error = open_setfp(l, fp, vp, indx, flags)))
-		return error;
+	if (vp == NULL) {
+		fd_abort(p, fp, indx);
+		error = fd_dupopen(dupfd, dupfd_move, flags, &indx);
+		if (error == 0) {
+			*fd = indx;
+			return 0;
+		}
+	} else {
+		error = open_setfp(l, fp, vp, indx, flags);
+		if (error)
+			return error;
+		VOP_UNLOCK(vp);
+		*fd = indx;
+		fd_affix(p, fp, indx);
+	}
 
-	VOP_UNLOCK(vp);
-	*fd = indx;
-	fd_affix(p, fp, indx);
 	return 0;
 }
 
@@ -2114,6 +2113,10 @@ bad:
 	fd_abort(p, fp, indx);
 	if (vp != NULL)
 		vput(vp);
+	if (error == EDUPFD || error == EMOVEFD) {
+		/* XXX should probably close curlwp->l_dupfd */
+		error = EOPNOTSUPP;
+	}
 	return (error);
 }
 

Index: src/sys/kern/vfs_vnops.c
diff -u src/sys/kern/vfs_vnops.c:1.215 src/sys/kern/vfs_vnops.c:1.216
--- src/sys/kern/vfs_vnops.c:1.215	Wed Jun 16 01:51:57 2021
+++ src/sys/kern/vfs_vnops.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_vnops.c,v 1.215 2021/06/16 01:51:57 dholland Exp $	*/
+/*	$NetBSD: vfs_vnops.c,v 1.216 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.215 2021/06/16 01:51:57 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_vnops.c,v 1.216 2021/06/29 22:40:53 dholland Exp $");
 
 #include "veriexec.h"
 
@@ -139,10 +139,31 @@ const struct fileops vnops = {
 /*
  * Common code for vnode open operations.
  * Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
+ *
+ * at_dvp is the directory for openat(), if any.
+ * pb is the path.
+ * nmode is additional namei flags, restricted to TRYEMULROOT and NOCHROOT.
+ * fmode is the open flags, converted from O_* to F*
+ * cmode is the creation file permissions.
+ *
+ * XXX shouldn't cmode be mode_t?
+ *
+ * On success produces either a vnode in *ret_vp, or if that is NULL,
+ * a file descriptor number in ret_fd.
+ *
+ * The caller may pass NULL for ret_fd (and ret_domove), in which case
+ * EOPNOTSUPP will be produced in the cases that would otherwise return
+ * a file descriptor.
+ *
+ * Note that callers that want NOFOLLOW should pass O_NOFOLLOW in fmode,
+ * not NOFOLLOW in nmode.
  */
 int
-vn_open(struct nameidata *ndp, int fmode, int cmode)
+vn_open(struct vnode *at_dvp, struct pathbuf *pb,
+	int nmode, int fmode, int cmode,
+	struct vnode **ret_vp, bool *ret_domove, int *ret_fd)
 {
+	struct nameidata nd;
 	struct vnode *vp;
 	struct lwp *l = curlwp;
 	kauth_cred_t cred = l->l_cred;
@@ -150,39 +171,53 @@ vn_open(struct nameidata *ndp, int fmode
 	int error;
 	const char *pathstring;
 
+	KASSERT((nmode & (TRYEMULROOT | NOCHROOT)) == nmode);
+
 	if ((fmode & (O_CREAT | O_DIRECTORY)) == (O_CREAT | O_DIRECTORY))
 		return EINVAL;
 
-	ndp->ni_cnd.cn_flags &= TRYEMULROOT | NOCHROOT;
+	NDINIT(&nd, LOOKUP, FOLLOW | nmode, pb);
+	if (at_dvp != NULL)
+		NDAT(&nd, at_dvp);
+
+	nd.ni_cnd.cn_flags &= TRYEMULROOT | NOCHROOT;
 
 	if (fmode & O_CREAT) {
-		ndp->ni_cnd.cn_nameiop = CREATE;
-		ndp->ni_cnd.cn_flags |= LOCKPARENT | LOCKLEAF;
+		nd.ni_cnd.cn_nameiop = CREATE;
+		nd.ni_cnd.cn_flags |= LOCKPARENT | LOCKLEAF;
 		if ((fmode & O_EXCL) == 0 &&
 		    ((fmode & O_NOFOLLOW) == 0))
-			ndp->ni_cnd.cn_flags |= FOLLOW;
+			nd.ni_cnd.cn_flags |= FOLLOW;
 		if ((fmode & O_EXCL) == 0)
-			ndp->ni_cnd.cn_flags |= NONEXCLHACK;
+			nd.ni_cnd.cn_flags |= NONEXCLHACK;
 	} else {
-		ndp->ni_cnd.cn_nameiop = LOOKUP;
-		ndp->ni_cnd.cn_flags |= LOCKLEAF;
+		nd.ni_cnd.cn_nameiop = LOOKUP;
+		nd.ni_cnd.cn_flags |= LOCKLEAF;
 		if ((fmode & O_NOFOLLOW) == 0)
-			ndp->ni_cnd.cn_flags |= FOLLOW;
+			nd.ni_cnd.cn_flags |= FOLLOW;
 	}
 
-	pathstring = pathbuf_stringcopy_get(ndp->ni_pathbuf);
+	pathstring = pathbuf_stringcopy_get(nd.ni_pathbuf);
 	if (pathstring == NULL) {
 		return ENOMEM;
 	}
 
-	error = namei(ndp);
+	/*
+	 * When this "interface" was exposed to do_open() it used
+	 * to initialize l_dupfd to -newfd-1 (thus passing in the
+	 * new file handle number to use)... but nothing in the
+	 * kernel uses that value. So just send 0.
+	 */
+	l->l_dupfd = 0;
+
+	error = namei(&nd);
 	if (error)
 		goto out;
 
-	vp = ndp->ni_vp;
+	vp = nd.ni_vp;
 
 #if NVERIEXEC > 0
-	error = veriexec_openchk(l, ndp->ni_vp, pathstring, fmode);
+	error = veriexec_openchk(l, nd.ni_vp, pathstring, fmode);
 	if (error) {
 		/* We have to release the locks ourselves */
 		/*
@@ -190,16 +225,16 @@ vn_open(struct nameidata *ndp, int fmode
 		 * get ni_dvp == NULL back if ni_vp exists, and we should
 		 * treat that like the non-O_CREAT case.
 		 */
-		if ((fmode & O_CREAT) != 0 && ndp->ni_dvp != NULL) {
+		if ((fmode & O_CREAT) != 0 && nd.ni_dvp != NULL) {
 			if (vp == NULL) {
-				vput(ndp->ni_dvp);
+				vput(nd.ni_dvp);
 			} else {
-				VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
-				if (ndp->ni_dvp == ndp->ni_vp)
-					vrele(ndp->ni_dvp);
+				VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+				if (nd.ni_dvp == nd.ni_vp)
+					vrele(nd.ni_dvp);
 				else
-					vput(ndp->ni_dvp);
-				ndp->ni_dvp = NULL;
+					vput(nd.ni_dvp);
+				nd.ni_dvp = NULL;
 				vput(vp);
 			}
 		} else {
@@ -212,31 +247,31 @@ vn_open(struct nameidata *ndp, int fmode
 	/*
 	 * 20210604 dholland ditto
 	 */
-	if ((fmode & O_CREAT) != 0 && ndp->ni_dvp != NULL) {
-		if (ndp->ni_vp == NULL) {
+	if ((fmode & O_CREAT) != 0 && nd.ni_dvp != NULL) {
+		if (nd.ni_vp == NULL) {
 			vattr_null(&va);
 			va.va_type = VREG;
 			va.va_mode = cmode;
 			if (fmode & O_EXCL)
 				 va.va_vaflags |= VA_EXCLUSIVE;
-			error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp,
-					   &ndp->ni_cnd, &va);
+			error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp,
+					   &nd.ni_cnd, &va);
 			if (error) {
-				vput(ndp->ni_dvp);
+				vput(nd.ni_dvp);
 				goto out;
 			}
 			fmode &= ~O_TRUNC;
-			vp = ndp->ni_vp;
+			vp = nd.ni_vp;
 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-			vput(ndp->ni_dvp);
+			vput(nd.ni_dvp);
 		} else {
-			VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd);
-			if (ndp->ni_dvp == ndp->ni_vp)
-				vrele(ndp->ni_dvp);
+			VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
+			if (nd.ni_dvp == nd.ni_vp)
+				vrele(nd.ni_dvp);
 			else
-				vput(ndp->ni_dvp);
-			ndp->ni_dvp = NULL;
-			vp = ndp->ni_vp;
+				vput(nd.ni_dvp);
+			nd.ni_dvp = NULL;
+			vp = nd.ni_vp;
 			if (fmode & O_EXCL) {
 				error = EEXIST;
 				goto bad;
@@ -251,17 +286,17 @@ vn_open(struct nameidata *ndp, int fmode
 		 * half of the following block. (Besides handle
 		 * ni_dvp, anyway.)
 		 */
-		vp = ndp->ni_vp;
+		vp = nd.ni_vp;
 		KASSERT((fmode & O_EXCL) == 0);
 		fmode &= ~O_CREAT;
 	} else {
-		vp = ndp->ni_vp;
+		vp = nd.ni_vp;
 	}
 	if (vp->v_type == VSOCK) {
 		error = EOPNOTSUPP;
 		goto bad;
 	}
-	if (ndp->ni_vp->v_type == VLNK) {
+	if (nd.ni_vp->v_type == VLNK) {
 		error = EFTYPE;
 		goto bad;
 	}
@@ -291,8 +326,40 @@ bad:
 	if (error)
 		vput(vp);
 out:
-	pathbuf_stringcopy_put(ndp->ni_pathbuf, pathstring);
-	return (error);
+	pathbuf_stringcopy_put(nd.ni_pathbuf, pathstring);
+
+	/* if the caller isn't prepared to handle fds, fail for them */
+	if (ret_fd == NULL && (error == EDUPFD || error == EMOVEFD)) {
+		/*
+		 * XXX: for EMOVEFD (cloning devices) this leaks the
+		 * device's file descriptor. That's not good, but
+		 * fixing it here would still be a layer violation and
+		 * callers not currently prepared to deal weren't
+		 * prepared before I rearranged things either and
+		 * would still have leaked the fd, so it's at least
+		 * not a regression.
+		 *    -- dholland 20210627
+		 */
+		error = EOPNOTSUPP;
+	}
+
+	if (error == EDUPFD) {
+		*ret_vp = NULL;
+		*ret_domove = false;
+		*ret_fd = l->l_dupfd;
+		error = 0;
+	} else if (error == EMOVEFD) {
+		*ret_vp = NULL;
+		*ret_domove = true;
+		*ret_fd = l->l_dupfd;
+		error = 0;
+	} else if (error == 0) {
+		*ret_vp = vp;
+		*ret_domove = false;
+		*ret_fd = -1;
+	}
+	l->l_dupfd = 0;
+	return error;
 }
 
 /*
@@ -1235,17 +1302,15 @@ vn_bdev_open(dev_t dev, struct vnode **v
 int
 vn_bdev_openpath(struct pathbuf *pb, struct vnode **vpp, struct lwp *l)
 {
-	struct nameidata nd;
 	struct vnode *vp;
 	dev_t dev;
 	enum vtype vt;
 	int     error;
 
-	NDINIT(&nd, LOOKUP, FOLLOW, pb);
-	if ((error = vn_open(&nd, FREAD | FWRITE, 0)) != 0)
+	error = vn_open(NULL, pb, 0, FREAD | FWRITE, 0, &vp, NULL, NULL);
+	if (error != 0)
 		return error;
 
-	vp = nd.ni_vp;
 	dev = vp->v_rdev;
 	vt = vp->v_type;
 

Index: src/sys/miscfs/fdesc/fdesc_vnops.c
diff -u src/sys/miscfs/fdesc/fdesc_vnops.c:1.137 src/sys/miscfs/fdesc/fdesc_vnops.c:1.138
--- src/sys/miscfs/fdesc/fdesc_vnops.c:1.137	Tue Jun 29 22:34:08 2021
+++ src/sys/miscfs/fdesc/fdesc_vnops.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: fdesc_vnops.c,v 1.137 2021/06/29 22:34:08 dholland Exp $	*/
+/*	$NetBSD: fdesc_vnops.c,v 1.138 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.137 2021/06/29 22:34:08 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdesc_vnops.c,v 1.138 2021/06/29 22:40:53 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -326,11 +326,13 @@ fdesc_open(void *v)
 	case Fdesc:
 		/*
 		 * XXX Kludge: set dupfd to contain the value of the
-		 * the file descriptor being sought for duplication. The error
-		 * return ensures that the vnode for this device will be
-		 * released by vn_open. Open will detect this special error and
-		 * take the actions in dupfdopen.  Other callers of vn_open or
-		 * VOP_OPEN will simply report the error.
+		 * the file descriptor being sought for duplication.
+		 * The error return ensures that the vnode for this
+		 * device will be released by vn_open. vn_open will
+		 * then detect this special error and take the actions
+		 * in fd_dupopen. Other callers of vn_open or VOP_OPEN
+		 * not prepared to deal with this situation will
+		 * report a real error.
 		 */
 		curlwp->l_dupfd = VTOFDESC(vp)->fd_fd;	/* XXX */
 		return EDUPFD;

Index: src/sys/modules/lua/lua.c
diff -u src/sys/modules/lua/lua.c:1.24 src/sys/modules/lua/lua.c:1.25
--- src/sys/modules/lua/lua.c:1.24	Tue Dec 26 12:43:59 2017
+++ src/sys/modules/lua/lua.c	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: lua.c,v 1.24 2017/12/26 12:43:59 martin Exp $ */
+/*	$NetBSD: lua.c,v 1.25 2021/06/29 22:40:53 dholland Exp $ */
 
 /*
  * Copyright (c) 2011 - 2017 by Marc Balmer <mbal...@netbsd.org>.
@@ -284,7 +284,7 @@ luaioctl(dev_t dev, u_long cmd, void *da
 	struct lua_state *s;
 	struct lua_module *m;
 	kauth_cred_t cred;
-	struct nameidata nd;
+	struct vnode *vp;
 	struct pathbuf *pb;
 	struct vattr va;
 	struct lua_loadstate ls;
@@ -414,8 +414,8 @@ luaioctl(dev_t dev, u_long cmd, void *da
 				pb = pathbuf_create(load->path);
 				if (pb == NULL)
 					return ENOMEM;
-				NDINIT(&nd, LOOKUP, FOLLOW | NOCHROOT, pb);
-				error = vn_open(&nd, FREAD, 0);
+				error = vn_open(NULL, pb, NOCHROOT, FREAD, 0,
+				    &vp, NULL, NULL);
 				pathbuf_destroy(pb);
 				if (error) {
 					if (lua_verbose)
@@ -424,11 +424,11 @@ luaioctl(dev_t dev, u_long cmd, void *da
 						    error);
 					return error;
 				}
-				error = VOP_GETATTR(nd.ni_vp, &va,
+				error = VOP_GETATTR(vp, &va,
 				    kauth_cred_get());
 				if (error) {
-					VOP_UNLOCK(nd.ni_vp);
-					vn_close(nd.ni_vp, FREAD,
+					VOP_UNLOCK(vp);
+					vn_close(vp, FREAD,
 					    kauth_cred_get());
 					if (lua_verbose)
 						device_printf(sc->sc_dev,
@@ -437,19 +437,19 @@ luaioctl(dev_t dev, u_long cmd, void *da
 					return error;
 				}
 				if (va.va_type != VREG) {
-					VOP_UNLOCK(nd.ni_vp);
-					vn_close(nd.ni_vp, FREAD,
+					VOP_UNLOCK(vp);
+					vn_close(vp, FREAD,
 					    kauth_cred_get());
 					return EINVAL;
 				}
-				ls.vp = nd.ni_vp;
+				ls.vp = vp;
 				ls.off = 0L;
 				ls.size = va.va_size;
-				VOP_UNLOCK(nd.ni_vp);
+				VOP_UNLOCK(vp);
 				klua_lock(s->K);
 				error = lua_load(s->K->L, lua_reader, &ls,
 				    strrchr(load->path, '/') + 1, "bt");
-				vn_close(nd.ni_vp, FREAD, cred);
+				vn_close(vp, FREAD, cred);
 				switch (error) {
 				case 0:	/* no error */
 					break;

Index: src/sys/sys/filedesc.h
diff -u src/sys/sys/filedesc.h:1.68 src/sys/sys/filedesc.h:1.69
--- src/sys/sys/filedesc.h:1.68	Tue Apr 21 21:46:07 2020
+++ src/sys/sys/filedesc.h	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: filedesc.h,v 1.68 2020/04/21 21:46:07 ad Exp $	*/
+/*	$NetBSD: filedesc.h,v 1.69 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -192,7 +192,7 @@ struct proc;
  */
 void	fd_sys_init(void);
 int	fd_open(const char*, int, int, int*);
-int	fd_dupopen(int, int *, int, int);
+int	fd_dupopen(int, bool, int, int *);
 int	fd_alloc(struct proc *, int, int *);
 void	fd_tryexpand(struct proc *);
 int	fd_allocfile(file_t **, int *);

Index: src/sys/sys/vnode.h
diff -u src/sys/sys/vnode.h:1.296 src/sys/sys/vnode.h:1.297
--- src/sys/sys/vnode.h:1.296	Sat May 16 18:31:53 2020
+++ src/sys/sys/vnode.h	Tue Jun 29 22:40:53 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: vnode.h,v 1.296 2020/05/16 18:31:53 christos Exp $	*/
+/*	$NetBSD: vnode.h,v 1.297 2021/06/29 22:40:53 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2020 The NetBSD Foundation, Inc.
@@ -594,7 +594,8 @@ int	vn_isunder(struct vnode *, struct vn
 int	vn_lock(struct vnode *, int);
 void	vn_markexec(struct vnode *);
 int	vn_marktext(struct vnode *);
-int 	vn_open(struct nameidata *, int, int);
+int 	vn_open(struct vnode *, struct pathbuf *, int, int, int,
+	    struct vnode **, bool *, int *);
 int 	vn_rdwr(enum uio_rw, struct vnode *, void *, int, off_t, enum uio_seg,
     int, kauth_cred_t, size_t *, struct lwp *);
 int	vn_readdir(struct file *, char *, int, unsigned int, int *,

Index: src/sys/ufs/lfs/ulfs_extattr.c
diff -u src/sys/ufs/lfs/ulfs_extattr.c:1.16 src/sys/ufs/lfs/ulfs_extattr.c:1.17
--- src/sys/ufs/lfs/ulfs_extattr.c:1.16	Sat May 16 18:31:53 2020
+++ src/sys/ufs/lfs/ulfs_extattr.c	Tue Jun 29 22:40:54 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ulfs_extattr.c,v 1.16 2020/05/16 18:31:53 christos Exp $	*/
+/*	$NetBSD: ulfs_extattr.c,v 1.17 2021/06/29 22:40:54 dholland Exp $	*/
 /*  from NetBSD: ulfs_extattr.c,v 1.48 2016/11/09 05:08:35 dholland Exp  */
 
 /*-
@@ -49,7 +49,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ulfs_extattr.c,v 1.16 2020/05/16 18:31:53 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ulfs_extattr.c,v 1.17 2021/06/29 22:40:54 dholland Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_lfs.h"
@@ -171,7 +171,6 @@ ulfs_extattr_autocreate_attr(struct vnod
 	struct mount *mp = vp->v_mount;
 	struct ulfsmount *ump = VFSTOULFS(mp);
 	struct vnode *backing_vp;
-	struct nameidata nd;
 	struct pathbuf *pb;
 	char *path;
 	struct ulfs_extattr_fileheader uef;
@@ -223,14 +222,16 @@ ulfs_extattr_autocreate_attr(struct vnod
 	VOP_UNLOCK(vp);
 
 	pb = pathbuf_create(path);
-	NDINIT(&nd, CREATE, LOCKPARENT, pb);
 	
 	/*
 	 * Since we do not hold ulfs_extattr_uepm_lock anymore,
 	 * another thread may race with us for backend creation,
-	 * but only one can succeed here thanks to O_EXCL
+	 * but only one can succeed here thanks to O_EXCL.
+	 *
+ 	 * backing_vp is the backing store. 
 	 */
-	error = vn_open(&nd, O_CREAT|O_EXCL|O_RDWR, 0600);
+	error = vn_open(NULL, pb, 0, O_CREAT|O_EXCL|O_RDWR, 0600,
+	    &backing_vp, NULL, NULL);
 
 	/*
 	 * Reacquire the lock on the vnode
@@ -247,14 +248,9 @@ ulfs_extattr_autocreate_attr(struct vnod
 		return error;
 	}
 
-	KASSERT(nd.ni_vp != NULL);
-	KASSERT(VOP_ISLOCKED(nd.ni_vp) == LK_EXCLUSIVE);
-	KASSERT(VOP_ISLOCKED(nd.ni_dvp) == 0);
+	KASSERT(backing_vp != NULL);
+	KASSERT(VOP_ISLOCKED(backing_vp) == LK_EXCLUSIVE);
 
-	/*
- 	 * backing_vp is the backing store. 
-	 */	
-	backing_vp = nd.ni_vp;
 	pathbuf_destroy(pb);
 	PNBUF_PUT(path);
 

Index: src/sys/ufs/lfs/ulfs_quota1.c
diff -u src/sys/ufs/lfs/ulfs_quota1.c:1.11 src/sys/ufs/lfs/ulfs_quota1.c:1.12
--- src/sys/ufs/lfs/ulfs_quota1.c:1.11	Mon Jun 20 00:53:10 2016
+++ src/sys/ufs/lfs/ulfs_quota1.c	Tue Jun 29 22:40:54 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ulfs_quota1.c,v 1.11 2016/06/20 00:53:10 dholland Exp $	*/
+/*	$NetBSD: ulfs_quota1.c,v 1.12 2021/06/29 22:40:54 dholland Exp $	*/
 /*  from NetBSD: ufs_quota1.c,v 1.22 2016/06/20 00:52:04 dholland Exp  */
 
 /*
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ulfs_quota1.c,v 1.11 2016/06/20 00:53:10 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ulfs_quota1.c,v 1.12 2021/06/29 22:40:54 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -312,7 +312,6 @@ lfsquota1_handle_cmd_quotaon(struct lwp 
 	struct dquot *dq;
 	int error;
 	struct pathbuf *pb;
-	struct nameidata nd;
 
 	if (fs->um_flags & ULFS_QUOTA2) {
 		uprintf("%s: quotas v2 already enabled\n",
@@ -326,12 +325,11 @@ lfsquota1_handle_cmd_quotaon(struct lwp 
 	if (pb == NULL) {
 		return ENOMEM;
 	}
-	NDINIT(&nd, LOOKUP, FOLLOW, pb);
-	if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
+	error = vn_open(NULL, pb, 0, FREAD|FWRITE, 0, &vp, NULL, NULL);
+	if (error != 0) {
 		pathbuf_destroy(pb);
 		return error;
 	}
-	vp = nd.ni_vp;
 	pathbuf_destroy(pb);
 
 	VOP_UNLOCK(vp);

Index: src/sys/ufs/ufs/ufs_extattr.c
diff -u src/sys/ufs/ufs/ufs_extattr.c:1.52 src/sys/ufs/ufs/ufs_extattr.c:1.53
--- src/sys/ufs/ufs/ufs_extattr.c:1.52	Sat May 16 18:31:54 2020
+++ src/sys/ufs/ufs/ufs_extattr.c	Tue Jun 29 22:40:54 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_extattr.c,v 1.52 2020/05/16 18:31:54 christos Exp $	*/
+/*	$NetBSD: ufs_extattr.c,v 1.53 2021/06/29 22:40:54 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1999-2002 Robert N. M. Watson
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_extattr.c,v 1.52 2020/05/16 18:31:54 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_extattr.c,v 1.53 2021/06/29 22:40:54 dholland Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ffs.h"
@@ -172,7 +172,6 @@ ufs_extattr_autocreate_attr(struct vnode
 	struct mount *mp = vp->v_mount;
 	struct ufsmount *ump = VFSTOUFS(mp);
 	struct vnode *backing_vp;
-	struct nameidata nd;
 	struct pathbuf *pb;
 	char *path;
 	struct ufs_extattr_fileheader uef;
@@ -220,14 +219,16 @@ ufs_extattr_autocreate_attr(struct vnode
 	VOP_UNLOCK(vp);
 
 	pb = pathbuf_create(path);
-	NDINIT(&nd, CREATE, LOCKPARENT, pb);
 	
 	/*
 	 * Since we do not hold ufs_extattr_uepm_lock anymore,
 	 * another thread may race with us for backend creation,
-	 * but only one can succeed here thanks to O_EXCL
+	 * but only one can succeed here thanks to O_EXCL.
+	 *
+ 	 * backing_vp is the backing store. 
 	 */
-	error = vn_open(&nd, O_CREAT|O_EXCL|O_RDWR, 0600);
+	error = vn_open(NULL, pb, 0, O_CREAT|O_EXCL|O_RDWR, 0600,
+	    &backing_vp, NULL, NULL);
 
 	/*
 	 * Reacquire the lock on the vnode
@@ -244,14 +245,9 @@ ufs_extattr_autocreate_attr(struct vnode
 		return error;
 	}
 
-	KASSERT(nd.ni_vp != NULL);
-	KASSERT(VOP_ISLOCKED(nd.ni_vp) == LK_EXCLUSIVE);
-	KASSERT(VOP_ISLOCKED(nd.ni_dvp) == 0);
+	KASSERT(backing_vp != NULL);
+	KASSERT(VOP_ISLOCKED(backing_vp) == LK_EXCLUSIVE);
 
-	/*
- 	 * backing_vp is the backing store. 
-	 */	
-	backing_vp = nd.ni_vp;
 	pathbuf_destroy(pb);
 	PNBUF_PUT(path);
 

Index: src/sys/ufs/ufs/ufs_quota1.c
diff -u src/sys/ufs/ufs/ufs_quota1.c:1.23 src/sys/ufs/ufs/ufs_quota1.c:1.24
--- src/sys/ufs/ufs/ufs_quota1.c:1.23	Fri Dec 25 10:00:40 2020
+++ src/sys/ufs/ufs/ufs_quota1.c	Tue Jun 29 22:40:54 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_quota1.c,v 1.23 2020/12/25 10:00:40 nia Exp $	*/
+/*	$NetBSD: ufs_quota1.c,v 1.24 2021/06/29 22:40:54 dholland Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1990, 1993, 1995
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_quota1.c,v 1.23 2020/12/25 10:00:40 nia Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_quota1.c,v 1.24 2021/06/29 22:40:54 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -309,7 +309,6 @@ quota1_handle_cmd_quotaon(struct lwp *l,
 	struct dquot *dq;
 	int error;
 	struct pathbuf *pb;
-	struct nameidata nd;
 
 	if (type < 0 || type >= MAXQUOTAS)
 		return EINVAL;
@@ -332,12 +331,11 @@ quota1_handle_cmd_quotaon(struct lwp *l,
 	if (pb == NULL) {
 		return ENOMEM;
 	}
-	NDINIT(&nd, LOOKUP, FOLLOW, pb);
-	if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
+	error = vn_open(NULL, pb, 0, FREAD|FWRITE, 0, &vp, NULL, NULL);
+	if (error != 0) {
 		pathbuf_destroy(pb);
 		return error;
 	}
-	vp = nd.ni_vp;
 	pathbuf_destroy(pb);
 
 	VOP_UNLOCK(vp);

Reply via email to