diff --git a/sys/conf/files b/sys/conf/files index 7c9970f0d8ba..05b85eb8f680 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.927 2008/11/18 11:36:58 pooka Exp $ +# $NetBSD: files,v 1.928 2008/11/18 13:01:41 pooka Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -1435,6 +1435,7 @@ file kern/subr_devsw.c file kern/subr_disk.c file kern/subr_iostat.c file kern/subr_evcnt.c +file kern/subr_exec_fd.c file kern/subr_extent.c file kern/subr_hash.c file kern/subr_kmem.c diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index 9f5623894c32..c8042088433a 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_descrip.c,v 1.183 2008/11/18 11:36:58 pooka Exp $ */ +/* $NetBSD: kern_descrip.c,v 1.184 2008/11/18 13:01:41 pooka Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -67,16 +67,14 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.183 2008/11/18 11:36:58 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.184 2008/11/18 13:01:41 pooka Exp $"); #include #include #include #include -#include #include #include -#include #include #include #include @@ -84,16 +82,16 @@ __KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.183 2008/11/18 11:36:58 pooka Exp #include #include #include -#include #include #include #include #include #include #include -#include #include #include +#include +#include static int file_ctor(void *, void *, int); static void file_dtor(void *, void *); @@ -1518,122 +1516,6 @@ fd_dupopen(int old, int *new, int mode, int error) return error; } -/* - * Close open files on exec. - */ -void -fd_closeexec(void) -{ - proc_t *p; - filedesc_t *fdp; - fdfile_t *ff; - lwp_t *l; - int fd; - - l = curlwp; - p = l->l_proc; - fdp = p->p_fd; - - cwdunshare(p); - - if (p->p_cwdi->cwdi_edir) { - vrele(p->p_cwdi->cwdi_edir); - } - - if (fdp->fd_refcnt > 1) { - fdp = fd_copy(); - fd_free(); - p->p_fd = fdp; - l->l_fd = fdp; - } - if (!fdp->fd_exclose) { - return; - } - fdp->fd_exclose = false; - - for (fd = 0; fd <= fdp->fd_lastfile; fd++) { - if ((ff = fdp->fd_ofiles[fd]) == NULL) { - KASSERT(fd >= NDFDFILE); - continue; - } - KASSERT(fd >= NDFDFILE || - ff == (fdfile_t *)fdp->fd_dfdfile[fd]); - if (ff->ff_file == NULL) - continue; - if (ff->ff_exclose) { - /* - * We need a reference to close the file. - * No other threads can see the fdfile_t at - * this point, so don't bother locking. - */ - KASSERT((ff->ff_refcnt & FR_CLOSING) == 0); - ff->ff_refcnt++; - fd_close(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. - */ -#define CHECK_UPTO 3 -int -fd_checkstd(void) -{ - struct proc *p; - struct nameidata nd; - filedesc_t *fdp; - file_t *fp; - struct proc *pp; - int fd, i, error, flags = FREAD|FWRITE; - char closed[CHECK_UPTO * 3 + 1], which[3 + 1]; - - p = curproc; - closed[0] = '\0'; - if ((fdp = p->p_fd) == NULL) - return (0); - for (i = 0; i < CHECK_UPTO; i++) { - KASSERT(i >= NDFDFILE || - fdp->fd_ofiles[i] == (fdfile_t *)fdp->fd_dfdfile[i]); - if (fdp->fd_ofiles[i]->ff_file != NULL) - continue; - snprintf(which, sizeof(which), ",%d", i); - strlcat(closed, which, sizeof(closed)); - if ((error = fd_allocfile(&fp, &fd)) != 0) - return (error); - KASSERT(fd < CHECK_UPTO); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null"); - if ((error = vn_open(&nd, flags, 0)) != 0) { - fd_abort(p, fp, fd); - return (error); - } - fp->f_data = nd.ni_vp; - fp->f_flag = flags; - fp->f_ops = &vnops; - fp->f_type = DTYPE_VNODE; - VOP_UNLOCK(nd.ni_vp, 0); - fd_affix(p, fp, fd); - } - if (closed[0] != '\0') { - mutex_enter(proc_lock); - pp = p->p_pptr; - mutex_enter(pp->p_lock); - log(LOG_WARNING, "set{u,g}id pid %d (%s) " - "was invoked by uid %d ppid %d (%s) " - "with fd %s closed\n", - p->p_pid, p->p_comm, kauth_cred_geteuid(pp->p_cred), - pp->p_pid, pp->p_comm, &closed[1]); - mutex_exit(pp->p_lock); - mutex_exit(proc_lock); - } - return (0); -} -#undef CHECK_UPTO - /* * Sets descriptor owner. If the owner is a process, 'pgid' * is set to positive value, process ID. If the owner is process group, diff --git a/sys/kern/subr_exec_fd.c b/sys/kern/subr_exec_fd.c new file mode 100644 index 000000000000..40861b6f600c --- /dev/null +++ b/sys/kern/subr_exec_fd.c @@ -0,0 +1,158 @@ +/* $NetBSD: subr_exec_fd.c,v 1.1 2008/11/18 13:01:41 pooka Exp $ */ + +/*- + * Copyright (c) 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * File descriptor related subroutines for exec. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: subr_exec_fd.c,v 1.1 2008/11/18 13:01:41 pooka Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +/* + * Close open files on exec. + */ +void +fd_closeexec(void) +{ + proc_t *p; + filedesc_t *fdp; + fdfile_t *ff; + lwp_t *l; + int fd; + + l = curlwp; + p = l->l_proc; + fdp = p->p_fd; + + cwdunshare(p); + + if (p->p_cwdi->cwdi_edir) { + vrele(p->p_cwdi->cwdi_edir); + } + + if (fdp->fd_refcnt > 1) { + fdp = fd_copy(); + fd_free(); + p->p_fd = fdp; + l->l_fd = fdp; + } + if (!fdp->fd_exclose) { + return; + } + fdp->fd_exclose = false; + + for (fd = 0; fd <= fdp->fd_lastfile; fd++) { + if ((ff = fdp->fd_ofiles[fd]) == NULL) { + KASSERT(fd >= NDFDFILE); + continue; + } + KASSERT(fd >= NDFDFILE || + ff == (fdfile_t *)fdp->fd_dfdfile[fd]); + if (ff->ff_file == NULL) + continue; + if (ff->ff_exclose) { + /* + * We need a reference to close the file. + * No other threads can see the fdfile_t at + * this point, so don't bother locking. + */ + KASSERT((ff->ff_refcnt & FR_CLOSING) == 0); + ff->ff_refcnt++; + fd_close(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. + */ +#define CHECK_UPTO 3 +int +fd_checkstd(void) +{ + struct proc *p; + struct nameidata nd; + filedesc_t *fdp; + file_t *fp; + struct proc *pp; + int fd, i, error, flags = FREAD|FWRITE; + char closed[CHECK_UPTO * 3 + 1], which[3 + 1]; + + p = curproc; + closed[0] = '\0'; + if ((fdp = p->p_fd) == NULL) + return (0); + for (i = 0; i < CHECK_UPTO; i++) { + KASSERT(i >= NDFDFILE || + fdp->fd_ofiles[i] == (fdfile_t *)fdp->fd_dfdfile[i]); + if (fdp->fd_ofiles[i]->ff_file != NULL) + continue; + snprintf(which, sizeof(which), ",%d", i); + strlcat(closed, which, sizeof(closed)); + if ((error = fd_allocfile(&fp, &fd)) != 0) + return (error); + KASSERT(fd < CHECK_UPTO); + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null"); + if ((error = vn_open(&nd, flags, 0)) != 0) { + fd_abort(p, fp, fd); + return (error); + } + fp->f_data = nd.ni_vp; + fp->f_flag = flags; + fp->f_ops = &vnops; + fp->f_type = DTYPE_VNODE; + VOP_UNLOCK(nd.ni_vp, 0); + fd_affix(p, fp, fd); + } + if (closed[0] != '\0') { + mutex_enter(proc_lock); + pp = p->p_pptr; + mutex_enter(pp->p_lock); + log(LOG_WARNING, "set{u,g}id pid %d (%s) " + "was invoked by uid %d ppid %d (%s) " + "with fd %s closed\n", + p->p_pid, p->p_comm, kauth_cred_geteuid(pp->p_cred), + pp->p_pid, pp->p_comm, &closed[1]); + mutex_exit(pp->p_lock); + mutex_exit(proc_lock); + } + return (0); +} +#undef CHECK_UPTO