xref: /netbsd-src/sys/kern/subr_exec_fd.c (revision 723d09ce8e2d3ae8b20c3e0b7e19547f389a870f)
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