1
2 /*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) NGINX, Inc.
5 */
6
7 #include <nxt_main.h>
8 #include <nxt_cgroup.h>
9
10 #if (NXT_HAVE_LINUX_NS)
11 #include <nxt_clone.h>
12 #endif
13
14 #include <signal.h>
15
16 #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
17 #include <sys/prctl.h>
18 #endif
19
20
21 #if (NXT_HAVE_LINUX_NS) && (NXT_HAVE_CLONE_NEWPID)
22 #define nxt_is_pid_isolated(process) \
23 nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID)
24 #else
25 #define nxt_is_pid_isolated(process) \
26 (0)
27 #endif
28
29
30 #if (NXT_HAVE_LINUX_NS)
31 static nxt_int_t nxt_process_pipe_timer(nxt_fd_t fd, short event);
32 static nxt_int_t nxt_process_check_pid_status(const nxt_fd_t *gc_pipe);
33 static nxt_pid_t nxt_process_recv_pid(const nxt_fd_t *pid_pipe,
34 const nxt_fd_t *gc_pipe);
35 static void nxt_process_send_pid(const nxt_fd_t *pid_pipe, nxt_pid_t pid);
36 static nxt_int_t nxt_process_unshare(nxt_task_t *task, nxt_process_t *process,
37 nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe, nxt_bool_t use_pidns);
38 static nxt_int_t nxt_process_init_pidns(nxt_task_t *task,
39 const nxt_process_t *process, nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe,
40 nxt_bool_t *use_pidns);
41 #endif
42
43 static nxt_pid_t nxt_process_create(nxt_task_t *task, nxt_process_t *process);
44 static nxt_int_t nxt_process_do_start(nxt_task_t *task, nxt_process_t *process);
45 static nxt_int_t nxt_process_whoami(nxt_task_t *task, nxt_process_t *process);
46 static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process);
47 static nxt_int_t nxt_process_child_fixup(nxt_task_t *task,
48 nxt_process_t *process);
49 static void nxt_process_whoami_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg,
50 void *data);
51 static void nxt_process_whoami_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
52 void *data);
53 static nxt_int_t nxt_process_send_created(nxt_task_t *task,
54 nxt_process_t *process);
55 static nxt_int_t nxt_process_send_ready(nxt_task_t *task,
56 nxt_process_t *process);
57 static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg,
58 void *data);
59 static void nxt_process_created_error(nxt_task_t *task,
60 nxt_port_recv_msg_t *msg, void *data);
61
62
63 /* A cached process pid. */
64 nxt_pid_t nxt_pid;
65
66 /* An original parent process pid. */
67 nxt_pid_t nxt_ppid;
68
69 /* A cached process effective uid */
70 nxt_uid_t nxt_euid;
71
72 /* A cached process effective gid */
73 nxt_gid_t nxt_egid;
74
75 uint8_t nxt_proc_keep_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = {
76 { 1, 1, 1, 1, 1, 1 },
77 { 1, 0, 0, 0, 0, 0 },
78 { 1, 0, 0, 1, 0, 0 },
79 { 1, 0, 1, 1, 1, 1 },
80 { 1, 0, 0, 1, 0, 0 },
81 { 1, 0, 0, 1, 0, 0 },
82 };
83
84 uint8_t nxt_proc_send_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = {
85 { 1, 1, 1, 1, 1, 1 },
86 { 1, 0, 0, 0, 0, 0 },
87 { 1, 0, 0, 1, 0, 0 },
88 { 1, 0, 1, 1, 1, 1 },
89 { 1, 0, 0, 0, 0, 0 },
90 { 1, 0, 0, 0, 0, 0 },
91 };
92
93 uint8_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = {
94 { 0, 0, 0, 0, 0, 0 },
95 { 0, 0, 0, 0, 0, 0 },
96 { 0, 0, 0, 1, 0, 0 },
97 { 0, 0, 1, 0, 1, 1 },
98 { 0, 0, 0, 1, 0, 0 },
99 { 1, 0, 0, 1, 0, 0 },
100 };
101
102
103 static const nxt_port_handlers_t nxt_process_whoami_port_handlers = {
104 .quit = nxt_signal_quit_handler,
105 .rpc_ready = nxt_port_rpc_handler,
106 .rpc_error = nxt_port_rpc_handler,
107 };
108
109
110 nxt_process_t *
nxt_process_new(nxt_runtime_t * rt)111 nxt_process_new(nxt_runtime_t *rt)
112 {
113 nxt_process_t *process;
114
115 process = nxt_mp_zalloc(rt->mem_pool, sizeof(nxt_process_t)
116 + sizeof(nxt_process_init_t));
117
118 if (nxt_slow_path(process == NULL)) {
119 return NULL;
120 }
121
122 nxt_queue_init(&process->ports);
123
124 nxt_thread_mutex_create(&process->incoming.mutex);
125
126 process->use_count = 1;
127
128 nxt_queue_init(&process->children);
129
130 return process;
131 }
132
133
134 void
nxt_process_use(nxt_task_t * task,nxt_process_t * process,int i)135 nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i)
136 {
137 process->use_count += i;
138
139 if (process->use_count == 0) {
140 nxt_runtime_process_release(task->thread->runtime, process);
141 }
142 }
143
144
145 nxt_int_t
nxt_process_init_start(nxt_task_t * task,nxt_process_init_t init)146 nxt_process_init_start(nxt_task_t *task, nxt_process_init_t init)
147 {
148 nxt_int_t ret;
149 nxt_runtime_t *rt;
150 nxt_process_t *process;
151 nxt_process_init_t *pinit;
152
153 rt = task->thread->runtime;
154
155 process = nxt_process_new(rt);
156 if (nxt_slow_path(process == NULL)) {
157 return NXT_ERROR;
158 }
159
160 process->parent_port = rt->port_by_type[rt->type];
161
162 process->name = init.name;
163 process->user_cred = &rt->user_cred;
164
165 pinit = nxt_process_init(process);
166 *pinit = init;
167
168 ret = nxt_process_start(task, process);
169 if (nxt_slow_path(ret == NXT_ERROR)) {
170 nxt_process_use(task, process, -1);
171 }
172
173 return ret;
174 }
175
176
177 nxt_int_t
nxt_process_start(nxt_task_t * task,nxt_process_t * process)178 nxt_process_start(nxt_task_t *task, nxt_process_t *process)
179 {
180 nxt_mp_t *tmp_mp;
181 nxt_int_t ret;
182 nxt_pid_t pid;
183 nxt_port_t *port;
184 nxt_process_init_t *init;
185
186 init = nxt_process_init(process);
187
188 port = nxt_port_new(task, 0, 0, init->type);
189 if (nxt_slow_path(port == NULL)) {
190 return NXT_ERROR;
191 }
192
193 nxt_process_port_add(task, process, port);
194
195 ret = nxt_port_socket_init(task, port, 0);
196 if (nxt_slow_path(ret != NXT_OK)) {
197 goto free_port;
198 }
199
200 tmp_mp = nxt_mp_create(1024, 128, 256, 32);
201 if (nxt_slow_path(tmp_mp == NULL)) {
202 ret = NXT_ERROR;
203
204 goto close_port;
205 }
206
207 if (init->prefork) {
208 ret = init->prefork(task, process, tmp_mp);
209 if (nxt_slow_path(ret != NXT_OK)) {
210 goto free_mempool;
211 }
212 }
213
214 pid = nxt_process_create(task, process);
215
216 switch (pid) {
217
218 case -1:
219 ret = NXT_ERROR;
220 break;
221
222 case 0:
223 /* The child process: return to the event engine work queue loop. */
224
225 nxt_process_use(task, process, -1);
226
227 ret = NXT_AGAIN;
228 break;
229
230 default:
231 /* The parent process created a new process. */
232
233 nxt_process_use(task, process, -1);
234
235 nxt_port_read_close(port);
236 nxt_port_write_enable(task, port);
237
238 ret = NXT_OK;
239 break;
240 }
241
242 free_mempool:
243
244 nxt_mp_destroy(tmp_mp);
245
246 close_port:
247
248 if (nxt_slow_path(ret == NXT_ERROR)) {
249 nxt_port_close(task, port);
250 }
251
252 free_port:
253
254 nxt_port_use(task, port, -1);
255
256 return ret;
257 }
258
259
260 static nxt_int_t
nxt_process_child_fixup(nxt_task_t * task,nxt_process_t * process)261 nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process)
262 {
263 nxt_process_t *p;
264 nxt_runtime_t *rt;
265 nxt_process_init_t *init;
266 nxt_process_type_t ptype;
267
268 init = nxt_process_init(process);
269
270 nxt_ppid = nxt_pid;
271
272 nxt_pid = getpid();
273
274 process->pid = nxt_pid;
275 process->isolated_pid = nxt_pid;
276
277 /* Clean inherited cached thread tid. */
278 task->thread->tid = 0;
279
280 ptype = init->type;
281
282 nxt_port_reset_next_id();
283
284 nxt_event_engine_thread_adopt(task->thread->engine);
285
286 rt = task->thread->runtime;
287
288 /* Remove not ready processes. */
289 nxt_runtime_process_each(rt, p) {
290
291 if (nxt_proc_keep_matrix[ptype][nxt_process_type(p)] == 0
292 && p->pid != nxt_ppid) /* Always keep parent's port. */
293 {
294 nxt_debug(task, "remove not required process %PI", p->pid);
295
296 nxt_process_close_ports(task, p);
297
298 continue;
299 }
300
301 if (p->state != NXT_PROCESS_STATE_READY) {
302 nxt_debug(task, "remove not ready process %PI", p->pid);
303
304 nxt_process_close_ports(task, p);
305
306 continue;
307 }
308
309 nxt_port_mmaps_destroy(&p->incoming, 0);
310
311 } nxt_runtime_process_loop;
312
313 if (init->siblings != NULL) {
314 nxt_queue_each(p, init->siblings, nxt_process_t, link) {
315
316 nxt_debug(task, "remove sibling process %PI", p->pid);
317
318 nxt_process_close_ports(task, p);
319
320 } nxt_queue_loop;
321 }
322
323 return NXT_OK;
324 }
325
326
327 #if (NXT_HAVE_LINUX_NS)
328
329 static nxt_int_t
nxt_process_pipe_timer(nxt_fd_t fd,short event)330 nxt_process_pipe_timer(nxt_fd_t fd, short event)
331 {
332 int ret;
333 sigset_t mask;
334 struct pollfd pfd;
335
336 static const struct timespec ts = { .tv_sec = 5 };
337
338 /*
339 * Temporarily block the signals we are handling, (except
340 * for SIGINT & SIGTERM) so that ppoll(2) doesn't get
341 * interrupted. After ppoll(2) returns, our old sigmask
342 * will be back in effect and any pending signals will be
343 * delivered.
344 *
345 * This is because while the kernel ppoll syscall updates
346 * the struct timespec with the time remaining if it got
347 * interrupted with EINTR, the glibc wrapper hides this
348 * from us so we have no way of knowing how long to retry
349 * the ppoll(2) for and if we just retry with the same
350 * timeout we could find ourselves in an infinite loop.
351 */
352 pthread_sigmask(SIG_SETMASK, NULL, &mask);
353 sigdelset(&mask, SIGINT);
354 sigdelset(&mask, SIGTERM);
355
356 pfd.fd = fd;
357 pfd.events = event;
358
359 ret = ppoll(&pfd, 1, &ts, &mask);
360 if (ret <= 0 || (ret == 1 && pfd.revents & POLLERR)) {
361 return NXT_ERROR;
362 }
363
364 return NXT_OK;
365 }
366
367
368 static nxt_int_t
nxt_process_check_pid_status(const nxt_fd_t * gc_pipe)369 nxt_process_check_pid_status(const nxt_fd_t *gc_pipe)
370 {
371 int8_t status;
372 ssize_t ret;
373
374 close(gc_pipe[1]);
375
376 ret = nxt_process_pipe_timer(gc_pipe[0], POLLIN);
377 if (ret == NXT_OK) {
378 ret = read(gc_pipe[0], &status, sizeof(int8_t));
379 }
380
381 if (ret <= 0) {
382 status = -1;
383 }
384
385 close(gc_pipe[0]);
386
387 return status;
388 }
389
390
391 static nxt_pid_t
nxt_process_recv_pid(const nxt_fd_t * pid_pipe,const nxt_fd_t * gc_pipe)392 nxt_process_recv_pid(const nxt_fd_t *pid_pipe, const nxt_fd_t *gc_pipe)
393 {
394 int8_t status;
395 ssize_t ret;
396 nxt_pid_t pid;
397
398 close(pid_pipe[1]);
399 close(gc_pipe[0]);
400
401 status = 0;
402
403 ret = nxt_process_pipe_timer(pid_pipe[0], POLLIN);
404 if (ret == NXT_OK) {
405 ret = read(pid_pipe[0], &pid, sizeof(nxt_pid_t));
406 }
407
408 if (ret <= 0) {
409 status = -1;
410 pid = -1;
411 }
412
413 write(gc_pipe[1], &status, sizeof(int8_t));
414
415 close(pid_pipe[0]);
416 close(gc_pipe[1]);
417
418 return pid;
419 }
420
421
422 static void
nxt_process_send_pid(const nxt_fd_t * pid_pipe,nxt_pid_t pid)423 nxt_process_send_pid(const nxt_fd_t *pid_pipe, nxt_pid_t pid)
424 {
425 nxt_int_t ret;
426
427 close(pid_pipe[0]);
428
429 ret = nxt_process_pipe_timer(pid_pipe[1], POLLOUT);
430 if (ret == NXT_OK) {
431 write(pid_pipe[1], &pid, sizeof(nxt_pid_t));
432 }
433
434 close(pid_pipe[1]);
435 }
436
437
438 static nxt_int_t
nxt_process_unshare(nxt_task_t * task,nxt_process_t * process,nxt_fd_t * pid_pipe,nxt_fd_t * gc_pipe,nxt_bool_t use_pidns)439 nxt_process_unshare(nxt_task_t *task, nxt_process_t *process,
440 nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe,
441 nxt_bool_t use_pidns)
442 {
443 int ret;
444 nxt_pid_t pid;
445
446 if (process->isolation.clone.flags == 0) {
447 return NXT_OK;
448 }
449
450 ret = unshare(process->isolation.clone.flags);
451 if (nxt_slow_path(ret == -1)) {
452 nxt_alert(task, "unshare() failed for %s %E", process->name,
453 nxt_errno);
454
455 if (use_pidns) {
456 nxt_pipe_close(task, gc_pipe);
457 nxt_pipe_close(task, pid_pipe);
458 }
459
460 return NXT_ERROR;
461 }
462
463 if (!use_pidns) {
464 return NXT_OK;
465 }
466
467 /*
468 * PID namespace requested. Employ a double fork(2) technique
469 * so that the prototype process will be placed into the new
470 * namespace and end up with PID 1 (as before with clone).
471 */
472 pid = fork();
473 if (nxt_slow_path(pid < 0)) {
474 nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno);
475 nxt_pipe_close(task, gc_pipe);
476 nxt_pipe_close(task, pid_pipe);
477
478 return NXT_ERROR;
479
480 } else if (pid > 0) {
481 nxt_pipe_close(task, gc_pipe);
482 nxt_process_send_pid(pid_pipe, pid);
483
484 _exit(EXIT_SUCCESS);
485 }
486
487 nxt_pipe_close(task, pid_pipe);
488 ret = nxt_process_check_pid_status(gc_pipe);
489 if (ret == -1) {
490 return NXT_ERROR;
491 }
492
493 return NXT_OK;
494 }
495
496
497 static nxt_int_t
nxt_process_init_pidns(nxt_task_t * task,const nxt_process_t * process,nxt_fd_t * pid_pipe,nxt_fd_t * gc_pipe,nxt_bool_t * use_pidns)498 nxt_process_init_pidns(nxt_task_t *task, const nxt_process_t *process,
499 nxt_fd_t *pid_pipe, nxt_fd_t *gc_pipe,
500 nxt_bool_t *use_pidns)
501 {
502 int ret;
503
504 *use_pidns = 0;
505
506 #if (NXT_HAVE_CLONE_NEWPID)
507 *use_pidns = nxt_is_pid_isolated(process);
508 #endif
509
510 if (!*use_pidns) {
511 return NXT_OK;
512 }
513
514 ret = nxt_pipe_create(task, pid_pipe, 0, 0);
515 if (nxt_slow_path(ret == NXT_ERROR)) {
516 return NXT_ERROR;
517 }
518
519 ret = nxt_pipe_create(task, gc_pipe, 0, 0);
520 if (nxt_slow_path(ret == NXT_ERROR)) {
521 return NXT_ERROR;
522 }
523
524 #if (NXT_HAVE_PR_SET_CHILD_SUBREAPER)
525 ret = prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
526 if (nxt_slow_path(ret == -1)) {
527 nxt_alert(task, "prctl(PR_SET_CHILD_SUBREAPER) failed for %s %E",
528 process->name, nxt_errno);
529 }
530 #endif
531
532 return NXT_OK;
533 }
534
535 #endif /* NXT_HAVE_LINUX_NS */
536
537
538 static nxt_pid_t
nxt_process_create(nxt_task_t * task,nxt_process_t * process)539 nxt_process_create(nxt_task_t *task, nxt_process_t *process)
540 {
541 nxt_int_t ret;
542 nxt_pid_t pid;
543 nxt_runtime_t *rt;
544
545 #if (NXT_HAVE_LINUX_NS)
546 nxt_fd_t pid_pipe[2], gc_pipe[2];
547 nxt_bool_t use_pidns;
548
549 ret = nxt_process_init_pidns(task, process, pid_pipe, gc_pipe, &use_pidns);
550 if (ret == NXT_ERROR) {
551 return -1;
552 }
553 #endif
554
555 pid = fork();
556 if (nxt_slow_path(pid < 0)) {
557 nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno);
558 return pid;
559 }
560
561 if (pid == 0) {
562 /* Child. */
563
564 #if (NXT_HAVE_LINUX_NS)
565 ret = nxt_process_unshare(task, process, pid_pipe, gc_pipe, use_pidns);
566 if (ret == NXT_ERROR) {
567 _exit(EXIT_FAILURE);
568 }
569 #endif
570
571 ret = nxt_process_child_fixup(task, process);
572 if (nxt_slow_path(ret != NXT_OK)) {
573 nxt_process_quit(task, 1);
574 return -1;
575 }
576
577 ret = nxt_process_setup(task, process);
578 if (nxt_slow_path(ret != NXT_OK)) {
579 nxt_process_quit(task, 1);
580 }
581
582 /*
583 * Explicitly return 0 to notice the caller function this is the child.
584 * The caller must return to the event engine work queue loop.
585 */
586 return 0;
587 }
588
589 /* Parent. */
590
591 nxt_debug(task, "fork(%s): %PI", process->name, pid);
592
593 #if (NXT_HAVE_LINUX_NS)
594 if (use_pidns) {
595 pid = nxt_process_recv_pid(pid_pipe, gc_pipe);
596 if (pid == -1) {
597 return pid;
598 }
599 }
600 #endif
601
602 process->pid = pid;
603 process->isolated_pid = pid;
604
605 rt = task->thread->runtime;
606
607 if (rt->is_pid_isolated) {
608 /*
609 * Do not register process in runtime with isolated pid.
610 * Only global pid can be the key to avoid clash.
611 */
612 nxt_assert(!nxt_queue_is_empty(&process->ports));
613
614 nxt_port_use(task, nxt_process_port_first(process), 1);
615
616 } else {
617 nxt_runtime_process_add(task, process);
618 }
619
620 #if (NXT_HAVE_CGROUP)
621 ret = nxt_cgroup_proc_add(task, process);
622 if (nxt_slow_path(ret != NXT_OK)) {
623 nxt_alert(task, "cgroup: failed to add process %s to %s %E",
624 process->name, process->isolation.cgroup.path, nxt_errno);
625 nxt_cgroup_cleanup(task, process);
626 kill(pid, SIGTERM);
627 return -1;
628 }
629 #endif
630
631 return pid;
632 }
633
634
635 static nxt_int_t
nxt_process_setup(nxt_task_t * task,nxt_process_t * process)636 nxt_process_setup(nxt_task_t *task, nxt_process_t *process)
637 {
638 nxt_int_t ret;
639 nxt_thread_t *thread;
640 nxt_runtime_t *rt;
641 nxt_process_init_t *init;
642 nxt_event_engine_t *engine;
643 const nxt_event_interface_t *interface;
644
645 init = nxt_process_init(process);
646
647 nxt_debug(task, "%s setup", process->name);
648
649 nxt_process_title(task, "unit: %s", process->name);
650
651 thread = task->thread;
652 rt = thread->runtime;
653
654 nxt_random_init(&thread->random);
655
656 rt->type = init->type;
657
658 engine = thread->engine;
659
660 /* Update inherited main process event engine and signals processing. */
661 engine->signals->sigev = init->signals;
662
663 interface = nxt_service_get(rt->services, "engine", rt->engine);
664 if (nxt_slow_path(interface == NULL)) {
665 return NXT_ERROR;
666 }
667
668 if (nxt_event_engine_change(engine, interface, rt->batch) != NXT_OK) {
669 return NXT_ERROR;
670 }
671
672 ret = nxt_runtime_thread_pool_create(thread, rt, rt->auxiliary_threads,
673 60000 * 1000000LL);
674 if (nxt_slow_path(ret != NXT_OK)) {
675 return NXT_ERROR;
676 }
677
678 nxt_port_read_close(process->parent_port);
679 nxt_port_write_enable(task, process->parent_port);
680
681 /*
682 * If the parent process is already isolated, rt->pid_isolation is already
683 * set to 1 at this point.
684 */
685 if (nxt_is_pid_isolated(process)) {
686 rt->is_pid_isolated = 1;
687 }
688
689 if (rt->is_pid_isolated
690 || process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN])
691 {
692 ret = nxt_process_whoami(task, process);
693
694 } else {
695 ret = nxt_process_do_start(task, process);
696 }
697
698 return ret;
699 }
700
701
702 static nxt_int_t
nxt_process_do_start(nxt_task_t * task,nxt_process_t * process)703 nxt_process_do_start(nxt_task_t *task, nxt_process_t *process)
704 {
705 nxt_int_t ret;
706 nxt_port_t *port;
707 nxt_process_init_t *init;
708
709 nxt_runtime_process_add(task, process);
710
711 init = nxt_process_init(process);
712 port = nxt_process_port_first(process);
713
714 nxt_port_enable(task, port, init->port_handlers);
715
716 ret = init->setup(task, process);
717 if (nxt_slow_path(ret != NXT_OK)) {
718 return NXT_ERROR;
719 }
720
721 switch (process->state) {
722
723 case NXT_PROCESS_STATE_CREATED:
724 ret = nxt_process_send_created(task, process);
725 break;
726
727 case NXT_PROCESS_STATE_READY:
728 ret = nxt_process_send_ready(task, process);
729
730 if (nxt_slow_path(ret != NXT_OK)) {
731 break;
732 }
733
734 ret = init->start(task, &process->data);
735
736 nxt_port_write_close(port);
737
738 break;
739
740 default:
741 nxt_assert(0);
742 }
743
744 if (nxt_slow_path(ret != NXT_OK)) {
745 nxt_alert(task, "%s failed to start", process->name);
746 }
747
748 return ret;
749 }
750
751
752 static nxt_int_t
nxt_process_whoami(nxt_task_t * task,nxt_process_t * process)753 nxt_process_whoami(nxt_task_t *task, nxt_process_t *process)
754 {
755 uint32_t stream;
756 nxt_fd_t fd;
757 nxt_buf_t *buf;
758 nxt_int_t ret;
759 nxt_port_t *my_port, *main_port;
760 nxt_runtime_t *rt;
761
762 rt = task->thread->runtime;
763
764 my_port = nxt_process_port_first(process);
765 main_port = rt->port_by_type[NXT_PROCESS_MAIN];
766
767 nxt_assert(my_port != NULL && main_port != NULL);
768
769 nxt_port_enable(task, my_port, &nxt_process_whoami_port_handlers);
770
771 buf = nxt_buf_mem_alloc(main_port->mem_pool, sizeof(nxt_pid_t), 0);
772 if (nxt_slow_path(buf == NULL)) {
773 return NXT_ERROR;
774 }
775
776 buf->mem.free = nxt_cpymem(buf->mem.free, &nxt_ppid, sizeof(nxt_pid_t));
777
778 stream = nxt_port_rpc_register_handler(task, my_port,
779 nxt_process_whoami_ok,
780 nxt_process_whoami_error,
781 main_port->pid, process);
782 if (nxt_slow_path(stream == 0)) {
783 nxt_mp_free(main_port->mem_pool, buf);
784
785 return NXT_ERROR;
786 }
787
788 fd = (process->parent_port != main_port) ? my_port->pair[1] : -1;
789
790 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_WHOAMI,
791 fd, stream, my_port->id, buf);
792
793 if (nxt_slow_path(ret != NXT_OK)) {
794 nxt_alert(task, "%s failed to send WHOAMI message", process->name);
795 nxt_port_rpc_cancel(task, my_port, stream);
796 nxt_mp_free(main_port->mem_pool, buf);
797
798 return NXT_ERROR;
799 }
800
801 return NXT_OK;
802 }
803
804
805 static void
nxt_process_whoami_ok(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)806 nxt_process_whoami_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data)
807 {
808 nxt_pid_t pid, isolated_pid;
809 nxt_buf_t *buf;
810 nxt_port_t *port;
811 nxt_process_t *process;
812 nxt_runtime_t *rt;
813
814 process = data;
815
816 buf = msg->buf;
817
818 nxt_assert(nxt_buf_used_size(buf) == sizeof(nxt_pid_t));
819
820 nxt_memcpy(&pid, buf->mem.pos, sizeof(nxt_pid_t));
821
822 isolated_pid = nxt_pid;
823
824 if (isolated_pid != pid) {
825 nxt_pid = pid;
826 process->pid = pid;
827
828 nxt_process_port_each(process, port) {
829 port->pid = pid;
830 } nxt_process_port_loop;
831 }
832
833 rt = task->thread->runtime;
834
835 if (process->parent_port != rt->port_by_type[NXT_PROCESS_MAIN]) {
836 port = process->parent_port;
837
838 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_PROCESS_CREATED,
839 -1, 0, 0, NULL);
840
841 nxt_log(task, NXT_LOG_INFO, "%s started", process->name);
842 }
843
844 if (nxt_slow_path(nxt_process_do_start(task, process) != NXT_OK)) {
845 nxt_process_quit(task, 1);
846 }
847 }
848
849
850 static void
nxt_process_whoami_error(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)851 nxt_process_whoami_error(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data)
852 {
853 nxt_alert(task, "WHOAMI error");
854
855 nxt_process_quit(task, 1);
856 }
857
858
859 static nxt_int_t
nxt_process_send_created(nxt_task_t * task,nxt_process_t * process)860 nxt_process_send_created(nxt_task_t *task, nxt_process_t *process)
861 {
862 uint32_t stream;
863 nxt_int_t ret;
864 nxt_port_t *my_port, *main_port;
865 nxt_runtime_t *rt;
866
867 nxt_assert(process->state == NXT_PROCESS_STATE_CREATED);
868
869 rt = task->thread->runtime;
870
871 my_port = nxt_process_port_first(process);
872 main_port = rt->port_by_type[NXT_PROCESS_MAIN];
873
874 nxt_assert(my_port != NULL && main_port != NULL);
875
876 stream = nxt_port_rpc_register_handler(task, my_port,
877 nxt_process_created_ok,
878 nxt_process_created_error,
879 main_port->pid, process);
880
881 if (nxt_slow_path(stream == 0)) {
882 return NXT_ERROR;
883 }
884
885 ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_PROCESS_CREATED,
886 -1, stream, my_port->id, NULL);
887
888 if (nxt_slow_path(ret != NXT_OK)) {
889 nxt_alert(task, "%s failed to send CREATED message", process->name);
890 nxt_port_rpc_cancel(task, my_port, stream);
891 return NXT_ERROR;
892 }
893
894 nxt_debug(task, "%s created", process->name);
895
896 return NXT_OK;
897 }
898
899
900 static void
nxt_process_created_ok(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)901 nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data)
902 {
903 nxt_int_t ret;
904 nxt_process_t *process;
905 nxt_process_init_t *init;
906
907 process = data;
908
909 process->state = NXT_PROCESS_STATE_READY;
910
911 init = nxt_process_init(process);
912
913 ret = nxt_process_apply_creds(task, process);
914 if (nxt_slow_path(ret != NXT_OK)) {
915 goto fail;
916 }
917
918 nxt_log(task, NXT_LOG_INFO, "%s started", process->name);
919
920 ret = nxt_process_send_ready(task, process);
921 if (nxt_slow_path(ret != NXT_OK)) {
922 goto fail;
923 }
924
925 ret = init->start(task, &process->data);
926
927 if (nxt_process_type(process) != NXT_PROCESS_PROTOTYPE) {
928 nxt_port_write_close(nxt_process_port_first(process));
929 }
930
931 if (nxt_fast_path(ret == NXT_OK)) {
932 return;
933 }
934
935 fail:
936 nxt_process_quit(task, 1);
937 }
938
939
940 static void
nxt_process_created_error(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)941 nxt_process_created_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
942 void *data)
943 {
944 nxt_process_t *process;
945 nxt_process_init_t *init;
946
947 process = data;
948 init = nxt_process_init(process);
949
950 nxt_alert(task, "%s failed to start", init->name);
951
952 nxt_process_quit(task, 1);
953 }
954
955
956 nxt_int_t
nxt_process_core_setup(nxt_task_t * task,nxt_process_t * process)957 nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process)
958 {
959 nxt_int_t ret;
960
961 ret = nxt_process_apply_creds(task, process);
962 if (nxt_slow_path(ret != NXT_OK)) {
963 return NXT_ERROR;
964 }
965
966 process->state = NXT_PROCESS_STATE_READY;
967
968 return NXT_OK;
969 }
970
971
972 nxt_int_t
nxt_process_creds_set(nxt_task_t * task,nxt_process_t * process,nxt_str_t * user,nxt_str_t * group)973 nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process, nxt_str_t *user,
974 nxt_str_t *group)
975 {
976 char *str;
977
978 process->user_cred = nxt_mp_zalloc(process->mem_pool,
979 sizeof(nxt_credential_t));
980
981 if (nxt_slow_path(process->user_cred == NULL)) {
982 return NXT_ERROR;
983 }
984
985 str = nxt_mp_zalloc(process->mem_pool, user->length + 1);
986 if (nxt_slow_path(str == NULL)) {
987 return NXT_ERROR;
988 }
989
990 nxt_memcpy(str, user->start, user->length);
991 str[user->length] = '\0';
992
993 process->user_cred->user = str;
994
995 if (group->start != NULL) {
996 str = nxt_mp_zalloc(process->mem_pool, group->length + 1);
997 if (nxt_slow_path(str == NULL)) {
998 return NXT_ERROR;
999 }
1000
1001 nxt_memcpy(str, group->start, group->length);
1002 str[group->length] = '\0';
1003
1004 } else {
1005 str = NULL;
1006 }
1007
1008 return nxt_credential_get(task, process->mem_pool, process->user_cred, str);
1009 }
1010
1011
1012 nxt_int_t
nxt_process_apply_creds(nxt_task_t * task,nxt_process_t * process)1013 nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process)
1014 {
1015 nxt_int_t ret, cap_setid;
1016 nxt_runtime_t *rt;
1017
1018 rt = task->thread->runtime;
1019
1020 cap_setid = rt->capabilities.setid;
1021
1022 #if (NXT_HAVE_LINUX_NS && NXT_HAVE_CLONE_NEWUSER)
1023 if (!cap_setid
1024 && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER))
1025 {
1026 cap_setid = 1;
1027 }
1028 #endif
1029
1030 if (cap_setid) {
1031 ret = nxt_credential_setgids(task, process->user_cred);
1032 if (nxt_slow_path(ret != NXT_OK)) {
1033 return NXT_ERROR;
1034 }
1035
1036 ret = nxt_credential_setuid(task, process->user_cred);
1037 if (nxt_slow_path(ret != NXT_OK)) {
1038 return NXT_ERROR;
1039 }
1040 }
1041
1042 #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
1043 if (nxt_slow_path(process->isolation.new_privs == 0
1044 && prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0))
1045 {
1046 nxt_alert(task, "failed to set no_new_privs %E", nxt_errno);
1047 return NXT_ERROR;
1048 }
1049 #endif
1050
1051 return NXT_OK;
1052 }
1053
1054
1055 static nxt_int_t
nxt_process_send_ready(nxt_task_t * task,nxt_process_t * process)1056 nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process)
1057 {
1058 nxt_int_t ret;
1059
1060 ret = nxt_port_socket_write(task, process->parent_port,
1061 NXT_PORT_MSG_PROCESS_READY,
1062 -1, process->stream, 0, NULL);
1063
1064 if (nxt_slow_path(ret != NXT_OK)) {
1065 nxt_alert(task, "%s failed to send READY message", process->name);
1066 return NXT_ERROR;
1067 }
1068
1069 nxt_debug(task, "%s sent ready", process->name);
1070
1071 return NXT_OK;
1072 }
1073
1074
1075 /*
1076 * Linux glibc 2.2 posix_spawn() is implemented via fork()/execve().
1077 * Linux glibc 2.4 posix_spawn() without file actions and spawn
1078 * attributes uses vfork()/execve().
1079 *
1080 * On FreeBSD 8.0 posix_spawn() is implemented via vfork()/execve().
1081 *
1082 * Solaris 10:
1083 * In the Solaris 10 OS, posix_spawn() is currently implemented using
1084 * private-to-libc vfork(), execve(), and exit() functions. They are
1085 * identical to regular vfork(), execve(), and exit() in functionality,
1086 * but they are not exported from libc and therefore don't cause the
1087 * deadlock-in-the-dynamic-linker problem that any multithreaded code
1088 * outside of libc that calls vfork() can cause.
1089 *
1090 * On MacOSX 10.5 (Leoprad) and NetBSD 6.0 posix_spawn() is implemented
1091 * as syscall.
1092 */
1093
1094 nxt_pid_t
nxt_process_execute(nxt_task_t * task,char * name,char ** argv,char ** envp)1095 nxt_process_execute(nxt_task_t *task, char *name, char **argv, char **envp)
1096 {
1097 nxt_pid_t pid;
1098
1099 nxt_debug(task, "posix_spawn(\"%s\")", name);
1100
1101 if (posix_spawn(&pid, name, NULL, NULL, argv, envp) != 0) {
1102 nxt_alert(task, "posix_spawn(\"%s\") failed %E", name, nxt_errno);
1103 return -1;
1104 }
1105
1106 return pid;
1107 }
1108
1109
1110 nxt_int_t
nxt_process_daemon(nxt_task_t * task)1111 nxt_process_daemon(nxt_task_t *task)
1112 {
1113 nxt_fd_t fd;
1114 nxt_pid_t pid;
1115 const char *msg;
1116
1117 fd = -1;
1118
1119 /*
1120 * fork() followed by a parent process's exit() detaches a child process
1121 * from an init script or terminal shell process which has started the
1122 * parent process and allows the child process to run in background.
1123 */
1124
1125 pid = fork();
1126
1127 switch (pid) {
1128
1129 case -1:
1130 msg = "fork() failed %E";
1131 goto fail;
1132
1133 case 0:
1134 /* A child. */
1135 break;
1136
1137 default:
1138 /* A parent. */
1139 nxt_debug(task, "fork(): %PI", pid);
1140 exit(0);
1141 nxt_unreachable();
1142 }
1143
1144 nxt_pid = getpid();
1145
1146 /* Clean inherited cached thread tid. */
1147 task->thread->tid = 0;
1148
1149 nxt_debug(task, "daemon");
1150
1151 /* Detach from controlling terminal. */
1152
1153 if (setsid() == -1) {
1154 nxt_alert(task, "setsid() failed %E", nxt_errno);
1155 return NXT_ERROR;
1156 }
1157
1158 /*
1159 * Set a sefe umask to give at most 755/644 permissions on
1160 * directories/files.
1161 */
1162 umask(0022);
1163
1164 /* Redirect STDIN and STDOUT to the "/dev/null". */
1165
1166 fd = open("/dev/null", O_RDWR);
1167 if (fd == -1) {
1168 msg = "open(\"/dev/null\") failed %E";
1169 goto fail;
1170 }
1171
1172 if (dup2(fd, STDIN_FILENO) == -1) {
1173 msg = "dup2(\"/dev/null\", STDIN) failed %E";
1174 goto fail;
1175 }
1176
1177 if (dup2(fd, STDOUT_FILENO) == -1) {
1178 msg = "dup2(\"/dev/null\", STDOUT) failed %E";
1179 goto fail;
1180 }
1181
1182 if (fd > STDERR_FILENO) {
1183 nxt_fd_close(fd);
1184 }
1185
1186 return NXT_OK;
1187
1188 fail:
1189
1190 nxt_alert(task, msg, nxt_errno);
1191
1192 if (fd != -1) {
1193 nxt_fd_close(fd);
1194 }
1195
1196 return NXT_ERROR;
1197 }
1198
1199
1200 void
nxt_nanosleep(nxt_nsec_t ns)1201 nxt_nanosleep(nxt_nsec_t ns)
1202 {
1203 struct timespec ts;
1204
1205 ts.tv_sec = ns / 1000000000;
1206 ts.tv_nsec = ns % 1000000000;
1207
1208 (void) nanosleep(&ts, NULL);
1209 }
1210
1211
1212 void
nxt_process_port_add(nxt_task_t * task,nxt_process_t * process,nxt_port_t * port)1213 nxt_process_port_add(nxt_task_t *task, nxt_process_t *process, nxt_port_t *port)
1214 {
1215 nxt_assert(port->process == NULL);
1216
1217 port->process = process;
1218 nxt_queue_insert_tail(&process->ports, &port->link);
1219
1220 nxt_process_use(task, process, 1);
1221 }
1222
1223
1224 nxt_process_type_t
nxt_process_type(nxt_process_t * process)1225 nxt_process_type(nxt_process_t *process)
1226 {
1227 return nxt_queue_is_empty(&process->ports) ? 0 :
1228 (nxt_process_port_first(process))->type;
1229 }
1230
1231
1232 void
nxt_process_close_ports(nxt_task_t * task,nxt_process_t * process)1233 nxt_process_close_ports(nxt_task_t *task, nxt_process_t *process)
1234 {
1235 nxt_port_t *port;
1236
1237 nxt_process_use(task, process, 1);
1238
1239 nxt_process_port_each(process, port) {
1240
1241 nxt_port_close(task, port);
1242
1243 nxt_runtime_port_remove(task, port);
1244
1245 } nxt_process_port_loop;
1246
1247 nxt_process_use(task, process, -1);
1248 }
1249
1250
1251 void
nxt_process_quit(nxt_task_t * task,nxt_uint_t exit_status)1252 nxt_process_quit(nxt_task_t *task, nxt_uint_t exit_status)
1253 {
1254 nxt_queue_t *listen;
1255 nxt_queue_link_t *link, *next;
1256 nxt_listen_event_t *lev;
1257
1258 nxt_debug(task, "close listen connections");
1259
1260 listen = &task->thread->engine->listen_connections;
1261
1262 for (link = nxt_queue_first(listen);
1263 link != nxt_queue_tail(listen);
1264 link = next)
1265 {
1266 next = nxt_queue_next(link);
1267 lev = nxt_queue_link_data(link, nxt_listen_event_t, link);
1268 nxt_queue_remove(link);
1269
1270 nxt_fd_event_close(task->thread->engine, &lev->socket);
1271 }
1272
1273 nxt_runtime_quit(task, exit_status);
1274 }
1275