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