nxt_application.c (1488:6976d36be926) nxt_application.c (1489:4a3ec07f4b19)
1
2/*
3 * Copyright (C) Max Romanov
4 * Copyright (C) Igor Sysoev
5 * Copyright (C) Valentin V. Bartenev
6 * Copyright (C) NGINX, Inc.
7 */
8
9#include <nxt_main.h>
10#include <nxt_runtime.h>
11#include <nxt_main_process.h>
12#include <nxt_router.h>
13#include <nxt_http.h>
14#include <nxt_application.h>
15#include <nxt_unit.h>
16#include <nxt_port_memory_int.h>
17
18#include <glob.h>
19
1
2/*
3 * Copyright (C) Max Romanov
4 * Copyright (C) Igor Sysoev
5 * Copyright (C) Valentin V. Bartenev
6 * Copyright (C) NGINX, Inc.
7 */
8
9#include <nxt_main.h>
10#include <nxt_runtime.h>
11#include <nxt_main_process.h>
12#include <nxt_router.h>
13#include <nxt_http.h>
14#include <nxt_application.h>
15#include <nxt_unit.h>
16#include <nxt_port_memory_int.h>
17
18#include <glob.h>
19
20#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
21#include <sys/prctl.h>
22#endif
20
23
24
21typedef struct {
22 nxt_app_type_t type;
23 nxt_str_t version;
24 nxt_str_t file;
25typedef struct {
26 nxt_app_type_t type;
27 nxt_str_t version;
28 nxt_str_t file;
29 nxt_array_t *mounts;
25} nxt_module_t;
26
27
28static nxt_int_t nxt_discovery_start(nxt_task_t *task,
29 nxt_process_data_t *data);
30static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path);
31static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp,
32 nxt_array_t *modules, const char *name);
33static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj,
34 void *data);
35static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg,
36 void *data);
37static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task,
38 const char *name);
39static nxt_int_t nxt_app_prefork(nxt_task_t *task, nxt_process_t *process,
40 nxt_mp_t *mp);
41static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process);
42static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment);
30} nxt_module_t;
31
32
33static nxt_int_t nxt_discovery_start(nxt_task_t *task,
34 nxt_process_data_t *data);
35static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path);
36static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp,
37 nxt_array_t *modules, const char *name);
38static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj,
39 void *data);
40static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg,
41 void *data);
42static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task,
43 const char *name);
44static nxt_int_t nxt_app_prefork(nxt_task_t *task, nxt_process_t *process,
45 nxt_mp_t *mp);
46static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process);
47static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment);
43static nxt_int_t nxt_app_isolation(nxt_task_t *task,
48static u_char *nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src);
49
50#if (NXT_HAVE_ISOLATION_ROOTFS)
51static nxt_int_t nxt_app_prepare_rootfs(nxt_task_t *task,
52 nxt_process_t *process);
53static nxt_int_t nxt_app_prepare_lang_mounts(nxt_task_t *task,
54 nxt_process_t *process, nxt_array_t *syspaths);
55static nxt_int_t nxt_app_set_isolation_rootfs(nxt_task_t *task,
44 nxt_conf_value_t *isolation, nxt_process_t *process);
56 nxt_conf_value_t *isolation, nxt_process_t *process);
57#endif
45
58
59static nxt_int_t nxt_app_set_isolation(nxt_task_t *task,
60 nxt_conf_value_t *isolation, nxt_process_t *process);
61
46#if (NXT_HAVE_CLONE)
62#if (NXT_HAVE_CLONE)
63static nxt_int_t nxt_app_set_isolation_namespaces(nxt_task_t *task,
64 nxt_conf_value_t *isolation, nxt_process_t *process);
47static nxt_int_t nxt_app_clone_flags(nxt_task_t *task,
48 nxt_conf_value_t *namespaces, nxt_clone_t *clone);
49#endif
50
51#if (NXT_HAVE_CLONE_NEWUSER)
65static nxt_int_t nxt_app_clone_flags(nxt_task_t *task,
66 nxt_conf_value_t *namespaces, nxt_clone_t *clone);
67#endif
68
69#if (NXT_HAVE_CLONE_NEWUSER)
52static nxt_int_t nxt_app_isolation_creds(nxt_task_t *task,
70static nxt_int_t nxt_app_set_isolation_creds(nxt_task_t *task,
53 nxt_conf_value_t *isolation, nxt_process_t *process);
54static nxt_int_t nxt_app_isolation_credential_map(nxt_task_t *task,
55 nxt_mp_t *mem_pool, nxt_conf_value_t *map_array,
56 nxt_clone_credential_map_t *map);
57#endif
58
71 nxt_conf_value_t *isolation, nxt_process_t *process);
72static nxt_int_t nxt_app_isolation_credential_map(nxt_task_t *task,
73 nxt_mp_t *mem_pool, nxt_conf_value_t *map_array,
74 nxt_clone_credential_map_t *map);
75#endif
76
77#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
78static nxt_int_t nxt_app_set_isolation_new_privs(nxt_task_t *task,
79 nxt_conf_value_t *isolation, nxt_process_t *process);
80#endif
81
59nxt_str_t nxt_server = nxt_string(NXT_SERVER);
60
61
62static uint32_t compat[] = {
63 NXT_VERNUM, NXT_DEBUG,
64};
65
66

