Apply by doing
	cd /usr/src/sys/kern
	patch -p0 < fdalloc.patch

Then rebuild the kernel you use.

Index: kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
retrieving revision 1.17
retrieving revision 1.21
diff -u -r1.17 -r1.21
--- kern_exec.c	1998/02/20 14:45:16	1.17
+++ kern_exec.c	1998/07/02 09:03:42	1.21
@@ -1,4 +1,4 @@
-/*	$OpenBSD: kern_exec.c,v 1.17 1998/02/20 14:45:16 niklas Exp $	*/
+/*	$OpenBSD: kern_exec.c,v 1.21 1998/07/02 09:03:42 deraadt Exp $	*/
 /*	$NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $	*/
 
 /*-
@@ -456,6 +456,8 @@
 	 * MNT_NOEXEC and P_TRACED have already been used to disable s[ug]id.
 	 */
 	if ((attr.va_mode & (VSUID | VSGID))) {
+		int i;
+
 #ifdef KTRACE
 		/*
 		 * If process is being ktraced, turn off - unless
@@ -474,6 +476,38 @@
 			p->p_ucred->cr_gid = attr.va_gid;
 		p->p_flag |= P_SUGID;
 		p->p_flag |= P_SUGIDEXEC;
+
+		/*
+		 * XXX For setuid processes, attempt to ensure that
+		 * stdin, stdout, and stderr are already allocated.
+		 * We do not want userland to accidentally allocate
+		 * descriptors in this range which has implied meaning
+		 * to libc.
+		 */
+		for (i = 0; i < 3; i++) {
+			extern struct fileops vnops;
+			struct nameidata nd;
+			struct file *fp;
+			int indx;
+
+			if (p->p_fd->fd_ofiles[i] == NULL) {
+				if ((error = falloc(p, &fp, &indx)) != 0)
+					continue;
+				NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE,
+				    "/dev/null", p);
+				if ((error = vn_open(&nd, FREAD, 0)) != 0) {
+					ffree(fp);
+					p->p_fd->fd_ofiles[indx] = NULL;
+					break;
+				}
+				fp->f_flag = FREAD;
+				fp->f_type = DTYPE_VNODE;
+				fp->f_ops = &vnops;
+				fp->f_data = (caddr_t)nd.ni_vp;
+				VOP_UNLOCK(nd.ni_vp, 0, p);
+			}
+		}
+
 	} else
 		p->p_flag &= ~P_SUGID;
 	p->p_cred->p_svuid = p->p_ucred->cr_uid;
