1*723d09ceSdholland /* $NetBSD: subr_exec_fd.c,v 1.12 2021/06/29 22:40:53 dholland Exp $ */
29e46e516Spooka
39e46e516Spooka /*-
49e46e516Spooka * Copyright (c) 2008 The NetBSD Foundation, Inc.
59e46e516Spooka * All rights reserved.
69e46e516Spooka *
79e46e516Spooka * Redistribution and use in source and binary forms, with or without
89e46e516Spooka * modification, are permitted provided that the following conditions
99e46e516Spooka * are met:
109e46e516Spooka * 1. Redistributions of source code must retain the above copyright
119e46e516Spooka * notice, this list of conditions and the following disclaimer.
129e46e516Spooka * 2. Redistributions in binary form must reproduce the above copyright
139e46e516Spooka * notice, this list of conditions and the following disclaimer in the
149e46e516Spooka * documentation and/or other materials provided with the distribution.
159e46e516Spooka *
169e46e516Spooka * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
179e46e516Spooka * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
189e46e516Spooka * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
199e46e516Spooka * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
209e46e516Spooka * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
219e46e516Spooka * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
229e46e516Spooka * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
239e46e516Spooka * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
249e46e516Spooka * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
259e46e516Spooka * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
269e46e516Spooka * POSSIBILITY OF SUCH DAMAGE.
279e46e516Spooka */
289e46e516Spooka
299e46e516Spooka #include <sys/cdefs.h>
30*723d09ceSdholland __KERNEL_RCSID(0, "$NetBSD: subr_exec_fd.c,v 1.12 2021/06/29 22:40:53 dholland Exp $");
319e46e516Spooka
329e46e516Spooka #include <sys/param.h>
338e6cd4ceSriastradh #include <sys/atomic.h>
349e46e516Spooka #include <sys/file.h>
359e46e516Spooka #include <sys/filedesc.h>
369e46e516Spooka #include <sys/mutex.h>
379e46e516Spooka #include <sys/namei.h>
389e46e516Spooka #include <sys/syslog.h>
399e46e516Spooka #include <sys/vnode.h>
40a739efc5Salnsn #include <sys/ktrace.h>
41a739efc5Salnsn
42a739efc5Salnsn void
fd_ktrexecfd(void)43a739efc5Salnsn fd_ktrexecfd(void)
44a739efc5Salnsn {
45a739efc5Salnsn proc_t *p;
46a739efc5Salnsn filedesc_t *fdp;
47a739efc5Salnsn fdfile_t *ff;
48a739efc5Salnsn lwp_t *l;
49a739efc5Salnsn fdtab_t *dt;
5017201b1cSriastradh file_t *fp;
51a739efc5Salnsn int fd;
52a739efc5Salnsn
53a739efc5Salnsn l = curlwp;
54a739efc5Salnsn p = l->l_proc;
55a739efc5Salnsn fdp = p->p_fd;
568e6cd4ceSriastradh dt = atomic_load_consume(&fdp->fd_dt);
57a739efc5Salnsn
58a739efc5Salnsn for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
59a739efc5Salnsn if ((ff = dt->dt_ff[fd]) == NULL) {
60a739efc5Salnsn KASSERT(fd >= NDFDFILE);
61a739efc5Salnsn continue;
62a739efc5Salnsn }
63a739efc5Salnsn KASSERT(fd >= NDFDFILE ||
64a739efc5Salnsn ff == (fdfile_t *)fdp->fd_dfdfile[fd]);
6517201b1cSriastradh if ((fp = atomic_load_consume(&ff->ff_file)) == NULL)
66a739efc5Salnsn continue;
6717201b1cSriastradh ktr_execfd(fd, fp->f_type);
68a739efc5Salnsn }
69a739efc5Salnsn }
709e46e516Spooka
719e46e516Spooka /*
729e46e516Spooka * It is unsafe for set[ug]id processes to be started with file
739e46e516Spooka * descriptors 0..2 closed, as these descriptors are given implicit
7443375286Smaya * significance in the Standard C library. fd_checkstd() will create a
759e46e516Spooka * descriptor referencing /dev/null for each of stdin, stdout, and
769e46e516Spooka * stderr that is not already open.
779e46e516Spooka */
789e46e516Spooka #define CHECK_UPTO 3
799e46e516Spooka int
fd_checkstd(void)809e46e516Spooka fd_checkstd(void)
819e46e516Spooka {
829e46e516Spooka struct proc *p;
838f6ed30dSdholland struct pathbuf *pb;
84*723d09ceSdholland struct vnode *vp;
859e46e516Spooka filedesc_t *fdp;
869e46e516Spooka file_t *fp;
87d991fcb3Sad fdtab_t *dt;
889e46e516Spooka struct proc *pp;
899e46e516Spooka int fd, i, error, flags = FREAD|FWRITE;
909e46e516Spooka char closed[CHECK_UPTO * 3 + 1], which[3 + 1];
919e46e516Spooka
929e46e516Spooka p = curproc;
939e46e516Spooka closed[0] = '\0';
949e46e516Spooka if ((fdp = p->p_fd) == NULL)
959e46e516Spooka return (0);
968e6cd4ceSriastradh dt = atomic_load_consume(&fdp->fd_dt);
979e46e516Spooka for (i = 0; i < CHECK_UPTO; i++) {
989e46e516Spooka KASSERT(i >= NDFDFILE ||
99d991fcb3Sad dt->dt_ff[i] == (fdfile_t *)fdp->fd_dfdfile[i]);
100d991fcb3Sad if (dt->dt_ff[i]->ff_file != NULL)
1019e46e516Spooka continue;
1029e46e516Spooka snprintf(which, sizeof(which), ",%d", i);
1039e46e516Spooka strlcat(closed, which, sizeof(closed));
1049e46e516Spooka if ((error = fd_allocfile(&fp, &fd)) != 0)
1059e46e516Spooka return (error);
1069e46e516Spooka KASSERT(fd < CHECK_UPTO);
1078f6ed30dSdholland pb = pathbuf_create("/dev/null");
1088f6ed30dSdholland if (pb == NULL) {
1098f6ed30dSdholland return ENOMEM;
1108f6ed30dSdholland }
111*723d09ceSdholland error = vn_open(NULL, pb, 0, flags, 0, &vp, NULL, NULL);
112*723d09ceSdholland if (error != 0) {
1138f6ed30dSdholland pathbuf_destroy(pb);
1149e46e516Spooka fd_abort(p, fp, fd);
1159e46e516Spooka return (error);
1169e46e516Spooka }
11745b1ec74Smatt fp->f_type = DTYPE_VNODE;
118*723d09ceSdholland fp->f_vnode = vp;
1199e46e516Spooka fp->f_flag = flags;
1209e46e516Spooka fp->f_ops = &vnops;
121*723d09ceSdholland VOP_UNLOCK(vp);
1229e46e516Spooka fd_affix(p, fp, fd);
1238f6ed30dSdholland pathbuf_destroy(pb);
1249e46e516Spooka }
1259e46e516Spooka if (closed[0] != '\0') {
1260eaaa024Sad mutex_enter(&proc_lock);
1279e46e516Spooka pp = p->p_pptr;
1289e46e516Spooka mutex_enter(pp->p_lock);
1299e46e516Spooka log(LOG_WARNING, "set{u,g}id pid %d (%s) "
1309e46e516Spooka "was invoked by uid %d ppid %d (%s) "
1319e46e516Spooka "with fd %s closed\n",
1329e46e516Spooka p->p_pid, p->p_comm, kauth_cred_geteuid(pp->p_cred),
1339e46e516Spooka pp->p_pid, pp->p_comm, &closed[1]);
1349e46e516Spooka mutex_exit(pp->p_lock);
1350eaaa024Sad mutex_exit(&proc_lock);
1369e46e516Spooka }
1379e46e516Spooka return (0);
1389e46e516Spooka }
1399e46e516Spooka #undef CHECK_UPTO
140