--- 82 unchanged lines hidden (view full) ---

149
150 return NXT_OK;
151}
152
153
154static nxt_buf_t *
155nxt_discovery_modules(nxt_task_t *task, const char *path)
156{
82nxt_str_t nxt_server = nxt_string(NXT_SERVER);
83
84
85static uint32_t compat[] = {
86 NXT_VERNUM, NXT_DEBUG,
87};
88
89

--- 82 unchanged lines hidden (view full) ---

172
173 return NXT_OK;
174}
175
176
177static nxt_buf_t *
178nxt_discovery_modules(nxt_task_t *task, const char *path)
179{
157 char *name;
158 u_char *p, *end;
159 size_t size;
160 glob_t glb;
161 nxt_mp_t *mp;
162 nxt_buf_t *b;
163 nxt_int_t ret;
164 nxt_uint_t i, n;
165 nxt_array_t *modules;
166 nxt_module_t *module;
180 char *name;
181 u_char *p, *end;
182 size_t size;
183 glob_t glb;
184 nxt_mp_t *mp;
185 nxt_buf_t *b;
186 nxt_int_t ret;
187 nxt_uint_t i, n, j;
188 nxt_array_t *modules, *mounts;
189 nxt_module_t *module;
190 nxt_fs_mount_t *mnt;
167
168 b = NULL;
169
170 mp = nxt_mp_create(1024, 128, 256, 32);
171 if (mp == NULL) {
172 return b;
173 }
174

--- 26 unchanged lines hidden (view full) ---

201 n = modules->nelts;
202
203 for (i = 0; i < n; i++) {
204 nxt_debug(task, "module: %d %V %V",
205 module[i].type, &module[i].version, &module[i].file);
206
207 size += nxt_length("{\"type\": ,");
208 size += nxt_length(" \"version\": \"\",");
191
192 b = NULL;
193
194 mp = nxt_mp_create(1024, 128, 256, 32);
195 if (mp == NULL) {
196 return b;
197 }
198

--- 26 unchanged lines hidden (view full) ---

225 n = modules->nelts;
226
227 for (i = 0; i < n; i++) {
228 nxt_debug(task, "module: %d %V %V",
229 module[i].type, &module[i].version, &module[i].file);
230
231 size += nxt_length("{\"type\": ,");
232 size += nxt_length(" \"version\": \"\",");
209 size += nxt_length(" \"file\": \"\"},");
233 size += nxt_length(" \"file\": \"\",");
234 size += nxt_length(" \"mounts\": []},");
210
211 size += NXT_INT_T_LEN
212 + module[i].version.length
213 + module[i].file.length;
235
236 size += NXT_INT_T_LEN
237 + module[i].version.length
238 + module[i].file.length;
239
240 mounts = module[i].mounts;
241
242 size += mounts->nelts * nxt_length("{\"src\": \"\", \"dst\": \"\", "
243 "\"fstype\": \"\", \"flags\": , "
244 "\"data\": \"\"},");
245
246 mnt = mounts->elts;
247
248 for (j = 0; j < mounts->nelts; j++) {
249 size += nxt_strlen(mnt[j].src) + nxt_strlen(mnt[j].dst)
250 + nxt_strlen(mnt[j].fstype) + NXT_INT_T_LEN
251 + (mnt[j].data == NULL ? 0 : nxt_strlen(mnt[j].data));
252 }
214 }
215
216 b = nxt_buf_mem_alloc(mp, size, 0);
217 if (b == NULL) {
218 goto fail;
219 }
220
221 b->completion_handler = nxt_discovery_completion_handler;
222
223 p = b->mem.free;
224 end = b->mem.end;
225 *p++ = '[';
226
227 for (i = 0; i < n; i++) {
253 }
254
255 b = nxt_buf_mem_alloc(mp, size, 0);
256 if (b == NULL) {
257 goto fail;
258 }
259
260 b->completion_handler = nxt_discovery_completion_handler;
261
262 p = b->mem.free;
263 end = b->mem.end;
264 *p++ = '[';
265
266 for (i = 0; i < n; i++) {
228 p = nxt_sprintf(p, end,
229 "{\"type\": %d, \"version\": \"%V\", \"file\": \"%V\"},",
230 module[i].type, &module[i].version, &module[i].file);
267 mounts = module[i].mounts;
268
269 p = nxt_sprintf(p, end, "{\"type\": %d, \"version\": \"%V\", "
270 "\"file\": \"%V\", \"mounts\": [",
271 module[i].type, &module[i].version, &module[i].file);
272
273 mnt = mounts->elts;
274 for (j = 0; j < mounts->nelts; j++) {
275 p = nxt_sprintf(p, end,
276 "{\"src\": \"%s\", \"dst\": \"%s\", "
277 "\"fstype\": \"%s\", \"flags\": %d, "
278 "\"data\": \"%s\"},",
279 mnt[j].src, mnt[j].dst, mnt[j].fstype, mnt[j].flags,
280 mnt[j].data == NULL ? (u_char *) "" : mnt[j].data);
281 }
282
283 *p++ = ']';
284 *p++ = '}';
285 *p++ = ',';
231 }
232
233 *p++ = ']';
286 }
287
288 *p++ = ']';
289
290 if (nxt_slow_path(p >= end)) {
291 nxt_alert(task, "discovery write past the buffer");
292 goto fail;
293 }
294
234 b->mem.free = p;
235
236fail:
237
238 globfree(&glb);
239
240 return b;
241}
242
243
244static nxt_int_t
245nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
246 const char *name)
247{
295 b->mem.free = p;
296
297fail:
298
299 globfree(&glb);
300
301 return b;
302}
303
304
305static nxt_int_t
306nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
307 const char *name)
308{
248 void *dl;
249 nxt_str_t version;
250 nxt_int_t ret;
251 nxt_uint_t i, n;
252 nxt_module_t *module;
253 nxt_app_type_t type;
254 nxt_app_module_t *app;
309 void *dl;
310 nxt_str_t version;
311 nxt_int_t ret;
312 nxt_uint_t i, j, n;
313 nxt_array_t *mounts;
314 nxt_module_t *module;
315 nxt_app_type_t type;
316 nxt_fs_mount_t *to;
317 nxt_app_module_t *app;
318 const nxt_fs_mount_t *from;
255
256 /*
257 * Only memory allocation failure should return NXT_ERROR.
258 * Any module processing errors are ignored.
259 */
260 ret = NXT_ERROR;
261
262 dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW);

