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