Index: kern/vfs_syscalls.c
===================================================================
--- kern/vfs_syscalls.c	(revision 188457)
+++ kern/vfs_syscalls.c	(working copy)
@@ -1097,7 +1097,7 @@
 		 * wonderous happened deep below and we just pass it up
 		 * pretending we know what we do.
 		 */
-		if (error == ENXIO && fp->f_ops != &badfileops) {
+		if (error == ENXIO && fp->f_ops != &newfileops) {
 			fdrop(fp, td);
 			td->td_retval[0] = indx;
 			return (0);
@@ -1137,7 +1137,7 @@
 	 * If the file wasn't claimed by devfs bind it to the normal
 	 * vnode operations here.
 	 */
-	if (fp->f_ops == &badfileops) {
+	if (fp->f_ops == &newfileops) {
 		KASSERT(vp->v_type != VFIFO, ("Unexpected fifo."));
 		fp->f_seqcount = 1;
 		finit(fp, flags & FMASK, DTYPE_VNODE, vp, &vnops);
Index: kern/tty.c
===================================================================
--- kern/tty.c	(revision 188457)
+++ kern/tty.c	(working copy)
@@ -1700,7 +1700,8 @@
 	if ((fdp = p->p_fd) == NULL)
 		return (EBADF);
 	FILEDESC_SLOCK(fdp);
-	if ((fp = fget_locked(fdp, fd)) == NULL || fp->f_ops == &badfileops) {
+	if ((fp = fget_locked(fdp, fd)) == NULL || fp->f_ops == &badfileops
+	    || fp->f_ops == &newfileops) {
 		FILEDESC_SUNLOCK(fdp);
 		return (EBADF);
 	}
Index: kern/kern_descrip.c
===================================================================
--- kern/kern_descrip.c	(revision 188457)
+++ kern/kern_descrip.c	(working copy)
@@ -1439,7 +1439,7 @@
 	if (resultfp)
 		fhold(fp);
 	fp->f_cred = crhold(td->td_ucred);
-	fp->f_ops = &badfileops;
+	fp->f_ops = &newfileops;
 	fp->f_data = NULL;
 	fp->f_vnode = NULL;
 	FILEDESC_XLOCK(p->p_fd);
@@ -1583,7 +1583,8 @@
 	newfdp->fd_freefile = -1;
 	for (i = 0; i <= fdp->fd_lastfile; ++i) {
 		if (fdisused(fdp, i) &&
-		    fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE) {
+		    fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE &&
+		    fdp->fd_ofiles[i]->f_ops != &newfileops) {
 			newfdp->fd_ofiles[i] = fdp->fd_ofiles[i];
 			newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i];
 			fhold(newfdp->fd_ofiles[i]);
@@ -2049,7 +2050,8 @@
 	if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
 		return (EBADF);
 	FILEDESC_SLOCK(fdp);
-	if ((fp = fget_locked(fdp, fd)) == NULL || fp->f_ops == &badfileops) {
+	if ((fp = fget_locked(fdp, fd)) == NULL || fp->f_ops == &badfileops
+	    || fp->f_ops == &newfileops) {
 		FILEDESC_SUNLOCK(fdp);
 		return (EBADF);
 	}
@@ -2207,7 +2209,7 @@
 	error = 0;
 	if (fp->f_count != 0)
 		panic("fdrop: count %d", fp->f_count);
-	if (fp->f_ops != &badfileops)
+	if (fp->f_ops != &badfileops && fp->f_ops != &newfileops)
 		error = fo_close(fp, td);
 	/*
 	 * The f_cdevpriv cannot be assigned non-NULL value while we
@@ -3199,6 +3201,14 @@
 	return (EBADF);
 }
 
+/*
+ * We have two different file descriptor "bad" operation vectors, both
+ * implemented by the badfo_ functions.  newfileops is used for new file
+ * descriptors that aren't yet ready for use; badfileops is used for revoked
+ * or otherwise invalidated file descripors.  There are a number of places
+ * where comparisons are done, such as in fork(2) where bad file descriptors
+ * are inherited but new ones aren't.
+ */
 struct fileops badfileops = {
 	.fo_read = badfo_readwrite,
 	.fo_write = badfo_readwrite,
@@ -3210,6 +3220,16 @@
 	.fo_close = badfo_close,
 };
 
+struct fileops newfileops = {
+	.fo_read = badfo_readwrite,
+	.fo_write = badfo_readwrite,
+	.fo_truncate = badfo_truncate,
+	.fo_ioctl = badfo_ioctl,
+	.fo_poll = badfo_poll,
+	.fo_kqfilter = badfo_kqfilter,
+	.fo_stat = badfo_stat,
+	.fo_close = badfo_close,
+};
 
 /*-------------------------------------------------------------------*/
 
Index: fs/devfs/devfs_vnops.c
===================================================================
--- fs/devfs/devfs_vnops.c	(revision 188457)
+++ fs/devfs/devfs_vnops.c	(working copy)
@@ -975,7 +975,7 @@
 	if(fp == NULL)
 		return (error);
 #endif
-	if (fp->f_ops == &badfileops)
+	if (fp->f_ops == &newfileops)
 		finit(fp, fp->f_flag, DTYPE_VNODE, dev, &devfs_ops_f);
 	return (error);
 }
Index: fs/fifofs/fifo_vnops.c
===================================================================
--- fs/fifofs/fifo_vnops.c	(revision 188457)
+++ fs/fifofs/fifo_vnops.c	(working copy)
@@ -296,7 +296,7 @@
 	}
 	mtx_unlock(&fifo_mtx);
 	KASSERT(fp != NULL, ("can't fifo/vnode bypass"));
-	KASSERT(fp->f_ops == &badfileops, ("not badfileops in fifo_open"));
+	KASSERT(fp->f_ops == &newfileops, ("not badfileops in fifo_open"));
 	finit(fp, fp->f_flag, DTYPE_FIFO, fip, &fifo_ops_f);
 	return (0);
 }
Index: sys/file.h
===================================================================
--- sys/file.h	(revision 188457)
+++ sys/file.h	(working copy)
@@ -169,6 +169,7 @@
 
 extern struct fileops vnops;
 extern struct fileops badfileops;
+extern struct fileops newfileops;
 extern struct fileops socketops;
 extern int maxfiles;		/* kernel limit on number of open files */
 extern int maxfilesperproc;	/* per process limit on number of open files */