--- 60 unchanged lines hidden (view full) ---

323
324 module->file.start = nxt_mp_alloc(mp, module->file.length);
325 if (module->file.start == NULL) {
326 goto fail;
327 }
328
329 nxt_memcpy(module->file.start, name, module->file.length);
330
319
320 /*
321 * Only memory allocation failure should return NXT_ERROR.
322 * Any module processing errors are ignored.
323 */
324 ret = NXT_ERROR;
325
326 dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW);

--- 60 unchanged lines hidden (view full) ---

387
388 module->file.start = nxt_mp_alloc(mp, module->file.length);
389 if (module->file.start == NULL) {
390 goto fail;
391 }
392
393 nxt_memcpy(module->file.start, name, module->file.length);
394
395 module->mounts = nxt_array_create(mp, app->nmounts,
396 sizeof(nxt_fs_mount_t));
397
398 if (nxt_slow_path(module->mounts == NULL)) {
399 goto fail;
400 }
401
402 mounts = module->mounts;
403
404 for (j = 0; j < app->nmounts; j++) {
405 from = &app->mounts[j];
406 to = nxt_array_zero_add(mounts);
407 if (nxt_slow_path(to == NULL)) {
408 goto fail;
409 }
410
411 to->src = nxt_cstr_dup(mp, to->src, from->src);
412 if (nxt_slow_path(to->src == NULL)) {
413 goto fail;
414 }
415
416 to->dst = nxt_cstr_dup(mp, to->dst, from->dst);
417 if (nxt_slow_path(to->dst == NULL)) {
418 goto fail;
419 }
420
421 to->fstype = nxt_cstr_dup(mp, to->fstype, from->fstype);
422 if (nxt_slow_path(to->fstype == NULL)) {
423 goto fail;
424 }
425
426 if (from->data != NULL) {
427 to->data = nxt_cstr_dup(mp, to->data, from->data);
428 if (nxt_slow_path(to->data == NULL)) {
429 goto fail;
430 }
431 }
432
433 to->flags = from->flags;
434 }
435
331 } else {
332 nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror());
333 }
334
335done:
336
337 ret = NXT_OK;
338

