1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #if !defined(_GNU_SOURCE)
26 #define _GNU_SOURCE
27 #endif
28 
29 #include "private-lib-core.h"
30 #include <unistd.h>
31 
32 void
lws_spawn_timeout(struct lws_sorted_usec_list * sul)33 lws_spawn_timeout(struct lws_sorted_usec_list *sul)
34 {
35 	struct lws_spawn_piped *lsp = lws_container_of(sul,
36 					struct lws_spawn_piped, sul);
37 
38 	lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__);
39 
40 	lws_spawn_piped_kill_child_process(lsp);
41 }
42 
43 static struct lws *
lws_create_basic_wsi(struct lws_context * context,int tsi,const struct lws_role_ops * ops)44 lws_create_basic_wsi(struct lws_context *context, int tsi,
45 		     const struct lws_role_ops *ops)
46 {
47 	struct lws *new_wsi;
48 
49 	if (!context->vhost_list)
50 		return NULL;
51 
52 	if ((unsigned int)context->pt[tsi].fds_count ==
53 	    context->fd_limit_per_thread - 1) {
54 		lwsl_err("no space for new conn\n");
55 		return NULL;
56 	}
57 
58 	new_wsi = lws_zalloc(sizeof(*new_wsi), "new wsi");
59 	if (new_wsi == NULL) {
60 		lwsl_err("Out of memory for new connection\n");
61 		return NULL;
62 	}
63 
64 	new_wsi->tsi = tsi;
65 	new_wsi->context = context;
66 	new_wsi->pending_timeout = NO_PENDING_TIMEOUT;
67 	new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
68 
69 	/* initialize the instance struct */
70 
71 	lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops);
72 
73 	new_wsi->hdr_parsing_completed = 0;
74 	new_wsi->position_in_fds_table = LWS_NO_FDS_POS;
75 
76 	/*
77 	 * these can only be set once the protocol is known
78 	 * we set an unestablished connection's protocol pointer
79 	 * to the start of the defauly vhost supported list, so it can look
80 	 * for matching ones during the handshake
81 	 */
82 
83 	new_wsi->user_space = NULL;
84 	new_wsi->desc.sockfd = LWS_SOCK_INVALID;
85 	context->count_wsi_allocated++;
86 
87 	return new_wsi;
88 }
89 
90 void
lws_spawn_piped_destroy(struct lws_spawn_piped ** _lsp)91 lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp)
92 {
93 	struct lws_spawn_piped *lsp = *_lsp;
94 	int n;
95 
96 	if (!lsp)
97 		return;
98 
99 	for (n = 0; n < 3; n++) {
100 		if (lsp->pipe_fds[n][!!(n == 0)] == 0)
101 			lwsl_err("ZERO FD IN CGI CLOSE");
102 
103 		if (lsp->pipe_fds[n][!!(n == 0)] >= 0) {
104 			close(lsp->pipe_fds[n][!!(n == 0)]);
105 			lsp->pipe_fds[n][!!(n == 0)] = LWS_SOCK_INVALID;
106 		}
107 	}
108 
109 	lws_dll2_remove(&lsp->dll);
110 
111 	lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul,
112 			 NULL, LWS_SET_TIMER_USEC_CANCEL);
113 
114 	lws_free_set_NULL((*_lsp));
115 }
116 
117 int
lws_spawn_reap(struct lws_spawn_piped * lsp)118 lws_spawn_reap(struct lws_spawn_piped *lsp)
119 {
120 	long hz = sysconf(_SC_CLK_TCK); /* accounting Hz */
121 	void *opaque = lsp->info.opaque;
122 	lsp_cb_t cb = lsp->info.reap_cb;
123 	struct lws_spawn_piped temp;
124 	struct tms tms;
125 	int n;
126 
127 	if (lsp->child_pid < 1)
128 		return 0;
129 
130 	/* check if exited, do not reap yet */
131 
132 	memset(&lsp->si, 0, sizeof(lsp->si));
133 	n = waitid(P_PID, lsp->child_pid, &lsp->si, WEXITED | WNOHANG | WNOWAIT);
134 	if (n < 0) {
135 		lwsl_info("%s: child %d still running\n", __func__, lsp->child_pid);
136 		return 0;
137 	}
138 
139 	if (!lsp->si.si_code)
140 		return 0;
141 
142 	/* his process has exited... */
143 
144 	if (!lsp->reaped) {
145 		/* mark the earliest time we knew he had gone */
146 		lsp->reaped = lws_now_usecs();
147 
148 		/*
149 		 * Switch the timeout to restrict the amount of grace time
150 		 * to drain stdwsi
151 		 */
152 
153 		lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
154 				 &lsp->sul, lws_spawn_timeout,
155 				 5 * LWS_US_PER_SEC);
156 	}
157 
158 	/*
159 	 * Stage finalizing our reaction to the process going down until the
160 	 * stdwsi flushed whatever is in flight and all noticed they were
161 	 * closed.  For that reason, each stdwsi close must call lws_spawn_reap
162 	 * to check if that was the last one and we can proceed with the reap.
163 	 */
164 
165 	if (!lsp->ungraceful && lsp->pipes_alive) {
166 		lwsl_debug("%s: stdwsi alive, not reaping\n", __func__);
167 		return 0;
168 	}
169 
170 	/* we reached the reap point, no need for timeout wait */
171 
172 	lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi, &lsp->sul, NULL,
173 			 LWS_SET_TIMER_USEC_CANCEL);
174 
175 	/*
176 	 * All the stdwsi went down, nothing more is coming... it's over
177 	 * Collect the final information and then reap the dead process
178 	 */
179 
180 	if (times(&tms) != (clock_t) -1) {
181 		/*
182 		 * Cpu accounting in us
183 		 */
184 		lsp->accounting[0] = ((uint64_t)tms.tms_cstime * 1000000) / hz;
185 		lsp->accounting[1] = ((uint64_t)tms.tms_cutime * 1000000) / hz;
186 		lsp->accounting[2] = ((uint64_t)tms.tms_stime * 1000000) / hz;
187 		lsp->accounting[3] = ((uint64_t)tms.tms_utime * 1000000) / hz;
188 	}
189 
190 	temp = *lsp;
191 	waitid(P_PID, lsp->child_pid, &lsp->si, WEXITED | WNOHANG);
192 	lsp->child_pid = -1;
193 
194 	/* destroy the lsp itself first (it's freed and plsp set NULL */
195 
196 	if (lsp->info.plsp)
197 		lws_spawn_piped_destroy(lsp->info.plsp);
198 
199 	/* then do the parent callback informing it's destroyed */
200 
201 	if (cb)
202 		cb(opaque, temp.accounting, &temp.si,
203 		   temp.we_killed_him_timeout |
204 			   (temp.we_killed_him_spew << 1));
205 
206 	return 1; /* was reaped */
207 }
208 
209 int
lws_spawn_piped_kill_child_process(struct lws_spawn_piped * lsp)210 lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp)
211 {
212 	int status, n;
213 
214 	if (lsp->child_pid <= 0)
215 		return 1;
216 
217 	lsp->ungraceful = 1; /* don't wait for flushing, just kill it */
218 
219 	if (lws_spawn_reap(lsp))
220 		/* that may have invalidated lsp */
221 		return 0;
222 
223 	/* kill the process group */
224 	n = kill(-lsp->child_pid, SIGTERM);
225 	lwsl_debug("%s: SIGTERM child PID %d says %d (errno %d)\n", __func__,
226 		   lsp->child_pid, n, errno);
227 	if (n < 0) {
228 		/*
229 		 * hum seen errno=3 when process is listed in ps,
230 		 * it seems we don't always retain process grouping
231 		 *
232 		 * Direct these fallback attempt to the exact child
233 		 */
234 		n = kill(lsp->child_pid, SIGTERM);
235 		if (n < 0) {
236 			n = kill(lsp->child_pid, SIGPIPE);
237 			if (n < 0) {
238 				n = kill(lsp->child_pid, SIGKILL);
239 				if (n < 0)
240 					lwsl_info("%s: SIGKILL PID %d "
241 						 "failed errno %d "
242 						 "(maybe zombie)\n", __func__,
243 						 lsp->child_pid, errno);
244 			}
245 		}
246 	}
247 
248 	/* He could be unkillable because he's a zombie */
249 
250 	n = 1;
251 	while (n > 0) {
252 		n = waitpid(-lsp->child_pid, &status, WNOHANG);
253 		if (n > 0)
254 			lwsl_debug("%s: reaped PID %d\n", __func__, n);
255 		if (n <= 0) {
256 			n = waitpid(lsp->child_pid, &status, WNOHANG);
257 			if (n > 0)
258 				lwsl_debug("%s: reaped PID %d\n", __func__, n);
259 		}
260 	}
261 
262 	lws_spawn_reap(lsp);
263 	/* that may have invalidated lsp */
264 
265 	return 0;
266 }
267 
268 /*
269  * Deals with spawning a subprocess and executing it securely with stdin/out/err
270  * diverted into pipes
271  */
272 
273 struct lws_spawn_piped *
lws_spawn_piped(const struct lws_spawn_piped_info * i)274 lws_spawn_piped(const struct lws_spawn_piped_info *i)
275 {
276 	const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols;
277 	struct lws_context *context = i->vh->context;
278 	struct lws_spawn_piped *lsp;
279 	const char *wd;
280 	int n, m;
281 
282 	if (i->protocol_name)
283 		pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name);
284 	if (!pcol) {
285 		lwsl_err("%s: unknown protocol %s\n", __func__,
286 			 i->protocol_name ? i->protocol_name : "default");
287 
288 		return NULL;
289 	}
290 
291 	lsp = lws_zalloc(sizeof(*lsp), __func__);
292 	if (!lsp)
293 		return NULL;
294 
295 	/* wholesale take a copy of info */
296 	lsp->info = *i;
297 
298 	/*
299 	 * Prepare the stdin / out / err pipes
300 	 */
301 
302 	for (n = 0; n < 3; n++) {
303 		lsp->pipe_fds[n][0] = -1;
304 		lsp->pipe_fds[n][1] = -1;
305 	}
306 
307 	/* create pipes for [stdin|stdout] and [stderr] */
308 
309 	for (n = 0; n < 3; n++)
310 		if (pipe(lsp->pipe_fds[n]) == -1)
311 			goto bail1;
312 
313 	/* create wsis for each stdin/out/err fd */
314 
315 	for (n = 0; n < 3; n++) {
316 		lsp->stdwsi[n] = lws_create_basic_wsi(i->vh->context, i->tsi,
317 					  i->ops ? i->ops : &role_ops_raw_file);
318 		if (!lsp->stdwsi[n]) {
319 			lwsl_err("%s: unable to create lsp stdwsi\n", __func__);
320 			goto bail2;
321 		}
322 		lsp->stdwsi[n]->lsp_channel = n;
323 		lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]);
324 		lsp->stdwsi[n]->protocol = pcol;
325 		lsp->stdwsi[n]->opaque_user_data = i->opaque;
326 
327 		lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__,
328 			   lsp->stdwsi[n], n, lsp->pipe_fds[n][!!(n == 0)],
329 			   lsp->pipe_fds[n][!(n == 0)]);
330 
331 		/* read side is 0, stdin we want the write side, others read */
332 
333 		lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][!!(n == 0)];
334 		if (fcntl(lsp->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK) < 0) {
335 			lwsl_err("%s: setting NONBLOCK failed\n", __func__);
336 			goto bail2;
337 		}
338 	}
339 
340 	for (n = 0; n < 3; n++) {
341 		if (context->event_loop_ops->sock_accept)
342 			if (context->event_loop_ops->sock_accept(lsp->stdwsi[n]))
343 				goto bail3;
344 
345 		if (__insert_wsi_socket_into_fds(context, lsp->stdwsi[n]))
346 			goto bail3;
347 		if (i->opt_parent) {
348 			lsp->stdwsi[n]->parent = i->opt_parent;
349 			lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list;
350 			i->opt_parent->child_list = lsp->stdwsi[n];
351 		}
352 	}
353 
354 	if (lws_change_pollfd(lsp->stdwsi[LWS_STDIN], LWS_POLLIN, LWS_POLLOUT))
355 		goto bail3;
356 	if (lws_change_pollfd(lsp->stdwsi[LWS_STDOUT], LWS_POLLOUT, LWS_POLLIN))
357 		goto bail3;
358 	if (lws_change_pollfd(lsp->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN))
359 		goto bail3;
360 
361 	lwsl_debug("%s: fds in %d, out %d, err %d\n", __func__,
362 		   lsp->stdwsi[LWS_STDIN]->desc.sockfd,
363 		   lsp->stdwsi[LWS_STDOUT]->desc.sockfd,
364 		   lsp->stdwsi[LWS_STDERR]->desc.sockfd);
365 
366 	/* we are ready with the redirection pipes... run the thing */
367 #if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
368 	lsp->child_pid = fork();
369 #else
370 	lsp->child_pid = vfork();
371 #endif
372 	if (lsp->child_pid < 0) {
373 		lwsl_err("%s: fork failed, errno %d", __func__, errno);
374 		goto bail3;
375 	}
376 
377 #if defined(__linux__)
378 	prctl(PR_SET_PDEATHSIG, SIGTERM);
379 #endif
380 
381 	if (lsp->info.disable_ctrlc)
382 		/* stops non-daemonized main processess getting SIGINT
383 		 * from TTY */
384 		setpgrp();
385 
386 	if (lsp->child_pid) {
387 
388 		/* we are the parent process */
389 
390 		lwsl_info("%s: lsp %p spawned PID %d\n", __func__, lsp,
391 			  lsp->child_pid);
392 
393 		lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout,
394 				 i->timeout_us ? i->timeout_us :
395 						   300 * LWS_US_PER_SEC);
396 
397 		/*
398 		 *  close:                stdin:r, stdout:w, stderr:w
399 		 * hide from other forks: stdin:w, stdout:r, stderr:r
400 		 */
401 		for (n = 0; n < 3; n++) {
402 			lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][!!(n == 0)]);
403 			close(lsp->pipe_fds[n][!(n == 0)]);
404 		}
405 
406 		lsp->pipes_alive = 3;
407 		lsp->created = lws_now_usecs();
408 
409 		if (i->owner)
410 			lws_dll2_add_head(&lsp->dll, i->owner);
411 
412 		if (i->timeout_us)
413 			lws_sul_schedule(context, i->tsi, &lsp->sul,
414 					 lws_spawn_timeout, i->timeout_us);
415 
416 		return lsp;
417 	}
418 
419 	/*
420 	 * We are the forked process, redirect and kill inherited things.
421 	 *
422 	 * Because of vfork(), we cannot do anything that changes pages in
423 	 * the parent environment.  Stuff that changes kernel state for the
424 	 * process is OK.  Stuff that happens after the execvpe() is OK.
425 	 */
426 
427 	if (i->chroot_path && chroot(i->chroot_path)) {
428 		lwsl_err("%s: child chroot %s failed, errno %d\n",
429 			 __func__, i->chroot_path, errno);
430 
431 		exit(2);
432 	}
433 
434 	/* cwd: somewhere we can at least read things and enter it */
435 
436 	wd = i->wd;
437 	if (!wd)
438 		wd = "/tmp";
439 	if (chdir(wd))
440 		lwsl_notice("%s: Failed to cd to %s\n", __func__, wd);
441 
442 	for (m = 0; m < 3; m++) {
443 		if (dup2(lsp->pipe_fds[m][!(m == 0)], m) < 0) {
444 			lwsl_err("%s: stdin dup2 failed\n", __func__);
445 			goto bail3;
446 		}
447 		close(lsp->pipe_fds[m][0]);
448 		close(lsp->pipe_fds[m][1]);
449 	}
450 
451 	// lwsl_notice("%s: child cd %s, exec %s\n", __func__, wd, i->exec_array[0]);
452 
453 #if !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
454 #if defined(__linux__)
455 	m = 0;
456 	while (i->env_array[m]){
457 		char *p = strchr(i->env_array[m], '=');
458 		*p++ = '\0';
459 		setenv(i->env_array[m], p, 1);
460 		m++;
461 	}
462 #endif
463 	execvp(i->exec_array[0], (char * const *)&i->exec_array[0]);
464 #else
465 	execvpe(i->exec_array[0], (char * const *)&i->exec_array[0],
466 		&i->env_array[0]);
467 #endif
468 
469 	lwsl_err("%s: child exec of %s failed %d\n", __func__, i->exec_array[0],
470 		 LWS_ERRNO);
471 
472 	_exit(1);
473 
474 bail3:
475 
476 	while (--n >= 0)
477 		__remove_wsi_socket_from_fds(lsp->stdwsi[n]);
478 bail2:
479 	for (n = 0; n < 3; n++)
480 		if (lsp->stdwsi[n])
481 			__lws_free_wsi(lsp->stdwsi[n]);
482 
483 bail1:
484 	for (n = 0; n < 3; n++) {
485 		if (lsp->pipe_fds[n][0] >= 0)
486 			close(lsp->pipe_fds[n][0]);
487 		if (lsp->pipe_fds[n][1] >= 0)
488 			close(lsp->pipe_fds[n][1]);
489 	}
490 
491 	lws_free(lsp);
492 
493 	lwsl_err("%s: failed\n", __func__);
494 
495 	return NULL;
496 }
497 
498 void
lws_spawn_stdwsi_closed(struct lws_spawn_piped * lsp)499 lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp)
500 {
501 	assert(lsp);
502 	lsp->pipes_alive--;
503 	lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive);
504 	lws_spawn_reap(lsp);
505 }
506 
507 int
lws_spawn_get_stdfd(struct lws * wsi)508 lws_spawn_get_stdfd(struct lws *wsi)
509 {
510 	return wsi->lsp_channel;
511 }
512