10Sigor@sysoev.ru 20Sigor@sysoev.ru /* 384Smax.romanov@nginx.com * Copyright (C) Max Romanov 40Sigor@sysoev.ru * Copyright (C) Igor Sysoev 50Sigor@sysoev.ru * Copyright (C) Valentin V. Bartenev 60Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 70Sigor@sysoev.ru */ 80Sigor@sysoev.ru 90Sigor@sysoev.ru #include <nxt_main.h> 1020Sigor@sysoev.ru #include <nxt_runtime.h> 11240Sigor@sysoev.ru #include <nxt_main_process.h> 12431Sigor@sysoev.ru #include <nxt_router.h> 13431Sigor@sysoev.ru #include <nxt_http.h> 14444Sigor@sysoev.ru #include <nxt_application.h> 15743Smax.romanov@nginx.com #include <nxt_unit.h> 16723Smax.romanov@nginx.com #include <nxt_port_memory_int.h> 170Sigor@sysoev.ru 18216Sigor@sysoev.ru #include <glob.h> 190Sigor@sysoev.ru 201489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 211489St.nateldemoura@f5.com #include <sys/prctl.h> 221489St.nateldemoura@f5.com #endif 231489St.nateldemoura@f5.com 24216Sigor@sysoev.ru 25216Sigor@sysoev.ru typedef struct { 26356Svbart@nginx.com nxt_app_type_t type; 27356Svbart@nginx.com nxt_str_t version; 28356Svbart@nginx.com nxt_str_t file; 291489St.nateldemoura@f5.com nxt_array_t *mounts; 30216Sigor@sysoev.ru } nxt_module_t; 31216Sigor@sysoev.ru 32216Sigor@sysoev.ru 331488St.nateldemoura@f5.com static nxt_int_t nxt_discovery_start(nxt_task_t *task, 341488St.nateldemoura@f5.com nxt_process_data_t *data); 35216Sigor@sysoev.ru static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path); 36216Sigor@sysoev.ru static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, 37216Sigor@sysoev.ru nxt_array_t *modules, const char *name); 38549Svbart@nginx.com static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj, 39549Svbart@nginx.com void *data); 40549Svbart@nginx.com static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, 41549Svbart@nginx.com void *data); 42216Sigor@sysoev.ru static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task, 43216Sigor@sysoev.ru const char *name); 441503St.nateldemoura@f5.com static nxt_int_t nxt_app_main_prefork(nxt_task_t *task, nxt_process_t *process, 451488St.nateldemoura@f5.com nxt_mp_t *mp); 461488St.nateldemoura@f5.com static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process); 47678Svbart@nginx.com static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment); 481489St.nateldemoura@f5.com static u_char *nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src); 491489St.nateldemoura@f5.com 501489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 511503St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_mounts(nxt_task_t *task, 521503St.nateldemoura@f5.com nxt_process_t *process, nxt_str_t *app_type); 531503St.nateldemoura@f5.com static nxt_int_t nxt_app_set_lang_mounts(nxt_task_t *task, 541489St.nateldemoura@f5.com nxt_process_t *process, nxt_array_t *syspaths); 551489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_rootfs(nxt_task_t *task, 561489St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 571503St.nateldemoura@f5.com static nxt_int_t nxt_app_prepare_rootfs(nxt_task_t *task, 581503St.nateldemoura@f5.com nxt_process_t *process); 591489St.nateldemoura@f5.com #endif 601489St.nateldemoura@f5.com 611489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation(nxt_task_t *task, 621488St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 631488St.nateldemoura@f5.com 641488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 651489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_namespaces(nxt_task_t *task, 661489St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 671488St.nateldemoura@f5.com static nxt_int_t nxt_app_clone_flags(nxt_task_t *task, 681488St.nateldemoura@f5.com nxt_conf_value_t *namespaces, nxt_clone_t *clone); 691488St.nateldemoura@f5.com #endif 701488St.nateldemoura@f5.com 711488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 721489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_creds(nxt_task_t *task, 731488St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 741488St.nateldemoura@f5.com static nxt_int_t nxt_app_isolation_credential_map(nxt_task_t *task, 751488St.nateldemoura@f5.com nxt_mp_t *mem_pool, nxt_conf_value_t *map_array, 761488St.nateldemoura@f5.com nxt_clone_credential_map_t *map); 771488St.nateldemoura@f5.com #endif 781488St.nateldemoura@f5.com 791489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 801489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_new_privs(nxt_task_t *task, 811489St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 821489St.nateldemoura@f5.com #endif 831489St.nateldemoura@f5.com 841488St.nateldemoura@f5.com nxt_str_t nxt_server = nxt_string(NXT_SERVER); 850Sigor@sysoev.ru 86216Sigor@sysoev.ru 87258Sigor@sysoev.ru static uint32_t compat[] = { 88360Sigor@sysoev.ru NXT_VERNUM, NXT_DEBUG, 89258Sigor@sysoev.ru }; 90258Sigor@sysoev.ru 91258Sigor@sysoev.ru 92743Smax.romanov@nginx.com static nxt_app_module_t *nxt_app; 93417Svbart@nginx.com 94417Svbart@nginx.com 951488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_discovery_process_port_handlers = { 961488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler, 971488St.nateldemoura@f5.com .new_port = nxt_port_new_port_handler, 981488St.nateldemoura@f5.com .change_file = nxt_port_change_log_file_handler, 991488St.nateldemoura@f5.com .mmap = nxt_port_mmap_handler, 1001488St.nateldemoura@f5.com .data = nxt_port_data_handler, 1011488St.nateldemoura@f5.com .remove_pid = nxt_port_remove_pid_handler, 1021488St.nateldemoura@f5.com .rpc_ready = nxt_port_rpc_handler, 1031488St.nateldemoura@f5.com .rpc_error = nxt_port_rpc_handler, 1041488St.nateldemoura@f5.com }; 1051488St.nateldemoura@f5.com 1061488St.nateldemoura@f5.com 1071488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_app_process_port_handlers = { 1081488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler, 1091488St.nateldemoura@f5.com .rpc_ready = nxt_port_rpc_handler, 1101488St.nateldemoura@f5.com .rpc_error = nxt_port_rpc_handler, 1111488St.nateldemoura@f5.com }; 1121488St.nateldemoura@f5.com 1131488St.nateldemoura@f5.com 1141488St.nateldemoura@f5.com const nxt_process_init_t nxt_discovery_process = { 1151488St.nateldemoura@f5.com .name = "discovery", 1161488St.nateldemoura@f5.com .type = NXT_PROCESS_DISCOVERY, 1171488St.nateldemoura@f5.com .prefork = NULL, 1181488St.nateldemoura@f5.com .restart = 0, 1191488St.nateldemoura@f5.com .setup = nxt_process_core_setup, 1201488St.nateldemoura@f5.com .start = nxt_discovery_start, 1211488St.nateldemoura@f5.com .port_handlers = &nxt_discovery_process_port_handlers, 1221488St.nateldemoura@f5.com .signals = nxt_process_signals, 1231488St.nateldemoura@f5.com }; 1241488St.nateldemoura@f5.com 1251488St.nateldemoura@f5.com 1261488St.nateldemoura@f5.com const nxt_process_init_t nxt_app_process = { 1271488St.nateldemoura@f5.com .type = NXT_PROCESS_APP, 1281488St.nateldemoura@f5.com .setup = nxt_app_setup, 1291503St.nateldemoura@f5.com .prefork = nxt_app_main_prefork, 1301488St.nateldemoura@f5.com .restart = 0, 1311488St.nateldemoura@f5.com .start = NULL, /* set to module->start */ 1321488St.nateldemoura@f5.com .port_handlers = &nxt_app_process_port_handlers, 1331488St.nateldemoura@f5.com .signals = nxt_process_signals, 1341488St.nateldemoura@f5.com }; 1351488St.nateldemoura@f5.com 1361488St.nateldemoura@f5.com 1371488St.nateldemoura@f5.com static nxt_int_t 1381488St.nateldemoura@f5.com nxt_discovery_start(nxt_task_t *task, nxt_process_data_t *data) 139216Sigor@sysoev.ru { 140549Svbart@nginx.com uint32_t stream; 141549Svbart@nginx.com nxt_buf_t *b; 142549Svbart@nginx.com nxt_int_t ret; 143549Svbart@nginx.com nxt_port_t *main_port, *discovery_port; 144549Svbart@nginx.com nxt_runtime_t *rt; 145216Sigor@sysoev.ru 1461488St.nateldemoura@f5.com nxt_log(task, NXT_LOG_INFO, "discovery started"); 147216Sigor@sysoev.ru 148233Sigor@sysoev.ru rt = task->thread->runtime; 149216Sigor@sysoev.ru 150233Sigor@sysoev.ru b = nxt_discovery_modules(task, rt->modules); 151250Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 152549Svbart@nginx.com return NXT_ERROR; 153250Sigor@sysoev.ru } 154233Sigor@sysoev.ru 155240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 156549Svbart@nginx.com discovery_port = rt->port_by_type[NXT_PROCESS_DISCOVERY]; 157216Sigor@sysoev.ru 158549Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, discovery_port, 159549Svbart@nginx.com nxt_discovery_quit, 160549Svbart@nginx.com nxt_discovery_quit, 161549Svbart@nginx.com main_port->pid, NULL); 162549Svbart@nginx.com 163645Svbart@nginx.com if (nxt_slow_path(stream == 0)) { 164645Svbart@nginx.com return NXT_ERROR; 165645Svbart@nginx.com } 166645Svbart@nginx.com 167549Svbart@nginx.com ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, 168549Svbart@nginx.com stream, discovery_port->id, b); 169549Svbart@nginx.com 170549Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 171549Svbart@nginx.com nxt_port_rpc_cancel(task, discovery_port, stream); 172549Svbart@nginx.com return NXT_ERROR; 173549Svbart@nginx.com } 174216Sigor@sysoev.ru 175216Sigor@sysoev.ru return NXT_OK; 176216Sigor@sysoev.ru } 177216Sigor@sysoev.ru 178216Sigor@sysoev.ru 179216Sigor@sysoev.ru static nxt_buf_t * 180216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path) 181216Sigor@sysoev.ru { 1821489St.nateldemoura@f5.com char *name; 1831489St.nateldemoura@f5.com u_char *p, *end; 1841489St.nateldemoura@f5.com size_t size; 1851489St.nateldemoura@f5.com glob_t glb; 1861489St.nateldemoura@f5.com nxt_mp_t *mp; 1871489St.nateldemoura@f5.com nxt_buf_t *b; 1881489St.nateldemoura@f5.com nxt_int_t ret; 1891489St.nateldemoura@f5.com nxt_uint_t i, n, j; 1901489St.nateldemoura@f5.com nxt_array_t *modules, *mounts; 1911489St.nateldemoura@f5.com nxt_module_t *module; 1921489St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 193216Sigor@sysoev.ru 194216Sigor@sysoev.ru b = NULL; 195216Sigor@sysoev.ru 196216Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 197216Sigor@sysoev.ru if (mp == NULL) { 198216Sigor@sysoev.ru return b; 199216Sigor@sysoev.ru } 200216Sigor@sysoev.ru 201216Sigor@sysoev.ru ret = glob(path, 0, NULL, &glb); 202216Sigor@sysoev.ru 203250Sigor@sysoev.ru n = glb.gl_pathc; 204250Sigor@sysoev.ru 205250Sigor@sysoev.ru if (ret != 0) { 206250Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 207250Sigor@sysoev.ru "no modules matching: \"%s\" found", path); 208250Sigor@sysoev.ru n = 0; 209250Sigor@sysoev.ru } 210216Sigor@sysoev.ru 211250Sigor@sysoev.ru modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); 212250Sigor@sysoev.ru if (modules == NULL) { 213250Sigor@sysoev.ru goto fail; 214250Sigor@sysoev.ru } 215250Sigor@sysoev.ru 216250Sigor@sysoev.ru for (i = 0; i < n; i++) { 217250Sigor@sysoev.ru name = glb.gl_pathv[i]; 218250Sigor@sysoev.ru 219250Sigor@sysoev.ru ret = nxt_discovery_module(task, mp, modules, name); 220250Sigor@sysoev.ru if (ret != NXT_OK) { 221216Sigor@sysoev.ru goto fail; 222216Sigor@sysoev.ru } 223250Sigor@sysoev.ru } 224216Sigor@sysoev.ru 225703Svbart@nginx.com size = nxt_length("[]"); 226250Sigor@sysoev.ru module = modules->elts; 227250Sigor@sysoev.ru n = modules->nelts; 228216Sigor@sysoev.ru 229250Sigor@sysoev.ru for (i = 0; i < n; i++) { 230356Svbart@nginx.com nxt_debug(task, "module: %d %V %V", 231356Svbart@nginx.com module[i].type, &module[i].version, &module[i].file); 232216Sigor@sysoev.ru 233703Svbart@nginx.com size += nxt_length("{\"type\": ,"); 234703Svbart@nginx.com size += nxt_length(" \"version\": \"\","); 2351489St.nateldemoura@f5.com size += nxt_length(" \"file\": \"\","); 2361489St.nateldemoura@f5.com size += nxt_length(" \"mounts\": []},"); 237216Sigor@sysoev.ru 238356Svbart@nginx.com size += NXT_INT_T_LEN 239250Sigor@sysoev.ru + module[i].version.length 240250Sigor@sysoev.ru + module[i].file.length; 2411489St.nateldemoura@f5.com 2421489St.nateldemoura@f5.com mounts = module[i].mounts; 2431489St.nateldemoura@f5.com 2441489St.nateldemoura@f5.com size += mounts->nelts * nxt_length("{\"src\": \"\", \"dst\": \"\", " 2451489St.nateldemoura@f5.com "\"fstype\": \"\", \"flags\": , " 2461489St.nateldemoura@f5.com "\"data\": \"\"},"); 2471489St.nateldemoura@f5.com 2481489St.nateldemoura@f5.com mnt = mounts->elts; 2491489St.nateldemoura@f5.com 2501489St.nateldemoura@f5.com for (j = 0; j < mounts->nelts; j++) { 2511489St.nateldemoura@f5.com size += nxt_strlen(mnt[j].src) + nxt_strlen(mnt[j].dst) 2521489St.nateldemoura@f5.com + nxt_strlen(mnt[j].fstype) + NXT_INT_T_LEN 2531489St.nateldemoura@f5.com + (mnt[j].data == NULL ? 0 : nxt_strlen(mnt[j].data)); 2541489St.nateldemoura@f5.com } 255250Sigor@sysoev.ru } 256216Sigor@sysoev.ru 257250Sigor@sysoev.ru b = nxt_buf_mem_alloc(mp, size, 0); 258250Sigor@sysoev.ru if (b == NULL) { 259250Sigor@sysoev.ru goto fail; 260250Sigor@sysoev.ru } 261216Sigor@sysoev.ru 262250Sigor@sysoev.ru b->completion_handler = nxt_discovery_completion_handler; 263216Sigor@sysoev.ru 264250Sigor@sysoev.ru p = b->mem.free; 265250Sigor@sysoev.ru end = b->mem.end; 266250Sigor@sysoev.ru *p++ = '['; 267216Sigor@sysoev.ru 268250Sigor@sysoev.ru for (i = 0; i < n; i++) { 2691489St.nateldemoura@f5.com mounts = module[i].mounts; 2701489St.nateldemoura@f5.com 2711489St.nateldemoura@f5.com p = nxt_sprintf(p, end, "{\"type\": %d, \"version\": \"%V\", " 2721489St.nateldemoura@f5.com "\"file\": \"%V\", \"mounts\": [", 2731489St.nateldemoura@f5.com module[i].type, &module[i].version, &module[i].file); 2741489St.nateldemoura@f5.com 2751489St.nateldemoura@f5.com mnt = mounts->elts; 2761489St.nateldemoura@f5.com for (j = 0; j < mounts->nelts; j++) { 2771489St.nateldemoura@f5.com p = nxt_sprintf(p, end, 2781489St.nateldemoura@f5.com "{\"src\": \"%s\", \"dst\": \"%s\", " 2791489St.nateldemoura@f5.com "\"fstype\": \"%s\", \"flags\": %d, " 2801489St.nateldemoura@f5.com "\"data\": \"%s\"},", 2811489St.nateldemoura@f5.com mnt[j].src, mnt[j].dst, mnt[j].fstype, mnt[j].flags, 2821489St.nateldemoura@f5.com mnt[j].data == NULL ? (u_char *) "" : mnt[j].data); 2831489St.nateldemoura@f5.com } 2841489St.nateldemoura@f5.com 2851489St.nateldemoura@f5.com *p++ = ']'; 2861489St.nateldemoura@f5.com *p++ = '}'; 2871489St.nateldemoura@f5.com *p++ = ','; 288250Sigor@sysoev.ru } 289216Sigor@sysoev.ru 290250Sigor@sysoev.ru *p++ = ']'; 2911489St.nateldemoura@f5.com 292*1515Smax.romanov@nginx.com if (nxt_slow_path(p > end)) { 2931489St.nateldemoura@f5.com nxt_alert(task, "discovery write past the buffer"); 2941489St.nateldemoura@f5.com goto fail; 2951489St.nateldemoura@f5.com } 2961489St.nateldemoura@f5.com 297250Sigor@sysoev.ru b->mem.free = p; 298216Sigor@sysoev.ru 299216Sigor@sysoev.ru fail: 300216Sigor@sysoev.ru 301216Sigor@sysoev.ru globfree(&glb); 302216Sigor@sysoev.ru 303216Sigor@sysoev.ru return b; 304216Sigor@sysoev.ru } 305216Sigor@sysoev.ru 306216Sigor@sysoev.ru 307216Sigor@sysoev.ru static nxt_int_t 308216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, 309216Sigor@sysoev.ru const char *name) 310216Sigor@sysoev.ru { 3111489St.nateldemoura@f5.com void *dl; 3121489St.nateldemoura@f5.com nxt_str_t version; 3131489St.nateldemoura@f5.com nxt_int_t ret; 3141489St.nateldemoura@f5.com nxt_uint_t i, j, n; 3151489St.nateldemoura@f5.com nxt_array_t *mounts; 3161489St.nateldemoura@f5.com nxt_module_t *module; 3171489St.nateldemoura@f5.com nxt_app_type_t type; 3181489St.nateldemoura@f5.com nxt_fs_mount_t *to; 3191489St.nateldemoura@f5.com nxt_app_module_t *app; 3201489St.nateldemoura@f5.com const nxt_fs_mount_t *from; 321216Sigor@sysoev.ru 322216Sigor@sysoev.ru /* 323216Sigor@sysoev.ru * Only memory allocation failure should return NXT_ERROR. 324216Sigor@sysoev.ru * Any module processing errors are ignored. 325216Sigor@sysoev.ru */ 326216Sigor@sysoev.ru ret = NXT_ERROR; 327216Sigor@sysoev.ru 328216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); 329216Sigor@sysoev.ru 330216Sigor@sysoev.ru if (dl == NULL) { 331564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 332216Sigor@sysoev.ru return NXT_OK; 333216Sigor@sysoev.ru } 334216Sigor@sysoev.ru 335216Sigor@sysoev.ru app = dlsym(dl, "nxt_app_module"); 336216Sigor@sysoev.ru 337216Sigor@sysoev.ru if (app != NULL) { 338612Salexander.borisov@nginx.com nxt_log(task, NXT_LOG_NOTICE, "module: %V %s \"%s\"", 339612Salexander.borisov@nginx.com &app->type, app->version, name); 340258Sigor@sysoev.ru 341258Sigor@sysoev.ru if (app->compat_length != sizeof(compat) 342258Sigor@sysoev.ru || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) 343258Sigor@sysoev.ru { 344258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); 345258Sigor@sysoev.ru 346258Sigor@sysoev.ru goto done; 347258Sigor@sysoev.ru } 348216Sigor@sysoev.ru 349356Svbart@nginx.com type = nxt_app_parse_type(app->type.start, app->type.length); 350356Svbart@nginx.com 351356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 352494Spluknet@nginx.com nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", &app->type); 353356Svbart@nginx.com 354356Svbart@nginx.com goto done; 355356Svbart@nginx.com } 356356Svbart@nginx.com 357216Sigor@sysoev.ru module = modules->elts; 358216Sigor@sysoev.ru n = modules->nelts; 359216Sigor@sysoev.ru 360612Salexander.borisov@nginx.com version.start = (u_char *) app->version; 361612Salexander.borisov@nginx.com version.length = nxt_strlen(app->version); 362612Salexander.borisov@nginx.com 363216Sigor@sysoev.ru for (i = 0; i < n; i++) { 364356Svbart@nginx.com if (type == module[i].type 365612Salexander.borisov@nginx.com && nxt_strstr_eq(&module[i].version, &version)) 366258Sigor@sysoev.ru { 367216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 368216Sigor@sysoev.ru "ignoring %s module with the same " 369267Sigor@sysoev.ru "application language version %V %V as in %V", 370655Svbart@nginx.com name, &app->type, &version, &module[i].file); 371216Sigor@sysoev.ru 372216Sigor@sysoev.ru goto done; 373216Sigor@sysoev.ru } 374216Sigor@sysoev.ru } 375216Sigor@sysoev.ru 376216Sigor@sysoev.ru module = nxt_array_add(modules); 377216Sigor@sysoev.ru if (module == NULL) { 378216Sigor@sysoev.ru goto fail; 379216Sigor@sysoev.ru } 380216Sigor@sysoev.ru 381356Svbart@nginx.com module->type = type; 382216Sigor@sysoev.ru 383612Salexander.borisov@nginx.com nxt_str_dup(mp, &module->version, &version); 384612Salexander.borisov@nginx.com if (module->version.start == NULL) { 385216Sigor@sysoev.ru goto fail; 386216Sigor@sysoev.ru } 387216Sigor@sysoev.ru 388216Sigor@sysoev.ru module->file.length = nxt_strlen(name); 389216Sigor@sysoev.ru 390216Sigor@sysoev.ru module->file.start = nxt_mp_alloc(mp, module->file.length); 391216Sigor@sysoev.ru if (module->file.start == NULL) { 392216Sigor@sysoev.ru goto fail; 393216Sigor@sysoev.ru } 394216Sigor@sysoev.ru 395216Sigor@sysoev.ru nxt_memcpy(module->file.start, name, module->file.length); 396216Sigor@sysoev.ru 3971489St.nateldemoura@f5.com module->mounts = nxt_array_create(mp, app->nmounts, 3981489St.nateldemoura@f5.com sizeof(nxt_fs_mount_t)); 3991489St.nateldemoura@f5.com 4001489St.nateldemoura@f5.com if (nxt_slow_path(module->mounts == NULL)) { 4011489St.nateldemoura@f5.com goto fail; 4021489St.nateldemoura@f5.com } 4031489St.nateldemoura@f5.com 4041489St.nateldemoura@f5.com mounts = module->mounts; 4051489St.nateldemoura@f5.com 4061489St.nateldemoura@f5.com for (j = 0; j < app->nmounts; j++) { 4071489St.nateldemoura@f5.com from = &app->mounts[j]; 4081489St.nateldemoura@f5.com to = nxt_array_zero_add(mounts); 4091489St.nateldemoura@f5.com if (nxt_slow_path(to == NULL)) { 4101489St.nateldemoura@f5.com goto fail; 4111489St.nateldemoura@f5.com } 4121489St.nateldemoura@f5.com 4131489St.nateldemoura@f5.com to->src = nxt_cstr_dup(mp, to->src, from->src); 4141489St.nateldemoura@f5.com if (nxt_slow_path(to->src == NULL)) { 4151489St.nateldemoura@f5.com goto fail; 4161489St.nateldemoura@f5.com } 4171489St.nateldemoura@f5.com 4181489St.nateldemoura@f5.com to->dst = nxt_cstr_dup(mp, to->dst, from->dst); 4191489St.nateldemoura@f5.com if (nxt_slow_path(to->dst == NULL)) { 4201489St.nateldemoura@f5.com goto fail; 4211489St.nateldemoura@f5.com } 4221489St.nateldemoura@f5.com 4231489St.nateldemoura@f5.com to->fstype = nxt_cstr_dup(mp, to->fstype, from->fstype); 4241489St.nateldemoura@f5.com if (nxt_slow_path(to->fstype == NULL)) { 4251489St.nateldemoura@f5.com goto fail; 4261489St.nateldemoura@f5.com } 4271489St.nateldemoura@f5.com 4281489St.nateldemoura@f5.com if (from->data != NULL) { 4291489St.nateldemoura@f5.com to->data = nxt_cstr_dup(mp, to->data, from->data); 4301489St.nateldemoura@f5.com if (nxt_slow_path(to->data == NULL)) { 4311489St.nateldemoura@f5.com goto fail; 4321489St.nateldemoura@f5.com } 4331489St.nateldemoura@f5.com } 4341489St.nateldemoura@f5.com 4351489St.nateldemoura@f5.com to->flags = from->flags; 4361489St.nateldemoura@f5.com } 4371489St.nateldemoura@f5.com 438216Sigor@sysoev.ru } else { 439564Svbart@nginx.com nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror()); 440216Sigor@sysoev.ru } 441216Sigor@sysoev.ru 442216Sigor@sysoev.ru done: 443216Sigor@sysoev.ru 444216Sigor@sysoev.ru ret = NXT_OK; 445216Sigor@sysoev.ru 446216Sigor@sysoev.ru fail: 447216Sigor@sysoev.ru 448216Sigor@sysoev.ru if (dlclose(dl) != 0) { 449564Svbart@nginx.com nxt_alert(task, "dlclose(\"%s\"), failed: \"%s\"", name, dlerror()); 450216Sigor@sysoev.ru } 451216Sigor@sysoev.ru 452216Sigor@sysoev.ru return ret; 453216Sigor@sysoev.ru } 454216Sigor@sysoev.ru 455216Sigor@sysoev.ru 456549Svbart@nginx.com static void 457549Svbart@nginx.com nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) 458549Svbart@nginx.com { 459549Svbart@nginx.com nxt_mp_t *mp; 460549Svbart@nginx.com nxt_buf_t *b; 461549Svbart@nginx.com 462549Svbart@nginx.com b = obj; 463549Svbart@nginx.com mp = b->data; 464549Svbart@nginx.com 465549Svbart@nginx.com nxt_mp_destroy(mp); 466549Svbart@nginx.com } 467549Svbart@nginx.com 468549Svbart@nginx.com 469549Svbart@nginx.com static void 470549Svbart@nginx.com nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 471549Svbart@nginx.com { 4721488St.nateldemoura@f5.com nxt_signal_quit_handler(task, msg); 473549Svbart@nginx.com } 474549Svbart@nginx.com 475549Svbart@nginx.com 4761488St.nateldemoura@f5.com static nxt_int_t 4771503St.nateldemoura@f5.com nxt_app_main_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) 4781488St.nateldemoura@f5.com { 4791503St.nateldemoura@f5.com nxt_int_t cap_setid; 4801488St.nateldemoura@f5.com nxt_int_t ret; 4811488St.nateldemoura@f5.com nxt_runtime_t *rt; 4821488St.nateldemoura@f5.com nxt_common_app_conf_t *app_conf; 4831488St.nateldemoura@f5.com 4841488St.nateldemoura@f5.com rt = task->thread->runtime; 4851488St.nateldemoura@f5.com app_conf = process->data.app; 4861488St.nateldemoura@f5.com cap_setid = rt->capabilities.setid; 4871488St.nateldemoura@f5.com 4881488St.nateldemoura@f5.com if (app_conf->isolation != NULL) { 4891489St.nateldemoura@f5.com ret = nxt_app_set_isolation(task, app_conf->isolation, process); 4901488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 4911488St.nateldemoura@f5.com return ret; 4921488St.nateldemoura@f5.com } 4931488St.nateldemoura@f5.com } 4941488St.nateldemoura@f5.com 4951488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 4961488St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { 4971488St.nateldemoura@f5.com cap_setid = 1; 4981489St.nateldemoura@f5.com } 4991489St.nateldemoura@f5.com #endif 5001489St.nateldemoura@f5.com 5011489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 5021489St.nateldemoura@f5.com if (process->isolation.rootfs != NULL) { 5031503St.nateldemoura@f5.com ret = nxt_app_set_isolation_mounts(task, process, &app_conf->type); 5041503St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 5051503St.nateldemoura@f5.com return ret; 5061489St.nateldemoura@f5.com } 5071488St.nateldemoura@f5.com } 5081488St.nateldemoura@f5.com #endif 5091488St.nateldemoura@f5.com 5101488St.nateldemoura@f5.com if (cap_setid) { 5111488St.nateldemoura@f5.com ret = nxt_process_creds_set(task, process, &app_conf->user, 5121488St.nateldemoura@f5.com &app_conf->group); 5131488St.nateldemoura@f5.com 5141488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 5151488St.nateldemoura@f5.com return ret; 5161488St.nateldemoura@f5.com } 5171488St.nateldemoura@f5.com 5181488St.nateldemoura@f5.com } else { 5191488St.nateldemoura@f5.com if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user, 5201488St.nateldemoura@f5.com nxt_strlen(rt->user_cred.user))) 5211488St.nateldemoura@f5.com { 5221488St.nateldemoura@f5.com nxt_alert(task, "cannot set user \"%V\" for app \"%V\": " 5231488St.nateldemoura@f5.com "missing capabilities", &app_conf->user, &app_conf->name); 5241488St.nateldemoura@f5.com 5251488St.nateldemoura@f5.com return NXT_ERROR; 5261488St.nateldemoura@f5.com } 5271488St.nateldemoura@f5.com 5281488St.nateldemoura@f5.com if (app_conf->group.length > 0 5291488St.nateldemoura@f5.com && !nxt_str_eq(&app_conf->group, (u_char *) rt->group, 5301488St.nateldemoura@f5.com nxt_strlen(rt->group))) 5311488St.nateldemoura@f5.com { 5321488St.nateldemoura@f5.com nxt_alert(task, "cannot set group \"%V\" for app \"%V\": " 5331488St.nateldemoura@f5.com "missing capabilities", &app_conf->group, 5341488St.nateldemoura@f5.com &app_conf->name); 5351488St.nateldemoura@f5.com 5361488St.nateldemoura@f5.com return NXT_ERROR; 5371488St.nateldemoura@f5.com } 5381488St.nateldemoura@f5.com } 5391488St.nateldemoura@f5.com 5401488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 5411488St.nateldemoura@f5.com ret = nxt_process_vldt_isolation_creds(task, process); 5421488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 5431488St.nateldemoura@f5.com return ret; 5441488St.nateldemoura@f5.com } 5451488St.nateldemoura@f5.com #endif 5461488St.nateldemoura@f5.com 5471488St.nateldemoura@f5.com return NXT_OK; 5481488St.nateldemoura@f5.com } 5491488St.nateldemoura@f5.com 5501488St.nateldemoura@f5.com 5511488St.nateldemoura@f5.com static nxt_int_t 5521488St.nateldemoura@f5.com nxt_app_setup(nxt_task_t *task, nxt_process_t *process) 5530Sigor@sysoev.ru { 554216Sigor@sysoev.ru nxt_int_t ret; 5551488St.nateldemoura@f5.com nxt_process_init_t *init; 556216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 557216Sigor@sysoev.ru nxt_common_app_conf_t *app_conf; 558141Smax.romanov@nginx.com 5591488St.nateldemoura@f5.com app_conf = process->data.app; 560141Smax.romanov@nginx.com 561216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); 562216Sigor@sysoev.ru if (nxt_slow_path(lang == NULL)) { 563564Svbart@nginx.com nxt_alert(task, "unknown application type: \"%V\"", &app_conf->type); 564216Sigor@sysoev.ru return NXT_ERROR; 565216Sigor@sysoev.ru } 566216Sigor@sysoev.ru 567216Sigor@sysoev.ru nxt_app = lang->module; 568216Sigor@sysoev.ru 569216Sigor@sysoev.ru if (nxt_app == NULL) { 570354Svbart@nginx.com nxt_debug(task, "application language module: %s \"%s\"", 571354Svbart@nginx.com lang->version, lang->file); 572216Sigor@sysoev.ru 573216Sigor@sysoev.ru nxt_app = nxt_app_module_load(task, lang->file); 5741239Smax.romanov@nginx.com if (nxt_slow_path(nxt_app == NULL)) { 5751239Smax.romanov@nginx.com return NXT_ERROR; 5761239Smax.romanov@nginx.com } 577216Sigor@sysoev.ru } 578216Sigor@sysoev.ru 5791489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_environment(app_conf->environment) 5801489St.nateldemoura@f5.com != NXT_OK)) 5811489St.nateldemoura@f5.com { 5821489St.nateldemoura@f5.com nxt_alert(task, "failed to set environment"); 5831489St.nateldemoura@f5.com return NXT_ERROR; 5841489St.nateldemoura@f5.com } 5851489St.nateldemoura@f5.com 5861488St.nateldemoura@f5.com if (nxt_app->setup != NULL) { 5871488St.nateldemoura@f5.com ret = nxt_app->setup(task, process, app_conf); 588977Smax.romanov@gmail.com 589977Smax.romanov@gmail.com if (nxt_slow_path(ret != NXT_OK)) { 5901104Smax.romanov@nginx.com return ret; 591977Smax.romanov@gmail.com } 592977Smax.romanov@gmail.com } 593977Smax.romanov@gmail.com 5941489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 5951489St.nateldemoura@f5.com if (process->isolation.rootfs != NULL) { 5961489St.nateldemoura@f5.com if (process->isolation.mounts != NULL) { 5971489St.nateldemoura@f5.com ret = nxt_app_prepare_rootfs(task, process); 5981489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 5991489St.nateldemoura@f5.com return ret; 6001489St.nateldemoura@f5.com } 6011489St.nateldemoura@f5.com } 6021489St.nateldemoura@f5.com 6031489St.nateldemoura@f5.com ret = nxt_process_change_root(task, process); 6041489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 6051489St.nateldemoura@f5.com return NXT_ERROR; 6061489St.nateldemoura@f5.com } 6071489St.nateldemoura@f5.com } 6081489St.nateldemoura@f5.com #endif 6091489St.nateldemoura@f5.com 610277Sigor@sysoev.ru if (app_conf->working_directory != NULL 611277Sigor@sysoev.ru && app_conf->working_directory[0] != 0) 612271Smax.romanov@nginx.com { 613271Smax.romanov@nginx.com ret = chdir(app_conf->working_directory); 614271Smax.romanov@nginx.com 615271Smax.romanov@nginx.com if (nxt_slow_path(ret != 0)) { 616271Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E", 617271Smax.romanov@nginx.com app_conf->working_directory, nxt_errno); 618271Smax.romanov@nginx.com 619271Smax.romanov@nginx.com return NXT_ERROR; 620271Smax.romanov@nginx.com } 621271Smax.romanov@nginx.com } 622271Smax.romanov@nginx.com 6231488St.nateldemoura@f5.com init = nxt_process_init(process); 624141Smax.romanov@nginx.com 6251488St.nateldemoura@f5.com init->start = nxt_app->start; 626141Smax.romanov@nginx.com 6271488St.nateldemoura@f5.com process->state = NXT_PROCESS_STATE_CREATED; 62820Sigor@sysoev.ru 6291488St.nateldemoura@f5.com return NXT_OK; 63020Sigor@sysoev.ru } 63120Sigor@sysoev.ru 63220Sigor@sysoev.ru 633216Sigor@sysoev.ru static nxt_app_module_t * 634216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name) 635216Sigor@sysoev.ru { 636216Sigor@sysoev.ru void *dl; 637216Sigor@sysoev.ru 638216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); 639216Sigor@sysoev.ru 640216Sigor@sysoev.ru if (dl != NULL) { 641216Sigor@sysoev.ru return dlsym(dl, "nxt_app_module"); 642216Sigor@sysoev.ru } 643216Sigor@sysoev.ru 644564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 645216Sigor@sysoev.ru 646216Sigor@sysoev.ru return NULL; 647216Sigor@sysoev.ru } 648216Sigor@sysoev.ru 649216Sigor@sysoev.ru 650678Svbart@nginx.com static nxt_int_t 651678Svbart@nginx.com nxt_app_set_environment(nxt_conf_value_t *environment) 652678Svbart@nginx.com { 653678Svbart@nginx.com char *env, *p; 654678Svbart@nginx.com uint32_t next; 655678Svbart@nginx.com nxt_str_t name, value; 656678Svbart@nginx.com nxt_conf_value_t *value_obj; 657678Svbart@nginx.com 658678Svbart@nginx.com if (environment != NULL) { 659678Svbart@nginx.com next = 0; 660678Svbart@nginx.com 661678Svbart@nginx.com for ( ;; ) { 662678Svbart@nginx.com value_obj = nxt_conf_next_object_member(environment, &name, &next); 663678Svbart@nginx.com if (value_obj == NULL) { 664678Svbart@nginx.com break; 665678Svbart@nginx.com } 666678Svbart@nginx.com 667678Svbart@nginx.com nxt_conf_get_string(value_obj, &value); 668678Svbart@nginx.com 669678Svbart@nginx.com env = nxt_malloc(name.length + value.length + 2); 670678Svbart@nginx.com if (nxt_slow_path(env == NULL)) { 671678Svbart@nginx.com return NXT_ERROR; 672678Svbart@nginx.com } 673678Svbart@nginx.com 674678Svbart@nginx.com p = nxt_cpymem(env, name.start, name.length); 675678Svbart@nginx.com *p++ = '='; 676678Svbart@nginx.com p = nxt_cpymem(p, value.start, value.length); 677678Svbart@nginx.com *p = '\0'; 678678Svbart@nginx.com 679678Svbart@nginx.com if (nxt_slow_path(putenv(env) != 0)) { 680678Svbart@nginx.com return NXT_ERROR; 681678Svbart@nginx.com } 682678Svbart@nginx.com } 683678Svbart@nginx.com } 684678Svbart@nginx.com 685678Svbart@nginx.com return NXT_OK; 686678Svbart@nginx.com } 687678Svbart@nginx.com 688678Svbart@nginx.com 6891488St.nateldemoura@f5.com static nxt_int_t 6901489St.nateldemoura@f5.com nxt_app_set_isolation(nxt_task_t *task, nxt_conf_value_t *isolation, 6911488St.nateldemoura@f5.com nxt_process_t *process) 6921488St.nateldemoura@f5.com { 6931488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 6941489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_namespaces(task, isolation, process) 6951489St.nateldemoura@f5.com != NXT_OK)) 6961489St.nateldemoura@f5.com { 6971489St.nateldemoura@f5.com return NXT_ERROR; 6981489St.nateldemoura@f5.com } 6991489St.nateldemoura@f5.com #endif 7001489St.nateldemoura@f5.com 7011489St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 7021489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_creds(task, isolation, process) 7031489St.nateldemoura@f5.com != NXT_OK)) 7041489St.nateldemoura@f5.com { 7051489St.nateldemoura@f5.com return NXT_ERROR; 7061489St.nateldemoura@f5.com } 7071489St.nateldemoura@f5.com #endif 7081489St.nateldemoura@f5.com 7091489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 7101489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_rootfs(task, isolation, process) 7111489St.nateldemoura@f5.com != NXT_OK)) 7121489St.nateldemoura@f5.com { 7131489St.nateldemoura@f5.com return NXT_ERROR; 7141489St.nateldemoura@f5.com } 7151489St.nateldemoura@f5.com #endif 7161489St.nateldemoura@f5.com 7171489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 7181489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_new_privs(task, isolation, process) 7191489St.nateldemoura@f5.com != NXT_OK)) 7201489St.nateldemoura@f5.com { 7211489St.nateldemoura@f5.com return NXT_ERROR; 7221489St.nateldemoura@f5.com } 7231489St.nateldemoura@f5.com #endif 7241489St.nateldemoura@f5.com 7251489St.nateldemoura@f5.com return NXT_OK; 7261489St.nateldemoura@f5.com } 7271489St.nateldemoura@f5.com 7281489St.nateldemoura@f5.com 7291489St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 7301489St.nateldemoura@f5.com 7311489St.nateldemoura@f5.com static nxt_int_t 7321489St.nateldemoura@f5.com nxt_app_set_isolation_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation, 7331489St.nateldemoura@f5.com nxt_process_t *process) 7341489St.nateldemoura@f5.com { 7351488St.nateldemoura@f5.com nxt_int_t ret; 7361488St.nateldemoura@f5.com nxt_conf_value_t *obj; 7371488St.nateldemoura@f5.com 7381488St.nateldemoura@f5.com static nxt_str_t nsname = nxt_string("namespaces"); 7391488St.nateldemoura@f5.com 7401488St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &nsname, NULL); 7411488St.nateldemoura@f5.com if (obj != NULL) { 7421488St.nateldemoura@f5.com ret = nxt_app_clone_flags(task, obj, &process->isolation.clone); 7431488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7441488St.nateldemoura@f5.com return NXT_ERROR; 7451488St.nateldemoura@f5.com } 7461488St.nateldemoura@f5.com } 7471488St.nateldemoura@f5.com 7481488St.nateldemoura@f5.com return NXT_OK; 7491488St.nateldemoura@f5.com } 7501488St.nateldemoura@f5.com 7511489St.nateldemoura@f5.com #endif 7521489St.nateldemoura@f5.com 7531489St.nateldemoura@f5.com 7541488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 7551488St.nateldemoura@f5.com 7561488St.nateldemoura@f5.com static nxt_int_t 7571489St.nateldemoura@f5.com nxt_app_set_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation, 7581488St.nateldemoura@f5.com nxt_process_t *process) 7591488St.nateldemoura@f5.com { 7601488St.nateldemoura@f5.com nxt_int_t ret; 7611488St.nateldemoura@f5.com nxt_clone_t *clone; 7621488St.nateldemoura@f5.com nxt_conf_value_t *array; 7631488St.nateldemoura@f5.com 7641488St.nateldemoura@f5.com static nxt_str_t uidname = nxt_string("uidmap"); 7651488St.nateldemoura@f5.com static nxt_str_t gidname = nxt_string("gidmap"); 7661488St.nateldemoura@f5.com 7671488St.nateldemoura@f5.com clone = &process->isolation.clone; 7681488St.nateldemoura@f5.com 7691488St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &uidname, NULL); 7701488St.nateldemoura@f5.com if (array != NULL) { 7711488St.nateldemoura@f5.com ret = nxt_app_isolation_credential_map(task, process->mem_pool, array, 7721488St.nateldemoura@f5.com &clone->uidmap); 7731488St.nateldemoura@f5.com 7741488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7751488St.nateldemoura@f5.com return NXT_ERROR; 7761488St.nateldemoura@f5.com } 7771488St.nateldemoura@f5.com } 7781488St.nateldemoura@f5.com 7791488St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &gidname, NULL); 7801488St.nateldemoura@f5.com if (array != NULL) { 7811488St.nateldemoura@f5.com ret = nxt_app_isolation_credential_map(task, process->mem_pool, array, 7821488St.nateldemoura@f5.com &clone->gidmap); 7831488St.nateldemoura@f5.com 7841488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7851488St.nateldemoura@f5.com return NXT_ERROR; 7861488St.nateldemoura@f5.com } 7871488St.nateldemoura@f5.com } 7881488St.nateldemoura@f5.com 7891488St.nateldemoura@f5.com return NXT_OK; 7901488St.nateldemoura@f5.com } 7911488St.nateldemoura@f5.com 7921488St.nateldemoura@f5.com 7931488St.nateldemoura@f5.com static nxt_int_t 7941488St.nateldemoura@f5.com nxt_app_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mp, 7951488St.nateldemoura@f5.com nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map) 7961488St.nateldemoura@f5.com { 7971488St.nateldemoura@f5.com nxt_int_t ret; 7981488St.nateldemoura@f5.com nxt_uint_t i; 7991488St.nateldemoura@f5.com nxt_conf_value_t *obj; 8001488St.nateldemoura@f5.com 8011488St.nateldemoura@f5.com static nxt_conf_map_t nxt_clone_map_entry_conf[] = { 8021488St.nateldemoura@f5.com { 8031488St.nateldemoura@f5.com nxt_string("container"), 8041488St.nateldemoura@f5.com NXT_CONF_MAP_INT, 8051488St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, container), 8061488St.nateldemoura@f5.com }, 8071488St.nateldemoura@f5.com 8081488St.nateldemoura@f5.com { 8091488St.nateldemoura@f5.com nxt_string("host"), 8101488St.nateldemoura@f5.com NXT_CONF_MAP_INT, 8111488St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, host), 8121488St.nateldemoura@f5.com }, 8131488St.nateldemoura@f5.com 8141488St.nateldemoura@f5.com { 8151488St.nateldemoura@f5.com nxt_string("size"), 8161488St.nateldemoura@f5.com NXT_CONF_MAP_INT, 8171488St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, size), 8181488St.nateldemoura@f5.com }, 8191488St.nateldemoura@f5.com }; 8201488St.nateldemoura@f5.com 8211488St.nateldemoura@f5.com map->size = nxt_conf_array_elements_count(map_array); 8221488St.nateldemoura@f5.com 8231488St.nateldemoura@f5.com if (map->size == 0) { 8241488St.nateldemoura@f5.com return NXT_OK; 8251488St.nateldemoura@f5.com } 8261488St.nateldemoura@f5.com 8271488St.nateldemoura@f5.com map->map = nxt_mp_alloc(mp, map->size * sizeof(nxt_clone_map_entry_t)); 8281488St.nateldemoura@f5.com if (nxt_slow_path(map->map == NULL)) { 8291488St.nateldemoura@f5.com return NXT_ERROR; 8301488St.nateldemoura@f5.com } 8311488St.nateldemoura@f5.com 8321488St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 8331488St.nateldemoura@f5.com obj = nxt_conf_get_array_element(map_array, i); 8341488St.nateldemoura@f5.com 8351488St.nateldemoura@f5.com ret = nxt_conf_map_object(mp, obj, nxt_clone_map_entry_conf, 8361488St.nateldemoura@f5.com nxt_nitems(nxt_clone_map_entry_conf), 8371488St.nateldemoura@f5.com map->map + i); 8381488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 8391488St.nateldemoura@f5.com nxt_alert(task, "clone map entry map error"); 8401488St.nateldemoura@f5.com return NXT_ERROR; 8411488St.nateldemoura@f5.com } 8421488St.nateldemoura@f5.com } 8431488St.nateldemoura@f5.com 8441488St.nateldemoura@f5.com return NXT_OK; 8451488St.nateldemoura@f5.com } 8461488St.nateldemoura@f5.com 8471488St.nateldemoura@f5.com #endif 8481488St.nateldemoura@f5.com 8491488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 8501488St.nateldemoura@f5.com 8511488St.nateldemoura@f5.com static nxt_int_t 8521488St.nateldemoura@f5.com nxt_app_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces, 8531488St.nateldemoura@f5.com nxt_clone_t *clone) 8541488St.nateldemoura@f5.com { 8551488St.nateldemoura@f5.com uint32_t index; 8561488St.nateldemoura@f5.com nxt_str_t name; 8571488St.nateldemoura@f5.com nxt_int_t flag; 8581488St.nateldemoura@f5.com nxt_conf_value_t *value; 8591488St.nateldemoura@f5.com 8601488St.nateldemoura@f5.com index = 0; 8611488St.nateldemoura@f5.com 8621488St.nateldemoura@f5.com for ( ;; ) { 8631488St.nateldemoura@f5.com value = nxt_conf_next_object_member(namespaces, &name, &index); 8641488St.nateldemoura@f5.com 8651488St.nateldemoura@f5.com if (value == NULL) { 8661488St.nateldemoura@f5.com break; 8671488St.nateldemoura@f5.com } 8681488St.nateldemoura@f5.com 8691488St.nateldemoura@f5.com flag = 0; 8701488St.nateldemoura@f5.com 8711488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 8721488St.nateldemoura@f5.com if (nxt_str_eq(&name, "credential", 10)) { 8731488St.nateldemoura@f5.com flag = CLONE_NEWUSER; 8741488St.nateldemoura@f5.com } 8751488St.nateldemoura@f5.com #endif 8761488St.nateldemoura@f5.com 8771488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWPID) 8781488St.nateldemoura@f5.com if (nxt_str_eq(&name, "pid", 3)) { 8791488St.nateldemoura@f5.com flag = CLONE_NEWPID; 8801488St.nateldemoura@f5.com } 8811488St.nateldemoura@f5.com #endif 8821488St.nateldemoura@f5.com 8831488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNET) 8841488St.nateldemoura@f5.com if (nxt_str_eq(&name, "network", 7)) { 8851488St.nateldemoura@f5.com flag = CLONE_NEWNET; 8861488St.nateldemoura@f5.com } 8871488St.nateldemoura@f5.com #endif 8881488St.nateldemoura@f5.com 8891488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUTS) 8901488St.nateldemoura@f5.com if (nxt_str_eq(&name, "uname", 5)) { 8911488St.nateldemoura@f5.com flag = CLONE_NEWUTS; 8921488St.nateldemoura@f5.com } 8931488St.nateldemoura@f5.com #endif 8941488St.nateldemoura@f5.com 8951488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNS) 8961488St.nateldemoura@f5.com if (nxt_str_eq(&name, "mount", 5)) { 8971488St.nateldemoura@f5.com flag = CLONE_NEWNS; 8981488St.nateldemoura@f5.com } 8991488St.nateldemoura@f5.com #endif 9001488St.nateldemoura@f5.com 9011488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWCGROUP) 9021488St.nateldemoura@f5.com if (nxt_str_eq(&name, "cgroup", 6)) { 9031488St.nateldemoura@f5.com flag = CLONE_NEWCGROUP; 9041488St.nateldemoura@f5.com } 9051488St.nateldemoura@f5.com #endif 9061488St.nateldemoura@f5.com 9071488St.nateldemoura@f5.com if (!flag) { 9081488St.nateldemoura@f5.com nxt_alert(task, "unknown namespace flag: \"%V\"", &name); 9091488St.nateldemoura@f5.com return NXT_ERROR; 9101488St.nateldemoura@f5.com } 9111488St.nateldemoura@f5.com 9121488St.nateldemoura@f5.com if (nxt_conf_get_boolean(value)) { 9131488St.nateldemoura@f5.com clone->flags |= flag; 9141488St.nateldemoura@f5.com } 9151488St.nateldemoura@f5.com } 9161488St.nateldemoura@f5.com 9171488St.nateldemoura@f5.com return NXT_OK; 9181488St.nateldemoura@f5.com } 9191488St.nateldemoura@f5.com 9201488St.nateldemoura@f5.com #endif 9211488St.nateldemoura@f5.com 9221488St.nateldemoura@f5.com 9231489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 9241489St.nateldemoura@f5.com 9251489St.nateldemoura@f5.com static nxt_int_t 9261503St.nateldemoura@f5.com nxt_app_set_isolation_rootfs(nxt_task_t *task, nxt_conf_value_t *isolation, 9271503St.nateldemoura@f5.com nxt_process_t *process) 9281503St.nateldemoura@f5.com { 9291503St.nateldemoura@f5.com nxt_str_t str; 9301503St.nateldemoura@f5.com nxt_conf_value_t *obj; 9311503St.nateldemoura@f5.com 9321503St.nateldemoura@f5.com static nxt_str_t rootfs_name = nxt_string("rootfs"); 9331503St.nateldemoura@f5.com 9341503St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &rootfs_name, NULL); 9351503St.nateldemoura@f5.com if (obj != NULL) { 9361503St.nateldemoura@f5.com nxt_conf_get_string(obj, &str); 9371503St.nateldemoura@f5.com 9381503St.nateldemoura@f5.com if (nxt_slow_path(str.length <= 1 || str.start[0] != '/')) { 9391503St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "rootfs requires an absolute path other " 9401503St.nateldemoura@f5.com "than \"/\" but given \"%V\"", &str); 9411503St.nateldemoura@f5.com 9421503St.nateldemoura@f5.com return NXT_ERROR; 9431503St.nateldemoura@f5.com } 9441503St.nateldemoura@f5.com 9451503St.nateldemoura@f5.com if (str.start[str.length - 1] == '/') { 9461503St.nateldemoura@f5.com str.length--; 9471503St.nateldemoura@f5.com } 9481503St.nateldemoura@f5.com 9491503St.nateldemoura@f5.com process->isolation.rootfs = nxt_mp_alloc(process->mem_pool, 9501503St.nateldemoura@f5.com str.length + 1); 9511503St.nateldemoura@f5.com 9521503St.nateldemoura@f5.com if (nxt_slow_path(process->isolation.rootfs == NULL)) { 9531503St.nateldemoura@f5.com return NXT_ERROR; 9541503St.nateldemoura@f5.com } 9551503St.nateldemoura@f5.com 9561503St.nateldemoura@f5.com nxt_memcpy(process->isolation.rootfs, str.start, str.length); 9571503St.nateldemoura@f5.com 9581503St.nateldemoura@f5.com process->isolation.rootfs[str.length] = '\0'; 9591503St.nateldemoura@f5.com } 9601503St.nateldemoura@f5.com 9611503St.nateldemoura@f5.com return NXT_OK; 9621503St.nateldemoura@f5.com } 9631503St.nateldemoura@f5.com 9641503St.nateldemoura@f5.com 9651503St.nateldemoura@f5.com static nxt_int_t 9661503St.nateldemoura@f5.com nxt_app_set_isolation_mounts(nxt_task_t *task, nxt_process_t *process, 9671503St.nateldemoura@f5.com nxt_str_t *app_type) 9681503St.nateldemoura@f5.com { 9691503St.nateldemoura@f5.com nxt_int_t ret, cap_chroot; 9701503St.nateldemoura@f5.com nxt_runtime_t *rt; 9711503St.nateldemoura@f5.com nxt_app_lang_module_t *lang; 9721503St.nateldemoura@f5.com 9731503St.nateldemoura@f5.com rt = task->thread->runtime; 9741503St.nateldemoura@f5.com cap_chroot = rt->capabilities.chroot; 9751503St.nateldemoura@f5.com lang = nxt_app_lang_module(rt, app_type); 9761503St.nateldemoura@f5.com 9771503St.nateldemoura@f5.com nxt_assert(lang != NULL); 9781503St.nateldemoura@f5.com 9791503St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 9801503St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { 9811503St.nateldemoura@f5.com cap_chroot = 1; 9821503St.nateldemoura@f5.com } 9831503St.nateldemoura@f5.com #endif 9841503St.nateldemoura@f5.com 9851503St.nateldemoura@f5.com if (!cap_chroot) { 9861503St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "The \"rootfs\" field requires privileges"); 9871503St.nateldemoura@f5.com return NXT_ERROR; 9881503St.nateldemoura@f5.com } 9891503St.nateldemoura@f5.com 9901503St.nateldemoura@f5.com if (lang->mounts != NULL && lang->mounts->nelts > 0) { 9911503St.nateldemoura@f5.com ret = nxt_app_set_lang_mounts(task, process, lang->mounts); 9921503St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 9931503St.nateldemoura@f5.com return NXT_ERROR; 9941503St.nateldemoura@f5.com } 9951503St.nateldemoura@f5.com } 9961503St.nateldemoura@f5.com 9971503St.nateldemoura@f5.com return NXT_OK; 9981503St.nateldemoura@f5.com } 9991503St.nateldemoura@f5.com 10001503St.nateldemoura@f5.com 10011503St.nateldemoura@f5.com static nxt_int_t 10021503St.nateldemoura@f5.com nxt_app_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, 10031489St.nateldemoura@f5.com nxt_array_t *lang_mounts) 10041489St.nateldemoura@f5.com { 10051489St.nateldemoura@f5.com u_char *p; 10061489St.nateldemoura@f5.com size_t i, n, rootfs_len, len; 10071489St.nateldemoura@f5.com nxt_mp_t *mp; 10081489St.nateldemoura@f5.com nxt_array_t *mounts; 10091489St.nateldemoura@f5.com const u_char *rootfs; 10101489St.nateldemoura@f5.com nxt_fs_mount_t *mnt, *lang_mnt; 10111489St.nateldemoura@f5.com 10121489St.nateldemoura@f5.com rootfs = process->isolation.rootfs; 10131489St.nateldemoura@f5.com rootfs_len = nxt_strlen(rootfs); 10141489St.nateldemoura@f5.com mp = process->mem_pool; 10151489St.nateldemoura@f5.com 10161489St.nateldemoura@f5.com /* copy to init mem pool */ 10171489St.nateldemoura@f5.com mounts = nxt_array_copy(mp, NULL, lang_mounts); 10181489St.nateldemoura@f5.com if (mounts == NULL) { 10191489St.nateldemoura@f5.com return NXT_ERROR; 10201489St.nateldemoura@f5.com } 10211489St.nateldemoura@f5.com 10221489St.nateldemoura@f5.com n = mounts->nelts; 10231489St.nateldemoura@f5.com mnt = mounts->elts; 10241489St.nateldemoura@f5.com lang_mnt = lang_mounts->elts; 10251489St.nateldemoura@f5.com 10261489St.nateldemoura@f5.com for (i = 0; i < n; i++) { 10271489St.nateldemoura@f5.com len = nxt_strlen(lang_mnt[i].dst); 10281489St.nateldemoura@f5.com 10291489St.nateldemoura@f5.com mnt[i].dst = nxt_mp_alloc(mp, rootfs_len + len + 1); 10301489St.nateldemoura@f5.com if (mnt[i].dst == NULL) { 10311489St.nateldemoura@f5.com return NXT_ERROR; 10321489St.nateldemoura@f5.com } 10331489St.nateldemoura@f5.com 10341489St.nateldemoura@f5.com p = nxt_cpymem(mnt[i].dst, rootfs, rootfs_len); 10351489St.nateldemoura@f5.com p = nxt_cpymem(p, lang_mnt[i].dst, len); 10361489St.nateldemoura@f5.com *p = '\0'; 10371489St.nateldemoura@f5.com } 10381489St.nateldemoura@f5.com 10391489St.nateldemoura@f5.com process->isolation.mounts = mounts; 10401489St.nateldemoura@f5.com 10411489St.nateldemoura@f5.com return NXT_OK; 10421489St.nateldemoura@f5.com } 10431489St.nateldemoura@f5.com 10441489St.nateldemoura@f5.com 10451489St.nateldemoura@f5.com static nxt_int_t 10461489St.nateldemoura@f5.com nxt_app_prepare_rootfs(nxt_task_t *task, nxt_process_t *process) 10471489St.nateldemoura@f5.com { 10481489St.nateldemoura@f5.com size_t i, n; 10491489St.nateldemoura@f5.com nxt_int_t ret, hasproc; 10501489St.nateldemoura@f5.com struct stat st; 10511489St.nateldemoura@f5.com nxt_array_t *mounts; 10521489St.nateldemoura@f5.com const u_char *dst; 10531489St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 10541489St.nateldemoura@f5.com 10551489St.nateldemoura@f5.com hasproc = 0; 10561489St.nateldemoura@f5.com 10571489St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWPID) && (NXT_HAVE_CLONE_NEWNS) 10581489St.nateldemoura@f5.com nxt_fs_mount_t mount; 10591489St.nateldemoura@f5.com 10601489St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID) 10611489St.nateldemoura@f5.com && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) 10621489St.nateldemoura@f5.com { 10631489St.nateldemoura@f5.com /* 10641489St.nateldemoura@f5.com * This mount point will automatically be gone when the namespace is 10651489St.nateldemoura@f5.com * destroyed. 10661489St.nateldemoura@f5.com */ 10671489St.nateldemoura@f5.com 10681489St.nateldemoura@f5.com mount.fstype = (u_char *) "proc"; 10691489St.nateldemoura@f5.com mount.src = (u_char *) "proc"; 10701489St.nateldemoura@f5.com mount.dst = (u_char *) "/proc"; 10711489St.nateldemoura@f5.com mount.data = (u_char *) ""; 10721489St.nateldemoura@f5.com mount.flags = 0; 10731489St.nateldemoura@f5.com 10741489St.nateldemoura@f5.com ret = nxt_fs_mkdir_all(mount.dst, S_IRWXU | S_IRWXG | S_IRWXO); 10751489St.nateldemoura@f5.com if (nxt_fast_path(ret == NXT_OK)) { 10761489St.nateldemoura@f5.com ret = nxt_fs_mount(task, &mount); 10771489St.nateldemoura@f5.com if (nxt_fast_path(ret == NXT_OK)) { 10781489St.nateldemoura@f5.com hasproc = 1; 10791489St.nateldemoura@f5.com } 10801489St.nateldemoura@f5.com 10811489St.nateldemoura@f5.com } else { 10821489St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN, "mkdir(%s) %E", mount.dst, nxt_errno); 10831489St.nateldemoura@f5.com } 10841489St.nateldemoura@f5.com } 10851489St.nateldemoura@f5.com #endif 10861489St.nateldemoura@f5.com 10871489St.nateldemoura@f5.com mounts = process->isolation.mounts; 10881489St.nateldemoura@f5.com 10891489St.nateldemoura@f5.com n = mounts->nelts; 10901489St.nateldemoura@f5.com mnt = mounts->elts; 10911489St.nateldemoura@f5.com 10921489St.nateldemoura@f5.com for (i = 0; i < n; i++) { 10931489St.nateldemoura@f5.com dst = mnt[i].dst; 10941489St.nateldemoura@f5.com 10951489St.nateldemoura@f5.com if (nxt_slow_path(nxt_memcmp(mnt[i].fstype, "bind", 4) == 0 10961489St.nateldemoura@f5.com && stat((const char *) mnt[i].src, &st) != 0)) 10971489St.nateldemoura@f5.com { 10981489St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src); 10991489St.nateldemoura@f5.com continue; 11001489St.nateldemoura@f5.com } 11011489St.nateldemoura@f5.com 11021489St.nateldemoura@f5.com if (hasproc && nxt_memcmp(mnt[i].fstype, "proc", 4) == 0 11031489St.nateldemoura@f5.com && nxt_memcmp(mnt[i].dst, "/proc", 5) == 0) 11041489St.nateldemoura@f5.com { 11051489St.nateldemoura@f5.com continue; 11061489St.nateldemoura@f5.com } 11071489St.nateldemoura@f5.com 11081489St.nateldemoura@f5.com ret = nxt_fs_mkdir_all(dst, S_IRWXU | S_IRWXG | S_IRWXO); 11091489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 11101489St.nateldemoura@f5.com nxt_alert(task, "mkdir(%s) %E", dst, nxt_errno); 11111489St.nateldemoura@f5.com goto undo; 11121489St.nateldemoura@f5.com } 11131489St.nateldemoura@f5.com 11141489St.nateldemoura@f5.com ret = nxt_fs_mount(task, &mnt[i]); 11151489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 11161489St.nateldemoura@f5.com goto undo; 11171489St.nateldemoura@f5.com } 11181489St.nateldemoura@f5.com } 11191489St.nateldemoura@f5.com 11201489St.nateldemoura@f5.com return NXT_OK; 11211489St.nateldemoura@f5.com 11221489St.nateldemoura@f5.com undo: 11231489St.nateldemoura@f5.com 11241489St.nateldemoura@f5.com n = i + 1; 11251489St.nateldemoura@f5.com 11261489St.nateldemoura@f5.com for (i = 0; i < n; i++) { 11271489St.nateldemoura@f5.com nxt_fs_unmount(mnt[i].dst); 11281489St.nateldemoura@f5.com } 11291489St.nateldemoura@f5.com 11301489St.nateldemoura@f5.com return NXT_ERROR; 11311489St.nateldemoura@f5.com } 11321489St.nateldemoura@f5.com 11331489St.nateldemoura@f5.com #endif 11341489St.nateldemoura@f5.com 11351489St.nateldemoura@f5.com 11361503St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 11371503St.nateldemoura@f5.com 11381503St.nateldemoura@f5.com static nxt_int_t 11391503St.nateldemoura@f5.com nxt_app_set_isolation_new_privs(nxt_task_t *task, nxt_conf_value_t *isolation, 11401503St.nateldemoura@f5.com nxt_process_t *process) 11411503St.nateldemoura@f5.com { 11421503St.nateldemoura@f5.com nxt_conf_value_t *obj; 11431503St.nateldemoura@f5.com 11441503St.nateldemoura@f5.com static nxt_str_t new_privs_name = nxt_string("new_privs"); 11451503St.nateldemoura@f5.com 11461503St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &new_privs_name, NULL); 11471503St.nateldemoura@f5.com if (obj != NULL) { 11481503St.nateldemoura@f5.com process->isolation.new_privs = nxt_conf_get_boolean(obj); 11491503St.nateldemoura@f5.com } 11501503St.nateldemoura@f5.com 11511503St.nateldemoura@f5.com return NXT_OK; 11521503St.nateldemoura@f5.com } 11531503St.nateldemoura@f5.com 11541503St.nateldemoura@f5.com #endif 11551503St.nateldemoura@f5.com 11561503St.nateldemoura@f5.com 11571489St.nateldemoura@f5.com static u_char * 11581489St.nateldemoura@f5.com nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src) 11591489St.nateldemoura@f5.com { 11601489St.nateldemoura@f5.com u_char *p; 11611489St.nateldemoura@f5.com size_t len; 11621489St.nateldemoura@f5.com 11631489St.nateldemoura@f5.com len = nxt_strlen(src); 11641489St.nateldemoura@f5.com 11651489St.nateldemoura@f5.com if (dst == NULL) { 11661489St.nateldemoura@f5.com dst = nxt_mp_alloc(mp, len + 1); 11671489St.nateldemoura@f5.com if (nxt_slow_path(dst == NULL)) { 11681489St.nateldemoura@f5.com return NULL; 11691489St.nateldemoura@f5.com } 11701489St.nateldemoura@f5.com } 11711489St.nateldemoura@f5.com 11721489St.nateldemoura@f5.com p = nxt_cpymem(dst, src, len); 11731489St.nateldemoura@f5.com *p = '\0'; 11741489St.nateldemoura@f5.com 11751489St.nateldemoura@f5.com return dst; 11761489St.nateldemoura@f5.com } 11771489St.nateldemoura@f5.com 11781488St.nateldemoura@f5.com 1179216Sigor@sysoev.ru nxt_app_lang_module_t * 1180216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) 1181216Sigor@sysoev.ru { 1182216Sigor@sysoev.ru u_char *p, *end, *version; 1183356Svbart@nginx.com size_t version_length; 1184216Sigor@sysoev.ru nxt_uint_t i, n; 1185356Svbart@nginx.com nxt_app_type_t type; 1186216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 1187216Sigor@sysoev.ru 1188216Sigor@sysoev.ru end = name->start + name->length; 1189216Sigor@sysoev.ru version = end; 1190216Sigor@sysoev.ru 1191216Sigor@sysoev.ru for (p = name->start; p < end; p++) { 1192216Sigor@sysoev.ru if (*p == ' ') { 1193216Sigor@sysoev.ru version = p + 1; 1194216Sigor@sysoev.ru break; 1195216Sigor@sysoev.ru } 1196216Sigor@sysoev.ru 1197216Sigor@sysoev.ru if (*p >= '0' && *p <= '9') { 1198216Sigor@sysoev.ru version = p; 1199216Sigor@sysoev.ru break; 1200216Sigor@sysoev.ru } 1201216Sigor@sysoev.ru } 1202216Sigor@sysoev.ru 1203356Svbart@nginx.com type = nxt_app_parse_type(name->start, p - name->start); 1204356Svbart@nginx.com 1205356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 1206356Svbart@nginx.com return NULL; 1207356Svbart@nginx.com } 1208356Svbart@nginx.com 1209216Sigor@sysoev.ru version_length = end - version; 1210216Sigor@sysoev.ru 1211216Sigor@sysoev.ru lang = rt->languages->elts; 1212216Sigor@sysoev.ru n = rt->languages->nelts; 1213216Sigor@sysoev.ru 1214216Sigor@sysoev.ru for (i = 0; i < n; i++) { 1215354Svbart@nginx.com 1216354Svbart@nginx.com /* 1217354Svbart@nginx.com * Versions are sorted in descending order 1218354Svbart@nginx.com * so first match chooses the highest version. 1219354Svbart@nginx.com */ 1220354Svbart@nginx.com 1221356Svbart@nginx.com if (lang[i].type == type 1222354Svbart@nginx.com && nxt_strvers_match(lang[i].version, version, version_length)) 1223216Sigor@sysoev.ru { 1224216Sigor@sysoev.ru return &lang[i]; 1225216Sigor@sysoev.ru } 1226216Sigor@sysoev.ru } 1227216Sigor@sysoev.ru 1228216Sigor@sysoev.ru return NULL; 1229216Sigor@sysoev.ru } 1230216Sigor@sysoev.ru 1231216Sigor@sysoev.ru 1232510Salexander.borisov@nginx.com nxt_app_type_t 1233356Svbart@nginx.com nxt_app_parse_type(u_char *p, size_t length) 1234141Smax.romanov@nginx.com { 1235356Svbart@nginx.com nxt_str_t str; 1236356Svbart@nginx.com 1237356Svbart@nginx.com str.length = length; 1238356Svbart@nginx.com str.start = p; 1239356Svbart@nginx.com 1240804Svbart@nginx.com if (nxt_str_eq(&str, "external", 8) || nxt_str_eq(&str, "go", 2)) { 1241804Svbart@nginx.com return NXT_APP_EXTERNAL; 1242804Svbart@nginx.com 1243804Svbart@nginx.com } else if (nxt_str_eq(&str, "python", 6)) { 1244141Smax.romanov@nginx.com return NXT_APP_PYTHON; 1245141Smax.romanov@nginx.com 1246356Svbart@nginx.com } else if (nxt_str_eq(&str, "php", 3)) { 1247141Smax.romanov@nginx.com return NXT_APP_PHP; 1248141Smax.romanov@nginx.com 1249510Salexander.borisov@nginx.com } else if (nxt_str_eq(&str, "perl", 4)) { 1250510Salexander.borisov@nginx.com return NXT_APP_PERL; 1251584Salexander.borisov@nginx.com 1252584Salexander.borisov@nginx.com } else if (nxt_str_eq(&str, "ruby", 4)) { 1253584Salexander.borisov@nginx.com return NXT_APP_RUBY; 1254977Smax.romanov@gmail.com 1255977Smax.romanov@gmail.com } else if (nxt_str_eq(&str, "java", 4)) { 1256977Smax.romanov@gmail.com return NXT_APP_JAVA; 1257141Smax.romanov@nginx.com } 1258141Smax.romanov@nginx.com 1259141Smax.romanov@nginx.com return NXT_APP_UNKNOWN; 1260141Smax.romanov@nginx.com } 1261743Smax.romanov@nginx.com 1262743Smax.romanov@nginx.com 1263743Smax.romanov@nginx.com nxt_int_t 1264743Smax.romanov@nginx.com nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init) 1265743Smax.romanov@nginx.com { 1266743Smax.romanov@nginx.com nxt_port_t *my_port, *main_port; 1267743Smax.romanov@nginx.com nxt_runtime_t *rt; 1268743Smax.romanov@nginx.com 1269743Smax.romanov@nginx.com nxt_memzero(init, sizeof(nxt_unit_init_t)); 1270743Smax.romanov@nginx.com 1271743Smax.romanov@nginx.com rt = task->thread->runtime; 1272743Smax.romanov@nginx.com 1273743Smax.romanov@nginx.com main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 1274743Smax.romanov@nginx.com if (nxt_slow_path(main_port == NULL)) { 1275743Smax.romanov@nginx.com return NXT_ERROR; 1276743Smax.romanov@nginx.com } 1277743Smax.romanov@nginx.com 1278743Smax.romanov@nginx.com my_port = nxt_runtime_port_find(rt, nxt_pid, 0); 1279743Smax.romanov@nginx.com if (nxt_slow_path(my_port == NULL)) { 1280743Smax.romanov@nginx.com return NXT_ERROR; 1281743Smax.romanov@nginx.com } 1282743Smax.romanov@nginx.com 1283743Smax.romanov@nginx.com init->ready_port.id.pid = main_port->pid; 1284743Smax.romanov@nginx.com init->ready_port.id.id = main_port->id; 1285743Smax.romanov@nginx.com init->ready_port.out_fd = main_port->pair[1]; 1286743Smax.romanov@nginx.com 1287743Smax.romanov@nginx.com nxt_fd_blocking(task, main_port->pair[1]); 1288743Smax.romanov@nginx.com 12891488St.nateldemoura@f5.com init->ready_stream = my_port->process->stream; 1290743Smax.romanov@nginx.com 1291743Smax.romanov@nginx.com init->read_port.id.pid = my_port->pid; 1292743Smax.romanov@nginx.com init->read_port.id.id = my_port->id; 1293743Smax.romanov@nginx.com init->read_port.in_fd = my_port->pair[0]; 1294743Smax.romanov@nginx.com 1295743Smax.romanov@nginx.com nxt_fd_blocking(task, my_port->pair[0]); 1296743Smax.romanov@nginx.com 1297743Smax.romanov@nginx.com init->log_fd = 2; 1298743Smax.romanov@nginx.com 1299743Smax.romanov@nginx.com return NXT_OK; 1300743Smax.romanov@nginx.com } 1301