--- 25 unchanged lines hidden (view full) ---

364{
365 nxt_signal_quit_handler(task, msg);
366}
367
368
369static nxt_int_t
370nxt_app_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
371{
436 } else {
437 nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror());
438 }
439
440done:
441
442 ret = NXT_OK;
443

--- 25 unchanged lines hidden (view full) ---

469{
470 nxt_signal_quit_handler(task, msg);
471}
472
473
474static nxt_int_t
475nxt_app_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
476{
372 nxt_int_t cap_setid;
477 nxt_int_t cap_setid, cap_chroot;
373 nxt_int_t ret;
374 nxt_runtime_t *rt;
375 nxt_common_app_conf_t *app_conf;
478 nxt_int_t ret;
479 nxt_runtime_t *rt;
480 nxt_common_app_conf_t *app_conf;
481 nxt_app_lang_module_t *lang;
376
377 rt = task->thread->runtime;
378 app_conf = process->data.app;
379 cap_setid = rt->capabilities.setid;
482
483 rt = task->thread->runtime;
484 app_conf = process->data.app;
485 cap_setid = rt->capabilities.setid;
486 cap_chroot = rt->capabilities.chroot;
380
487
488 lang = nxt_app_lang_module(rt, &app_conf->type);
489
490 nxt_assert(lang != NULL);
491
381 if (app_conf->isolation != NULL) {
492 if (app_conf->isolation != NULL) {
382 ret = nxt_app_isolation(task, app_conf->isolation, process);
493 ret = nxt_app_set_isolation(task, app_conf->isolation, process);
383 if (nxt_slow_path(ret != NXT_OK)) {
384 return ret;
385 }
386 }
387
388#if (NXT_HAVE_CLONE_NEWUSER)
389 if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
390 cap_setid = 1;
494 if (nxt_slow_path(ret != NXT_OK)) {
495 return ret;
496 }
497 }
498
499#if (NXT_HAVE_CLONE_NEWUSER)
500 if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
501 cap_setid = 1;
502 cap_chroot = 1;
391 }
392#endif
393
503 }
504#endif
505
506#if (NXT_HAVE_ISOLATION_ROOTFS)
507 if (process->isolation.rootfs != NULL) {
508 if (!cap_chroot) {
509 nxt_log(task, NXT_LOG_ERR,
510 "The \"rootfs\" field requires privileges");
511
512 return NXT_ERROR;
513 }
514
515 if (lang->mounts != NULL && lang->mounts->nelts > 0) {
516 ret = nxt_app_prepare_lang_mounts(task, process, lang->mounts);
517 if (nxt_slow_path(ret != NXT_OK)) {
518 return NXT_ERROR;
519 }
520 }
521 }
522#endif
523
394 if (cap_setid) {
395 ret = nxt_process_creds_set(task, process, &app_conf->user,
396 &app_conf->group);
397
398 if (nxt_slow_path(ret != NXT_OK)) {
399 return ret;
400 }
401

--- 53 unchanged lines hidden (view full) ---

455 lang->version, lang->file);
456
457 nxt_app = nxt_app_module_load(task, lang->file);
458 if (nxt_slow_path(nxt_app == NULL)) {
459 return NXT_ERROR;
460 }
461 }
462
524 if (cap_setid) {
525 ret = nxt_process_creds_set(task, process, &app_conf->user,
526 &app_conf->group);
527
528 if (nxt_slow_path(ret != NXT_OK)) {
529 return ret;
530 }
531

--- 53 unchanged lines hidden (view full) ---

585 lang->version, lang->file);
586
587 nxt_app = nxt_app_module_load(task, lang->file);
588 if (nxt_slow_path(nxt_app == NULL)) {
589 return NXT_ERROR;
590 }
591 }
592
593 if (nxt_slow_path(nxt_app_set_environment(app_conf->environment)
594 != NXT_OK))
595 {
596 nxt_alert(task, "failed to set environment");
597 return NXT_ERROR;
598 }
599
463 if (nxt_app->setup != NULL) {
464 ret = nxt_app->setup(task, process, app_conf);
465
466 if (nxt_slow_path(ret != NXT_OK)) {
467 return ret;
468 }
469 }
470
600 if (nxt_app->setup != NULL) {
601 ret = nxt_app->setup(task, process, app_conf);
602
603 if (nxt_slow_path(ret != NXT_OK)) {
604 return ret;
605 }
606 }
607
608#if (NXT_HAVE_ISOLATION_ROOTFS)
609 if (process->isolation.rootfs != NULL) {
610 if (process->isolation.mounts != NULL) {
611 ret = nxt_app_prepare_rootfs(task, process);
612 if (nxt_slow_path(ret != NXT_OK)) {
613 return ret;
614 }
615 }
616
617 ret = nxt_process_change_root(task, process);
618 if (nxt_slow_path(ret != NXT_OK)) {
619 return NXT_ERROR;
620 }
621 }
622#endif
623
471 if (app_conf->working_directory != NULL
472 && app_conf->working_directory[0] != 0)
473 {
474 ret = chdir(app_conf->working_directory);
475
476 if (nxt_slow_path(ret != 0)) {
477 nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E",
478 app_conf->working_directory, nxt_errno);
479
480 return NXT_ERROR;
481 }
482 }
483
624 if (app_conf->working_directory != NULL
625 && app_conf->working_directory[0] != 0)
626 {
627 ret = chdir(app_conf->working_directory);
628
629 if (nxt_slow_path(ret != 0)) {
630 nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E",
631 app_conf->working_directory, nxt_errno);
632
633 return NXT_ERROR;
634 }
635 }
636
484 if (nxt_slow_path(nxt_app_set_environment(app_conf->environment)
485 != NXT_OK))
486 {
487 nxt_alert(task, "failed to set environment");
488 return NXT_ERROR;
489 }
490
491 init = nxt_process_init(process);
492
493 init->start = nxt_app->start;
494
495 process->state = NXT_PROCESS_STATE_CREATED;
496
497 return NXT_OK;
498}

