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