summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornectar <nectar@FreeBSD.org>2002-04-19 00:45:29 +0000
committernectar <nectar@FreeBSD.org>2002-04-19 00:45:29 +0000
commitfcc5ad0935b7186f4b02cdb9e21265c4b22f7bdc (patch)
treecc853206d1f9aa9281220f43c34852831f4734aa
parent57865251c86fc1a67f3fe94878e07688c988ee3d (diff)
downloadFreeBSD-src-fcc5ad0935b7186f4b02cdb9e21265c4b22f7bdc.zip
FreeBSD-src-fcc5ad0935b7186f4b02cdb9e21265c4b22f7bdc.tar.gz
When exec'ing a set[ug]id program, make sure that the stdio file descriptors
(0, 1, 2) are allocated by opening /dev/null for any which are not already open. Reviewed by: alfred, phk MFC after: 2 days
-rw-r--r--sys/kern/kern_descrip.c65
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/sys/filedesc.h1
3 files changed, 70 insertions, 0 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 136bd61..0476493 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -53,6 +53,7 @@
#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <sys/proc.h>
+#include <sys/namei.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/filio.h>
@@ -1498,6 +1499,70 @@ fdcloseexec(td)
}
/*
+ * 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(td)
+ struct thread *td;
+{
+ struct nameidata nd;
+ struct filedesc *fdp;
+ struct file *fp;
+ register_t retval;
+ int fd, i, error, flags, devnull;
+
+ fdp = td->td_proc->p_fd;
+ if (fdp == NULL)
+ return (0);
+ devnull = -1;
+ error = 0;
+ for (i = 0; i < 3; i++) {
+ if (fdp->fd_ofiles[i] != NULL)
+ continue;
+ if (devnull < 0) {
+ FILEDESC_LOCK(fdp);
+ error = falloc(td, &fp, &fd);
+ FILEDESC_UNLOCK(fdp);
+ if (error != 0)
+ break;
+ NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null",
+ td);
+ flags = FREAD | FWRITE;
+ error = vn_open(&nd, &flags, 0);
+ if (error != 0) {
+ FILEDESC_LOCK(fdp);
+ fdp->fd_ofiles[i] = NULL;
+ FILEDESC_UNLOCK(fdp);
+ fdrop(fp, td);
+ break;
+ }
+ NDFREE(&nd, NDF_ONLY_PNBUF);
+ 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, td);
+ devnull = fd;
+ } else {
+ FILEDESC_LOCK(fdp);
+ error = fdalloc(td, 0, &fd);
+ if (error != 0) {
+ FILEDESC_UNLOCK(fdp);
+ break;
+ }
+ error = do_dup(fdp, devnull, fd, &retval, td);
+ if (error != 0)
+ break;
+ }
+ }
+ return (error);
+}
+
+/*
* Internal form of close.
* Decrement reference count on file structure.
* Note: td may be NULL when closing a file
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 1b32699..af4edae 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -368,6 +368,10 @@ interpret:
vrele(vtmp);
}
}
+ /* Make sure file descriptors 0..2 are in use. */
+ error = fdcheckstd(td);
+ if (error != 0)
+ goto exec_fail_dealloc;
/*
* Set the new credentials.
*/
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 160bda2..d2d108c 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -147,6 +147,7 @@ int falloc(struct thread *p, struct file **resultfp, int *resultfd);
int fdalloc(struct thread *p, int want, int *result);
int fdavail(struct thread *td, int n);
void fdcloseexec(struct thread *td);
+int fdcheckstd(struct thread *td);
struct filedesc *fdcopy(struct thread *td);
void fdfree(struct thread *td);
struct filedesc *fdinit(struct thread *td);
OpenPOWER on IntegriCloud