Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys From OpenBSD, via FreeBSD: If a set{u, g}id binary is inv...



details:   https://anonhg.NetBSD.org/src/rev/b2935fb30101
branches:  trunk
changeset: 526023:b2935fb30101
user:      christos <christos%NetBSD.org@localhost>
date:      Tue Apr 23 15:11:25 2002 +0000

description:
>From OpenBSD, via FreeBSD: If a set{u,g}id binary is invoked with fd < 3
closed, open those fds to /dev/null.

XXX: This needs to be fixed in a better way. The kernel should not need to
know about /dev/null or special case 0, 1, 2.

diffstat:

 sys/kern/kern_descrip.c |  65 +++++++++++++++++++++++++++++++++++++++++++++++-
 sys/kern/kern_exec.c    |   8 ++++-
 sys/sys/filedesc.h      |   5 ++-
 3 files changed, 72 insertions(+), 6 deletions(-)

diffs (139 lines):

diff -r 9ace2428e413 -r b2935fb30101 sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c   Tue Apr 23 13:59:03 2002 +0000
+++ b/sys/kern/kern_descrip.c   Tue Apr 23 15:11:25 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_descrip.c,v 1.85 2002/03/08 20:48:40 thorpej Exp $        */
+/*     $NetBSD: kern_descrip.c,v 1.86 2002/04/23 15:11:25 christos Exp $       */
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1991, 1993
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.85 2002/03/08 20:48:40 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.86 2002/04/23 15:11:25 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -50,6 +50,7 @@
 #include <sys/vnode.h>
 #include <sys/proc.h>
 #include <sys/file.h>
+#include <sys/namei.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/stat.h>
@@ -1374,3 +1375,63 @@
                if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
                        (void) fdrelease(p, fd);
 }
+
+/*
+ * It is unsafe for set[ug]id processes to be started with file
+ * descriptors 0..2 closed, as these descriptors are given implicit
+ * significance in the Standard C library.  fdcheckstd() will create a
+ * descriptor referencing /dev/null for each of stdin, stdout, and
+ * stderr that is not already open.
+ */
+int
+fdcheckstd(p)
+       struct proc *p;
+{
+       struct nameidata nd;
+       struct filedesc *fdp;
+       struct file *fp;
+       register_t retval;
+       int fd, i, error = 0, flags = FREAD|FWRITE, devnull = -1, logged = 0;
+
+       if ((fdp = p->p_fd) == NULL)
+              return 0;
+       for (i = 0; i < 3; i++) {
+               if (fdp->fd_ofiles[i] != NULL)
+                       continue;
+               if (!logged) {
+                       log(LOG_WARNING, "set{u,g}id pid %d (%s) was invoked "
+                           "with fd 0, 1, or 2 closed\n", p->p_pid, p->p_comm);
+                       logged++;
+               }
+               if (devnull < 0) {
+                       if ((error = falloc(p, &fp, &fd)) != 0)
+                               return error;
+                       NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null",
+                           p);
+                       if ((error = vn_open(&nd, flags, 0)) != 0) {
+                               FILE_UNUSE(fp, p);
+                               ffree(fp);
+                               fdremove(p->p_fd, fd);
+                               return error;
+                       }
+                       fp->f_data = (caddr_t)nd.ni_vp;
+                       fp->f_flag = flags;
+                       fp->f_ops = &vnops;
+                       fp->f_type = DTYPE_VNODE;
+                       VOP_UNLOCK(nd.ni_vp, 0);
+                       devnull = fd;
+               } else {
+restart:
+                       if ((error = fdalloc(p, 0, &fd)) != 0) {
+                               if (error == ENOSPC) {
+                                       fdexpand(p);
+                                       goto restart;
+                               }
+                               return error;
+                       }
+                       if ((error = finishdup(p, devnull, fd, &retval)) != 0)
+                               return error;
+               }
+       }
+       return error;
+}
diff -r 9ace2428e413 -r b2935fb30101 sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c      Tue Apr 23 13:59:03 2002 +0000
+++ b/sys/kern/kern_exec.c      Tue Apr 23 15:11:25 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_exec.c,v 1.151 2002/04/02 20:18:07 jdolecek Exp $ */
+/*     $NetBSD: kern_exec.c,v 1.152 2002/04/23 15:11:25 christos Exp $ */
 
 /*-
  * Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.151 2002/04/02 20:18:07 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.152 2002/04/23 15:11:25 christos Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_syscall_debug.h"
@@ -625,6 +625,10 @@
                 */
                p_sugid(p);
 
+               /* Make sure file descriptors 0..2 are in use. */
+               if ((error = fdcheckstd(p)) != 0)
+                       goto exec_abort;
+
                p->p_ucred = crcopy(cred);
 #ifdef KTRACE
                /*
diff -r 9ace2428e413 -r b2935fb30101 sys/sys/filedesc.h
--- a/sys/sys/filedesc.h        Tue Apr 23 13:59:03 2002 +0000
+++ b/sys/sys/filedesc.h        Tue Apr 23 15:11:25 2002 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: filedesc.h,v 1.23 2001/06/14 20:32:49 thorpej Exp $    */
+/*     $NetBSD: filedesc.h,v 1.24 2002/04/23 15:11:26 christos Exp $   */
 
 /*
  * Copyright (c) 1990, 1993
@@ -114,8 +114,9 @@
 void   fdclear(struct proc *p);
 void   fdfree(struct proc *p);
 void   fdremove(struct filedesc *, int);
-int    fdrelease(struct proc *p, int);
+int    fdrelease(struct proc *, int);
 void   fdcloseexec(struct proc *);
+int    fdcheckstd(struct proc *);
 
 struct file *fd_getfile(struct filedesc *, int);
 



Home | Main Index | Thread Index | Old Index