diff options
author | nectar <nectar@FreeBSD.org> | 2002-04-19 00:45:29 +0000 |
---|---|---|
committer | nectar <nectar@FreeBSD.org> | 2002-04-19 00:45:29 +0000 |
commit | fcc5ad0935b7186f4b02cdb9e21265c4b22f7bdc (patch) | |
tree | cc853206d1f9aa9281220f43c34852831f4734aa | |
parent | 57865251c86fc1a67f3fe94878e07688c988ee3d (diff) | |
download | FreeBSD-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.c | 65 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 4 | ||||
-rw-r--r-- | sys/sys/filedesc.h | 1 |
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); |