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 #if defined(__OpenBSD__) || defined(__NetBSD__)
33 #include <sys/resource.h>
34 #include <sys/wait.h>
35 #endif
36
37 void
lws_spawn_timeout(struct lws_sorted_usec_list * sul)38 lws_spawn_timeout(struct lws_sorted_usec_list *sul)
39 {
40 struct lws_spawn_piped *lsp = lws_container_of(sul,
41 struct lws_spawn_piped, sul);
42
43 lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__);
44
45 lws_spawn_piped_kill_child_process(lsp);
46 }
47
48 void
lws_spawn_sul_reap(struct lws_sorted_usec_list * sul)49 lws_spawn_sul_reap(struct lws_sorted_usec_list *sul)
50 {
51 struct lws_spawn_piped *lsp = lws_container_of(sul,
52 struct lws_spawn_piped, sul_reap);
53
54 lwsl_notice("%s: reaping spawn after last stdpipe, tries left %d\n",
55 __func__, lsp->reap_retry_budget);
56 if (!lws_spawn_reap(lsp) && !lsp->pipes_alive) {
57 if (--lsp->reap_retry_budget) {
58 lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
59 &lsp->sul_reap, lws_spawn_sul_reap,
60 250 * LWS_US_PER_MS);
61 } else {
62 lwsl_err("%s: Unable to reap lsp %p, killing\n",
63 __func__, lsp);
64 lsp->reap_retry_budget = 20;
65 lws_spawn_piped_kill_child_process(lsp);
66 }
67 }
68 }
69
70 static struct lws *
lws_create_stdwsi(struct lws_context * context,int tsi,const struct lws_role_ops * ops)71 lws_create_stdwsi(struct lws_context *context, int tsi,
72 const struct lws_role_ops *ops)
73 {
74 struct lws_context_per_thread *pt = &context->pt[tsi];
75 struct lws *new_wsi;
76
77 if (!context->vhost_list)
78 return NULL;
79
80 if ((unsigned int)pt->fds_count == context->fd_limit_per_thread - 1) {
81 lwsl_err("no space for new conn\n");
82 return NULL;
83 }
84
85 lws_context_lock(context, __func__);
86 new_wsi = __lws_wsi_create_with_role(context, tsi, ops, NULL);
87 lws_context_unlock(context);
88 if (new_wsi == NULL) {
89 lwsl_err("Out of memory for new connection\n");
90 return NULL;
91 }
92
93 new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
94
95 /* initialize the instance struct */
96
97 lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops);
98
99 new_wsi->hdr_parsing_completed = 0;
100
101 /*
102 * these can only be set once the protocol is known
103 * we set an unestablished connection's protocol pointer
104 * to the start of the defauly vhost supported list, so it can look
105 * for matching ones during the handshake
106 */
107
108 new_wsi->user_space = NULL;
109
110 return new_wsi;
111 }
112
113 void
lws_spawn_piped_destroy(struct lws_spawn_piped ** _lsp)114 lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp)
115 {
116 struct lws_spawn_piped *lsp = *_lsp;
117 int n;
118
119 if (!lsp)
120 return;
121
122 lws_dll2_remove(&lsp->dll);
123
124 lws_sul_cancel(&lsp->sul);
125 lws_sul_cancel(&lsp->sul_reap);
126
127 for (n = 0; n < 3; n++) {
128 #if 0
129 if (lsp->pipe_fds[n][!!(n == 0)] == 0)
130 lwsl_err("ZERO FD IN CGI CLOSE");
131
132 if (lsp->pipe_fds[n][!!(n == 0)] >= 0) {
133 close(lsp->pipe_fds[n][!!(n == 0)]);
134 lsp->pipe_fds[n][!!(n == 0)] = LWS_SOCK_INVALID;
135 }
136 #endif
137 if (lsp->stdwsi[n]) {
138 lws_set_timeout(lsp->stdwsi[n], 1, LWS_TO_KILL_ASYNC);
139 lsp->stdwsi[n] = NULL;
140 }
141 }
142
143 lws_free_set_NULL((*_lsp));
144 }
145
146 int
lws_spawn_reap(struct lws_spawn_piped * lsp)147 lws_spawn_reap(struct lws_spawn_piped *lsp)
148 {
149 long hz = sysconf(_SC_CLK_TCK); /* accounting Hz */
150 void *opaque = lsp->info.opaque;
151 lsp_cb_t cb = lsp->info.reap_cb;
152 struct lws_spawn_piped temp;
153 struct tms tms;
154 #if defined(__OpenBSD__) || defined(__NetBSD__)
155 struct rusage rusa;
156 int status;
157 #endif
158 int n;
159
160 if (lsp->child_pid < 1)
161 return 0;
162
163 /* check if exited, do not reap yet */
164
165 memset(&lsp->si, 0, sizeof(lsp->si));
166 #if defined(__OpenBSD__) || defined(__NetBSD__)
167 n = wait4(lsp->child_pid, &status, WNOHANG, &rusa);
168 if (!n)
169 return 0;
170 lsp->si.si_code = WIFEXITED(status);
171 #else
172 n = waitid(P_PID, (id_t)lsp->child_pid, &lsp->si, WEXITED | WNOHANG | WNOWAIT);
173 #endif
174 if (n < 0) {
175 lwsl_info("%s: child %d still running\n", __func__, lsp->child_pid);
176 return 0;
177 }
178
179 if (!lsp->si.si_code)
180 return 0;
181
182 /* his process has exited... */
183
184 if (!lsp->reaped) {
185 /* mark the earliest time we knew he had gone */
186 lsp->reaped = lws_now_usecs();
187
188 /*
189 * Switch the timeout to restrict the amount of grace time
190 * to drain stdwsi
191 */
192
193 lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
194 &lsp->sul, lws_spawn_timeout,
195 5 * LWS_US_PER_SEC);
196 }
197
198 /*
199 * Stage finalizing our reaction to the process going down until the
200 * stdwsi flushed whatever is in flight and all noticed they were
201 * closed. For that reason, each stdwsi close must call lws_spawn_reap
202 * to check if that was the last one and we can proceed with the reap.
203 */
204
205 if (!lsp->ungraceful && lsp->pipes_alive) {
206 lwsl_info("%s: %d stdwsi alive, not reaping\n", __func__,
207 lsp->pipes_alive);
208 return 0;
209 }
210
211 /* we reached the reap point, no need for timeout wait */
212
213 lws_sul_cancel(&lsp->sul);
214
215 /*
216 * All the stdwsi went down, nothing more is coming... it's over
217 * Collect the final information and then reap the dead process
218 */
219
220 if (times(&tms) != (clock_t) -1) {
221 /*
222 * Cpu accounting in us
223 */
224 lsp->accounting[0] = (lws_usec_t)((uint64_t)tms.tms_cstime * 1000000) / hz;
225 lsp->accounting[1] = (lws_usec_t)((uint64_t)tms.tms_cutime * 1000000) / hz;
226 lsp->accounting[2] = (lws_usec_t)((uint64_t)tms.tms_stime * 1000000) / hz;
227 lsp->accounting[3] = (lws_usec_t)((uint64_t)tms.tms_utime * 1000000) / hz;
228 }
229
230 temp = *lsp;
231 #if defined(__OpenBSD__) || defined(__NetBSD__)
232 n = wait4(lsp->child_pid, &status, WNOHANG, &rusa);
233 if (!n)
234 return 0;
235 lsp->si.si_code = WIFEXITED(status);
236 if (lsp->si.si_code == CLD_EXITED)
237 temp.si.si_code = CLD_EXITED;
238 temp.si.si_status = WEXITSTATUS(status);
239 #else
240 n = waitid(P_PID, (id_t)lsp->child_pid, &temp.si, WEXITED | WNOHANG);
241 #endif
242 temp.si.si_status &= 0xff; /* we use b8 + for flags */
243 lwsl_info("%s: waitd says %d, process exit %d\n",
244 __func__, n, temp.si.si_status);
245
246 lsp->child_pid = -1;
247
248 /* destroy the lsp itself first (it's freed and plsp set NULL */
249
250 if (lsp->info.plsp)
251 lws_spawn_piped_destroy(lsp->info.plsp);
252
253 /* then do the parent callback informing it's destroyed */
254
255 if (cb)
256 cb(opaque, temp.accounting, &temp.si,
257 temp.we_killed_him_timeout |
258 (temp.we_killed_him_spew << 1));
259
260 return 1; /* was reaped */
261 }
262
263 int
lws_spawn_piped_kill_child_process(struct lws_spawn_piped * lsp)264 lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp)
265 {
266 int status, n;
267
268 if (lsp->child_pid <= 0)
269 return 1;
270
271 lsp->ungraceful = 1; /* don't wait for flushing, just kill it */
272
273 if (lws_spawn_reap(lsp))
274 /* that may have invalidated lsp */
275 return 0;
276
277 /* kill the process group */
278 n = kill(-lsp->child_pid, SIGTERM);
279 lwsl_debug("%s: SIGTERM child PID %d says %d (errno %d)\n", __func__,
280 lsp->child_pid, n, errno);
281 if (n < 0) {
282 /*
283 * hum seen errno=3 when process is listed in ps,
284 * it seems we don't always retain process grouping
285 *
286 * Direct these fallback attempt to the exact child
287 */
288 n = kill(lsp->child_pid, SIGTERM);
289 if (n < 0) {
290 n = kill(lsp->child_pid, SIGPIPE);
291 if (n < 0) {
292 n = kill(lsp->child_pid, SIGKILL);
293 if (n < 0)
294 lwsl_info("%s: SIGKILL PID %d "
295 "failed errno %d "
296 "(maybe zombie)\n", __func__,
297 lsp->child_pid, errno);
298 }
299 }
300 }
301
302 /* He could be unkillable because he's a zombie */
303
304 n = 1;
305 while (n > 0) {
306 n = waitpid(-lsp->child_pid, &status, WNOHANG);
307 if (n > 0)
308 lwsl_debug("%s: reaped PID %d\n", __func__, n);
309 if (n <= 0) {
310 n = waitpid(lsp->child_pid, &status, WNOHANG);
311 if (n > 0)
312 lwsl_debug("%s: reaped PID %d\n", __func__, n);
313 }
314 }
315
316 lws_spawn_reap(lsp);
317 /* that may have invalidated lsp */
318
319 return 0;
320 }
321
322 /*
323 * Deals with spawning a subprocess and executing it securely with stdin/out/err
324 * diverted into pipes
325 */
326
327 struct lws_spawn_piped *
lws_spawn_piped(const struct lws_spawn_piped_info * i)328 lws_spawn_piped(const struct lws_spawn_piped_info *i)
329 {
330 const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols;
331 struct lws_context *context = i->vh->context;
332 struct lws_spawn_piped *lsp;
333 const char *wd;
334 int n, m;
335
336 if (i->protocol_name)
337 pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name);
338 if (!pcol) {
339 lwsl_err("%s: unknown protocol %s\n", __func__,
340 i->protocol_name ? i->protocol_name : "default");
341
342 return NULL;
343 }
344
345 lsp = lws_zalloc(sizeof(*lsp), __func__);
346 if (!lsp)
347 return NULL;
348
349 /* wholesale take a copy of info */
350 lsp->info = *i;
351 lsp->reap_retry_budget = 20;
352
353 /*
354 * Prepare the stdin / out / err pipes
355 */
356
357 for (n = 0; n < 3; n++) {
358 lsp->pipe_fds[n][0] = -1;
359 lsp->pipe_fds[n][1] = -1;
360 }
361
362 /* create pipes for [stdin|stdout] and [stderr] */
363
364 for (n = 0; n < 3; n++) {
365 if (pipe(lsp->pipe_fds[n]) == -1)
366 goto bail1;
367 lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][n == 0]);
368 }
369
370 /*
371 * At this point, we have 6 pipe fds open on lws side and no wsis
372 * bound to them
373 */
374
375 /* create wsis for each stdin/out/err fd */
376
377 for (n = 0; n < 3; n++) {
378 lsp->stdwsi[n] = lws_create_stdwsi(i->vh->context, i->tsi,
379 i->ops ? i->ops : &role_ops_raw_file);
380 if (!lsp->stdwsi[n]) {
381 lwsl_err("%s: unable to create lsp stdwsi\n", __func__);
382 goto bail2;
383 }
384
385 __lws_lc_tag(i->vh->context, &i->vh->context->lcg[LWSLCG_WSI],
386 &lsp->stdwsi[n]->lc, "nspawn-stdwsi-%d", n);
387
388 lsp->stdwsi[n]->lsp_channel = (uint8_t)n;
389 lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]);
390 lsp->stdwsi[n]->a.protocol = pcol;
391 lsp->stdwsi[n]->a.opaque_user_data = i->opaque;
392
393 lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__,
394 lsp->stdwsi[n], n, lsp->pipe_fds[n][n == 0],
395 lsp->pipe_fds[n][n != 0]);
396
397 /* read side is 0, stdin we want the write side, others read */
398
399 lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][n == 0];
400 if (fcntl(lsp->pipe_fds[n][n == 0], F_SETFL, O_NONBLOCK) < 0) {
401 lwsl_err("%s: setting NONBLOCK failed\n", __func__);
402 goto bail2;
403 }
404
405 /*
406 * We have bound 3 x pipe fds to wsis, wr side of stdin and rd
407 * side of stdout / stderr... those are marked CLOEXEC so they
408 * won't go through the fork
409 *
410 * rd side of stdin and wr side of stdout / stderr are open but
411 * not bound to anything on lws side.
412 */
413 }
414
415 /*
416 * Stitch the wsi fd into the poll wait
417 */
418
419 for (n = 0; n < 3; n++) {
420 if (context->event_loop_ops->sock_accept)
421 if (context->event_loop_ops->sock_accept(lsp->stdwsi[n]))
422 goto bail3;
423
424 if (__insert_wsi_socket_into_fds(context, lsp->stdwsi[n]))
425 goto bail3;
426 if (i->opt_parent) {
427 lsp->stdwsi[n]->parent = i->opt_parent;
428 lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list;
429 i->opt_parent->child_list = lsp->stdwsi[n];
430 }
431 }
432
433 if (lws_change_pollfd(lsp->stdwsi[LWS_STDIN], LWS_POLLIN, LWS_POLLOUT))
434 goto bail3;
435 if (lws_change_pollfd(lsp->stdwsi[LWS_STDOUT], LWS_POLLOUT, LWS_POLLIN))
436 goto bail3;
437 if (lws_change_pollfd(lsp->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN))
438 goto bail3;
439
440 lwsl_info("%s: fds in %d, out %d, err %d\n", __func__,
441 lsp->stdwsi[LWS_STDIN]->desc.sockfd,
442 lsp->stdwsi[LWS_STDOUT]->desc.sockfd,
443 lsp->stdwsi[LWS_STDERR]->desc.sockfd);
444
445 /* we are ready with the redirection pipes... do the (v)fork */
446 #if defined(__sun) || !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
447 lsp->child_pid = fork();
448 #else
449 lsp->child_pid = vfork();
450 #endif
451 if (lsp->child_pid < 0) {
452 lwsl_err("%s: fork failed, errno %d", __func__, errno);
453 goto bail3;
454 }
455
456 #if defined(__linux__)
457 if (!lsp->child_pid)
458 prctl(PR_SET_PDEATHSIG, SIGTERM);
459 #endif
460
461 if (lsp->info.disable_ctrlc)
462 /* stops non-daemonized main processess getting SIGINT
463 * from TTY */
464 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
465 setpgid(0, 0);
466 #else
467 setpgrp();
468 #endif
469
470 if (lsp->child_pid) {
471
472 /*
473 * We are the parent process. We can close our copy of the
474 * "other" side of the pipe fds, ie, rd for stdin and wr for
475 * stdout / stderr.
476 */
477 for (n = 0; n < 3; n++)
478 /* these guys didn't have any wsi footprint */
479 close(lsp->pipe_fds[n][n != 0]);
480
481 lsp->pipes_alive = 3;
482 lsp->created = lws_now_usecs();
483
484 lwsl_info("%s: lsp %p spawned PID %d\n", __func__, lsp,
485 lsp->child_pid);
486
487 lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout,
488 i->timeout_us ? i->timeout_us :
489 300 * LWS_US_PER_SEC);
490
491 if (i->owner)
492 lws_dll2_add_head(&lsp->dll, i->owner);
493
494 if (i->timeout_us)
495 lws_sul_schedule(context, i->tsi, &lsp->sul,
496 lws_spawn_timeout, i->timeout_us);
497
498 return lsp;
499 }
500
501 /*
502 * We are the forked process, redirect and kill inherited things.
503 *
504 * Because of vfork(), we cannot do anything that changes pages in
505 * the parent environment. Stuff that changes kernel state for the
506 * process is OK. Stuff that happens after the execvpe() is OK.
507 */
508
509 if (i->chroot_path && chroot(i->chroot_path)) {
510 lwsl_err("%s: child chroot %s failed, errno %d\n",
511 __func__, i->chroot_path, errno);
512
513 exit(2);
514 }
515
516 /* cwd: somewhere we can at least read things and enter it */
517
518 wd = i->wd;
519 if (!wd)
520 wd = "/tmp";
521 if (chdir(wd))
522 lwsl_notice("%s: Failed to cd to %s\n", __func__, wd);
523
524 /*
525 * Bind the child's stdin / out / err to its side of our pipes
526 */
527
528 for (m = 0; m < 3; m++) {
529 if (dup2(lsp->pipe_fds[m][m != 0], m) < 0) {
530 lwsl_err("%s: stdin dup2 failed\n", __func__);
531 goto bail3;
532 }
533 /*
534 * CLOEXEC on the lws-side of the pipe fds should have already
535 * dealt with closing those for the child perspective.
536 *
537 * Now it has done the dup, the child should close its original
538 * copies of its side of the pipes.
539 */
540
541 close(lsp->pipe_fds[m][m != 0]);
542 }
543
544 #if defined(__sun) || !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
545 #if defined(__linux__) || defined(__APPLE__) || defined(__sun)
546 m = 0;
547 while (i->env_array[m]){
548 const char *p = strchr(i->env_array[m], '=');
549 int naml = lws_ptr_diff(p, i->env_array[m]);
550 char enam[32];
551
552 lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam));
553 setenv(enam, p, 1);
554 m++;
555 }
556 #endif
557 execvp(i->exec_array[0], (char * const *)&i->exec_array[0]);
558 #else
559 execvpe(i->exec_array[0], (char * const *)&i->exec_array[0],
560 (char **)&i->env_array[0]);
561 #endif
562
563 lwsl_err("%s: child exec of %s failed %d\n", __func__, i->exec_array[0],
564 LWS_ERRNO);
565
566 _exit(1);
567
568 bail3:
569
570 while (--n >= 0)
571 __remove_wsi_socket_from_fds(lsp->stdwsi[n]);
572 bail2:
573 for (n = 0; n < 3; n++)
574 if (lsp->stdwsi[n])
575 __lws_free_wsi(lsp->stdwsi[n]);
576
577 bail1:
578 for (n = 0; n < 3; n++) {
579 if (lsp->pipe_fds[n][0] >= 0)
580 close(lsp->pipe_fds[n][0]);
581 if (lsp->pipe_fds[n][1] >= 0)
582 close(lsp->pipe_fds[n][1]);
583 }
584
585 lws_free(lsp);
586
587 lwsl_err("%s: failed\n", __func__);
588
589 return NULL;
590 }
591
592 void
lws_spawn_stdwsi_closed(struct lws_spawn_piped * lsp,struct lws * wsi)593 lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi)
594 {
595 int n;
596
597 assert(lsp);
598 lsp->pipes_alive--;
599 lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive);
600 if (!lsp->pipes_alive)
601 lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
602 &lsp->sul_reap, lws_spawn_sul_reap, 1);
603
604 for (n = 0; n < 3; n++)
605 if (lsp->stdwsi[n] == wsi)
606 lsp->stdwsi[n] = NULL;
607 }
608
609 int
lws_spawn_get_stdfd(struct lws * wsi)610 lws_spawn_get_stdfd(struct lws *wsi)
611 {
612 return wsi->lsp_channel;
613 }
614