xref: /freebsd/lib/libcasper/libcasper/zygote.c (revision 9768746b)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2012 The FreeBSD Foundation
5  * Copyright (c) 2015 Mariusz Zaborski <oshogbo@FreeBSD.org>
6  * Copyright (c) 2017 Robert N. M. Watson
7  *
8  * This software was developed by Pawel Jakub Dawidek under sponsorship from
9  * the FreeBSD Foundation.
10  *
11  * All rights reserved.
12  * This software was developed by SRI International and the University of
13  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
14  * ("CTSRD"), as part of the DARPA CRASH research programme.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
40 
41 #include <sys/types.h>
42 #include <sys/capsicum.h>
43 #include <sys/procdesc.h>
44 #include <sys/socket.h>
45 #include <sys/nv.h>
46 
47 #include <assert.h>
48 #include <err.h>
49 #include <errno.h>
50 #include <stdbool.h>
51 #include <stdlib.h>
52 #include <strings.h>
53 #include <unistd.h>
54 
55 #include "libcasper_impl.h"
56 #include "zygote.h"
57 
58 /* Zygote info. */
59 static int	zygote_sock = -1;
60 
61 #define	ZYGOTE_SERVICE_EXECUTE	1
62 
63 int
64 zygote_clone(uint64_t funcidx, int *chanfdp, int *procfdp)
65 {
66 	nvlist_t *nvl;
67 	int error;
68 
69 	if (zygote_sock == -1) {
70 		/* Zygote didn't start. */
71 		errno = ENXIO;
72 		return (-1);
73 	}
74 
75 	nvl = nvlist_create(0);
76 	nvlist_add_number(nvl, "funcidx", funcidx);
77 	nvl = nvlist_xfer(zygote_sock, nvl, 0);
78 	if (nvl == NULL)
79 		return (-1);
80 	if (nvlist_exists_number(nvl, "error")) {
81 		error = (int)nvlist_get_number(nvl, "error");
82 		nvlist_destroy(nvl);
83 		errno = error;
84 		return (-1);
85 	}
86 
87 	*chanfdp = nvlist_take_descriptor(nvl, "chanfd");
88 	*procfdp = nvlist_take_descriptor(nvl, "procfd");
89 
90 	nvlist_destroy(nvl);
91 	return (0);
92 }
93 
94 int
95 zygote_clone_service_execute(int *chanfdp, int *procfdp)
96 {
97 
98 	return (zygote_clone(ZYGOTE_SERVICE_EXECUTE, chanfdp, procfdp));
99 }
100 
101 /*
102  * This function creates sandboxes on-demand whoever has access to it via
103  * 'sock' socket. Function sends two descriptors to the caller: process
104  * descriptor of the sandbox and socket pair descriptor for communication
105  * between sandbox and its owner.
106  */
107 static void
108 zygote_main(int *sockp)
109 {
110 	int error, procfd;
111 	int chanfd[2];
112 	nvlist_t *nvlin, *nvlout;
113 	uint64_t funcidx;
114 	zygote_func_t *func;
115 	pid_t pid;
116 
117 	fd_fix_environment(sockp);
118 
119 	assert(*sockp > STDERR_FILENO);
120 
121 	setproctitle("zygote");
122 
123 	for (;;) {
124 		nvlin = nvlist_recv(*sockp, 0);
125 		if (nvlin == NULL) {
126 			if (errno == ENOTCONN) {
127 				/* Casper exited. */
128 				_exit(0);
129 			}
130 			continue;
131 		}
132 		funcidx = nvlist_get_number(nvlin, "funcidx");
133 		nvlist_destroy(nvlin);
134 
135 		switch (funcidx) {
136 		case ZYGOTE_SERVICE_EXECUTE:
137 			func = service_execute;
138 			break;
139 		default:
140 			_exit(0);
141 		}
142 
143 		/*
144 		 * Someone is requesting a new process, create one.
145 		 */
146 		procfd = -1;
147 		chanfd[0] = -1;
148 		chanfd[1] = -1;
149 		error = 0;
150 		if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0,
151 		    chanfd) == -1) {
152 			error = errno;
153 			goto send;
154 		}
155 		pid = pdfork(&procfd, 0);
156 		switch (pid) {
157 		case -1:
158 			/* Failure. */
159 			error = errno;
160 			break;
161 		case 0:
162 			/* Child. */
163 			close(*sockp);
164 			close(chanfd[0]);
165 			func(chanfd[1]);
166 			/* NOTREACHED */
167 			_exit(1);
168 		default:
169 			/* Parent. */
170 			close(chanfd[1]);
171 			break;
172 		}
173 send:
174 		nvlout = nvlist_create(0);
175 		if (error != 0) {
176 			nvlist_add_number(nvlout, "error", (uint64_t)error);
177 			if (chanfd[0] >= 0)
178 				close(chanfd[0]);
179 			if (procfd >= 0)
180 				close(procfd);
181 		} else {
182 			nvlist_move_descriptor(nvlout, "chanfd", chanfd[0]);
183 			nvlist_move_descriptor(nvlout, "procfd", procfd);
184 		}
185 		(void)nvlist_send(*sockp, nvlout);
186 		nvlist_destroy(nvlout);
187 	}
188 	/* NOTREACHED */
189 }
190 
191 int
192 zygote_init(void)
193 {
194 	int serrno, sp[2];
195 	pid_t pid;
196 
197 	if (socketpair(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, sp) == -1)
198 		return (-1);
199 
200 	pid = fork();
201 	switch (pid) {
202 	case -1:
203 		/* Failure. */
204 		serrno = errno;
205 		close(sp[0]);
206 		close(sp[1]);
207 		errno = serrno;
208 		return (-1);
209 	case 0:
210 		/* Child. */
211 		close(sp[0]);
212 		zygote_main(&sp[1]);
213 		/* NOTREACHED */
214 		abort();
215 	default:
216 		/* Parent. */
217 		zygote_sock = sp[0];
218 		close(sp[1]);
219 		return (0);
220 	}
221 	/* NOTREACHED */
222 }
223