xref: /unit/src/nxt_process.c (revision 2376:1a48ea61fec8)
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