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;