--- 51 unchanged lines hidden (view full) ---

550 }
551 }
552
553 return NXT_OK;
554}
555
556
557static nxt_int_t
637 init = nxt_process_init(process);
638
639 init->start = nxt_app->start;
640
641 process->state = NXT_PROCESS_STATE_CREATED;
642
643 return NXT_OK;
644}

--- 51 unchanged lines hidden (view full) ---

696 }
697 }
698
699 return NXT_OK;
700}
701
702
703static nxt_int_t
558nxt_app_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
704nxt_app_set_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
559 nxt_process_t *process)
560{
561#if (NXT_HAVE_CLONE)
705 nxt_process_t *process)
706{
707#if (NXT_HAVE_CLONE)
708 if (nxt_slow_path(nxt_app_set_isolation_namespaces(task, isolation, process)
709 != NXT_OK))
710 {
711 return NXT_ERROR;
712 }
713#endif
714
715#if (NXT_HAVE_CLONE_NEWUSER)
716 if (nxt_slow_path(nxt_app_set_isolation_creds(task, isolation, process)
717 != NXT_OK))
718 {
719 return NXT_ERROR;
720 }
721#endif
722
723#if (NXT_HAVE_ISOLATION_ROOTFS)
724 if (nxt_slow_path(nxt_app_set_isolation_rootfs(task, isolation, process)
725 != NXT_OK))
726 {
727 return NXT_ERROR;
728 }
729#endif
730
731#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
732 if (nxt_slow_path(nxt_app_set_isolation_new_privs(task, isolation, process)
733 != NXT_OK))
734 {
735 return NXT_ERROR;
736 }
737#endif
738
739 return NXT_OK;
740}
741
742
743#if (NXT_HAVE_CLONE)
744
745static nxt_int_t
746nxt_app_set_isolation_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation,
747 nxt_process_t *process)
748{
562 nxt_int_t ret;
563 nxt_conf_value_t *obj;
564
565 static nxt_str_t nsname = nxt_string("namespaces");
566
567 obj = nxt_conf_get_object_member(isolation, &nsname, NULL);
568 if (obj != NULL) {
569 ret = nxt_app_clone_flags(task, obj, &process->isolation.clone);
570 if (nxt_slow_path(ret != NXT_OK)) {
571 return NXT_ERROR;
572 }
573 }
749 nxt_int_t ret;
750 nxt_conf_value_t *obj;
751
752 static nxt_str_t nsname = nxt_string("namespaces");
753
754 obj = nxt_conf_get_object_member(isolation, &nsname, NULL);
755 if (obj != NULL) {
756 ret = nxt_app_clone_flags(task, obj, &process->isolation.clone);
757 if (nxt_slow_path(ret != NXT_OK)) {
758 return NXT_ERROR;
759 }
760 }
761
762 return NXT_OK;
763}
764
574#endif
575
765#endif
766
576#if (NXT_HAVE_CLONE_NEWUSER)
577 ret = nxt_app_isolation_creds(task, isolation, process);
578 if (nxt_slow_path(ret != NXT_OK)) {
579 return NXT_ERROR;
767
768#if (NXT_HAVE_ISOLATION_ROOTFS)
769
770static nxt_int_t
771nxt_app_set_isolation_rootfs(nxt_task_t *task, nxt_conf_value_t *isolation,
772 nxt_process_t *process)
773{
774 nxt_str_t str;
775 nxt_conf_value_t *obj;
776
777 static nxt_str_t rootfs_name = nxt_string("rootfs");
778
779 obj = nxt_conf_get_object_member(isolation, &rootfs_name, NULL);
780 if (obj != NULL) {
781 nxt_conf_get_string(obj, &str);
782
783 if (nxt_slow_path(str.length <= 1 || str.start[0] != '/')) {
784 nxt_log(task, NXT_LOG_ERR, "rootfs requires an absolute path other "
785 "than \"/\" but given \"%V\"", &str);
786
787 return NXT_ERROR;
788 }
789
790 if (str.start[str.length - 1] == '/') {
791 str.length--;
792 }
793
794 process->isolation.rootfs = nxt_mp_alloc(process->mem_pool,
795 str.length + 1);
796
797 if (nxt_slow_path(process->isolation.rootfs == NULL)) {
798 return NXT_ERROR;
799 }
800
801 nxt_memcpy(process->isolation.rootfs, str.start, str.length);
802
803 process->isolation.rootfs[str.length] = '\0';
580 }
804 }
805
806 return NXT_OK;
807}
808
581#endif
582
809#endif
810
811
812#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
813
814static nxt_int_t
815nxt_app_set_isolation_new_privs(nxt_task_t *task, nxt_conf_value_t *isolation,
816 nxt_process_t *process)
817{
818 nxt_conf_value_t *obj;
819
820 static nxt_str_t new_privs_name = nxt_string("new_privs");
821
822 obj = nxt_conf_get_object_member(isolation, &new_privs_name, NULL);
823 if (obj != NULL) {
824 process->isolation.new_privs = nxt_conf_get_boolean(obj);
825 }
826
583 return NXT_OK;
584}
585
827 return NXT_OK;
828}
829
830#endif
586
831
832
587#if (NXT_HAVE_CLONE_NEWUSER)
588
589static nxt_int_t
833#if (NXT_HAVE_CLONE_NEWUSER)
834
835static nxt_int_t
590nxt_app_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation,
836nxt_app_set_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation,
591 nxt_process_t *process)
592{
593 nxt_int_t ret;
594 nxt_clone_t *clone;
595 nxt_conf_value_t *array;
596
597 static nxt_str_t uidname = nxt_string("uidmap");
598 static nxt_str_t gidname = nxt_string("gidmap");

--- 149 unchanged lines hidden (view full) ---

748 }
749
750 return NXT_OK;
751}
752
753#endif
754
755
837 nxt_process_t *process)
838{
839 nxt_int_t ret;
840 nxt_clone_t *clone;
841 nxt_conf_value_t *array;
842
843 static nxt_str_t uidname = nxt_string("uidmap");
844 static nxt_str_t gidname = nxt_string("gidmap");

--- 149 unchanged lines hidden (view full) ---

994 }
995
996 return NXT_OK;
997}
998
999#endif
1000
1001
1002#if (NXT_HAVE_ISOLATION_ROOTFS)
756
1003
1004static nxt_int_t
1005nxt_app_prepare_lang_mounts(nxt_task_t *task, nxt_process_t *process,
1006 nxt_array_t *lang_mounts)
1007{
1008 u_char *p;
1009 size_t i, n, rootfs_len, len;
1010 nxt_mp_t *mp;
1011 nxt_array_t *mounts;
1012 const u_char *rootfs;
1013 nxt_fs_mount_t *mnt, *lang_mnt;
1014
1015 rootfs = process->isolation.rootfs;
1016 rootfs_len = nxt_strlen(rootfs);
1017 mp = process->mem_pool;
1018
1019 /* copy to init mem pool */
1020 mounts = nxt_array_copy(mp, NULL, lang_mounts);
1021 if (mounts == NULL) {
1022 return NXT_ERROR;
1023 }
1024
1025 n = mounts->nelts;
1026 mnt = mounts->elts;
1027 lang_mnt = lang_mounts->elts;
1028
1029 for (i = 0; i < n; i++) {
1030 len = nxt_strlen(lang_mnt[i].dst);
1031
1032 mnt[i].dst = nxt_mp_alloc(mp, rootfs_len + len + 1);
1033 if (mnt[i].dst == NULL) {
1034 return NXT_ERROR;
1035 }
1036
1037 p = nxt_cpymem(mnt[i].dst, rootfs, rootfs_len);
1038 p = nxt_cpymem(p, lang_mnt[i].dst, len);
1039 *p = '\0';
1040 }
1041
1042 process->isolation.mounts = mounts;
1043
1044 return NXT_OK;
1045}
1046
1047
1048
1049static nxt_int_t
1050nxt_app_prepare_rootfs(nxt_task_t *task, nxt_process_t *process)
1051{
1052 size_t i, n;
1053 nxt_int_t ret, hasproc;
1054 struct stat st;
1055 nxt_array_t *mounts;
1056 const u_char *dst;
1057 nxt_fs_mount_t *mnt;
1058
1059 hasproc = 0;
1060
1061#if (NXT_HAVE_CLONE_NEWPID) && (NXT_HAVE_CLONE_NEWNS)
1062 nxt_fs_mount_t mount;
1063
1064 if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID)
1065 && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS))
1066 {
1067 /*
1068 * This mount point will automatically be gone when the namespace is
1069 * destroyed.
1070 */
1071
1072 mount.fstype = (u_char *) "proc";
1073 mount.src = (u_char *) "proc";
1074 mount.dst = (u_char *) "/proc";
1075 mount.data = (u_char *) "";
1076 mount.flags = 0;
1077
1078 ret = nxt_fs_mkdir_all(mount.dst, S_IRWXU | S_IRWXG | S_IRWXO);
1079 if (nxt_fast_path(ret == NXT_OK)) {
1080 ret = nxt_fs_mount(task, &mount);
1081 if (nxt_fast_path(ret == NXT_OK)) {
1082 hasproc = 1;
1083 }
1084
1085 } else {
1086 nxt_log(task, NXT_LOG_WARN, "mkdir(%s) %E", mount.dst, nxt_errno);
1087 }
1088 }
1089#endif
1090
1091 mounts = process->isolation.mounts;
1092
1093 n = mounts->nelts;
1094 mnt = mounts->elts;
1095
1096 for (i = 0; i < n; i++) {
1097 dst = mnt[i].dst;
1098
1099 if (nxt_slow_path(nxt_memcmp(mnt[i].fstype, "bind", 4) == 0
1100 && stat((const char *) mnt[i].src, &st) != 0))
1101 {
1102 nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src);
1103 continue;
1104 }
1105
1106 if (hasproc && nxt_memcmp(mnt[i].fstype, "proc", 4) == 0
1107 && nxt_memcmp(mnt[i].dst, "/proc", 5) == 0)
1108 {
1109 continue;
1110 }
1111
1112 ret = nxt_fs_mkdir_all(dst, S_IRWXU | S_IRWXG | S_IRWXO);
1113 if (nxt_slow_path(ret != NXT_OK)) {
1114 nxt_alert(task, "mkdir(%s) %E", dst, nxt_errno);
1115 goto undo;
1116 }
1117
1118 ret = nxt_fs_mount(task, &mnt[i]);
1119 if (nxt_slow_path(ret != NXT_OK)) {
1120 goto undo;
1121 }
1122 }
1123
1124 return NXT_OK;
1125
1126undo:
1127
1128 n = i + 1;
1129
1130 for (i = 0; i < n; i++) {
1131 nxt_fs_unmount(mnt[i].dst);
1132 }
1133
1134 return NXT_ERROR;
1135}
1136
1137#endif
1138
1139
1140static u_char *
1141nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src)
1142{
1143 u_char *p;
1144 size_t len;
1145
1146 len = nxt_strlen(src);
1147
1148 if (dst == NULL) {
1149 dst = nxt_mp_alloc(mp, len + 1);
1150 if (nxt_slow_path(dst == NULL)) {
1151 return NULL;
1152 }
1153 }
1154
1155 p = nxt_cpymem(dst, src, len);
1156 *p = '\0';
1157
1158 return dst;
1159}
1160
1161
757nxt_app_lang_module_t *
758nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
759{
760 u_char *p, *end, *version;
761 size_t version_length;
762 nxt_uint_t i, n;
763 nxt_app_type_t type;
764 nxt_app_lang_module_t *lang;

--- 114 unchanged lines hidden ---
1162nxt_app_lang_module_t *
1163nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
1164{
1165 u_char *p, *end, *version;
1166 size_t version_length;
1167 nxt_uint_t i, n;
1168 nxt_app_type_t type;
1169 nxt_app_lang_module_t *lang;

--- 114 unchanged lines hidden ---