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 20*1489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 21*1489St.nateldemoura@f5.com #include <sys/prctl.h> 22*1489St.nateldemoura@f5.com #endif 23*1489St.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; 29*1489St.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); 441488St.nateldemoura@f5.com static nxt_int_t nxt_app_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); 48*1489St.nateldemoura@f5.com static u_char *nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src); 49*1489St.nateldemoura@f5.com 50*1489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 51*1489St.nateldemoura@f5.com static nxt_int_t nxt_app_prepare_rootfs(nxt_task_t *task, 52*1489St.nateldemoura@f5.com nxt_process_t *process); 53*1489St.nateldemoura@f5.com static nxt_int_t nxt_app_prepare_lang_mounts(nxt_task_t *task, 54*1489St.nateldemoura@f5.com nxt_process_t *process, nxt_array_t *syspaths); 55*1489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_rootfs(nxt_task_t *task, 56*1489St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 57*1489St.nateldemoura@f5.com #endif 58*1489St.nateldemoura@f5.com 59*1489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation(nxt_task_t *task, 601488St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 611488St.nateldemoura@f5.com 621488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 63*1489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_namespaces(nxt_task_t *task, 64*1489St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 651488St.nateldemoura@f5.com static nxt_int_t nxt_app_clone_flags(nxt_task_t *task, 661488St.nateldemoura@f5.com nxt_conf_value_t *namespaces, nxt_clone_t *clone); 671488St.nateldemoura@f5.com #endif 681488St.nateldemoura@f5.com 691488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 70*1489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_creds(nxt_task_t *task, 711488St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 721488St.nateldemoura@f5.com static nxt_int_t nxt_app_isolation_credential_map(nxt_task_t *task, 731488St.nateldemoura@f5.com nxt_mp_t *mem_pool, nxt_conf_value_t *map_array, 741488St.nateldemoura@f5.com nxt_clone_credential_map_t *map); 751488St.nateldemoura@f5.com #endif 761488St.nateldemoura@f5.com 77*1489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 78*1489St.nateldemoura@f5.com static nxt_int_t nxt_app_set_isolation_new_privs(nxt_task_t *task, 79*1489St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 80*1489St.nateldemoura@f5.com #endif 81*1489St.nateldemoura@f5.com 821488St.nateldemoura@f5.com nxt_str_t nxt_server = nxt_string(NXT_SERVER); 830Sigor@sysoev.ru 84216Sigor@sysoev.ru 85258Sigor@sysoev.ru static uint32_t compat[] = { 86360Sigor@sysoev.ru NXT_VERNUM, NXT_DEBUG, 87258Sigor@sysoev.ru }; 88258Sigor@sysoev.ru 89258Sigor@sysoev.ru 90743Smax.romanov@nginx.com static nxt_app_module_t *nxt_app; 91417Svbart@nginx.com 92417Svbart@nginx.com 931488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_discovery_process_port_handlers = { 941488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler, 951488St.nateldemoura@f5.com .new_port = nxt_port_new_port_handler, 961488St.nateldemoura@f5.com .change_file = nxt_port_change_log_file_handler, 971488St.nateldemoura@f5.com .mmap = nxt_port_mmap_handler, 981488St.nateldemoura@f5.com .data = nxt_port_data_handler, 991488St.nateldemoura@f5.com .remove_pid = nxt_port_remove_pid_handler, 1001488St.nateldemoura@f5.com .rpc_ready = nxt_port_rpc_handler, 1011488St.nateldemoura@f5.com .rpc_error = nxt_port_rpc_handler, 1021488St.nateldemoura@f5.com }; 1031488St.nateldemoura@f5.com 1041488St.nateldemoura@f5.com 1051488St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_app_process_port_handlers = { 1061488St.nateldemoura@f5.com .quit = nxt_signal_quit_handler, 1071488St.nateldemoura@f5.com .rpc_ready = nxt_port_rpc_handler, 1081488St.nateldemoura@f5.com .rpc_error = nxt_port_rpc_handler, 1091488St.nateldemoura@f5.com }; 1101488St.nateldemoura@f5.com 1111488St.nateldemoura@f5.com 1121488St.nateldemoura@f5.com const nxt_process_init_t nxt_discovery_process = { 1131488St.nateldemoura@f5.com .name = "discovery", 1141488St.nateldemoura@f5.com .type = NXT_PROCESS_DISCOVERY, 1151488St.nateldemoura@f5.com .prefork = NULL, 1161488St.nateldemoura@f5.com .restart = 0, 1171488St.nateldemoura@f5.com .setup = nxt_process_core_setup, 1181488St.nateldemoura@f5.com .start = nxt_discovery_start, 1191488St.nateldemoura@f5.com .port_handlers = &nxt_discovery_process_port_handlers, 1201488St.nateldemoura@f5.com .signals = nxt_process_signals, 1211488St.nateldemoura@f5.com }; 1221488St.nateldemoura@f5.com 1231488St.nateldemoura@f5.com 1241488St.nateldemoura@f5.com const nxt_process_init_t nxt_app_process = { 1251488St.nateldemoura@f5.com .type = NXT_PROCESS_APP, 1261488St.nateldemoura@f5.com .setup = nxt_app_setup, 1271488St.nateldemoura@f5.com .prefork = nxt_app_prefork, 1281488St.nateldemoura@f5.com .restart = 0, 1291488St.nateldemoura@f5.com .start = NULL, /* set to module->start */ 1301488St.nateldemoura@f5.com .port_handlers = &nxt_app_process_port_handlers, 1311488St.nateldemoura@f5.com .signals = nxt_process_signals, 1321488St.nateldemoura@f5.com }; 1331488St.nateldemoura@f5.com 1341488St.nateldemoura@f5.com 1351488St.nateldemoura@f5.com static nxt_int_t 1361488St.nateldemoura@f5.com nxt_discovery_start(nxt_task_t *task, nxt_process_data_t *data) 137216Sigor@sysoev.ru { 138549Svbart@nginx.com uint32_t stream; 139549Svbart@nginx.com nxt_buf_t *b; 140549Svbart@nginx.com nxt_int_t ret; 141549Svbart@nginx.com nxt_port_t *main_port, *discovery_port; 142549Svbart@nginx.com nxt_runtime_t *rt; 143216Sigor@sysoev.ru 1441488St.nateldemoura@f5.com nxt_log(task, NXT_LOG_INFO, "discovery started"); 145216Sigor@sysoev.ru 146233Sigor@sysoev.ru rt = task->thread->runtime; 147216Sigor@sysoev.ru 148233Sigor@sysoev.ru b = nxt_discovery_modules(task, rt->modules); 149250Sigor@sysoev.ru if (nxt_slow_path(b == NULL)) { 150549Svbart@nginx.com return NXT_ERROR; 151250Sigor@sysoev.ru } 152233Sigor@sysoev.ru 153240Sigor@sysoev.ru main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 154549Svbart@nginx.com discovery_port = rt->port_by_type[NXT_PROCESS_DISCOVERY]; 155216Sigor@sysoev.ru 156549Svbart@nginx.com stream = nxt_port_rpc_register_handler(task, discovery_port, 157549Svbart@nginx.com nxt_discovery_quit, 158549Svbart@nginx.com nxt_discovery_quit, 159549Svbart@nginx.com main_port->pid, NULL); 160549Svbart@nginx.com 161645Svbart@nginx.com if (nxt_slow_path(stream == 0)) { 162645Svbart@nginx.com return NXT_ERROR; 163645Svbart@nginx.com } 164645Svbart@nginx.com 165549Svbart@nginx.com ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1, 166549Svbart@nginx.com stream, discovery_port->id, b); 167549Svbart@nginx.com 168549Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 169549Svbart@nginx.com nxt_port_rpc_cancel(task, discovery_port, stream); 170549Svbart@nginx.com return NXT_ERROR; 171549Svbart@nginx.com } 172216Sigor@sysoev.ru 173216Sigor@sysoev.ru return NXT_OK; 174216Sigor@sysoev.ru } 175216Sigor@sysoev.ru 176216Sigor@sysoev.ru 177216Sigor@sysoev.ru static nxt_buf_t * 178216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path) 179216Sigor@sysoev.ru { 180*1489St.nateldemoura@f5.com char *name; 181*1489St.nateldemoura@f5.com u_char *p, *end; 182*1489St.nateldemoura@f5.com size_t size; 183*1489St.nateldemoura@f5.com glob_t glb; 184*1489St.nateldemoura@f5.com nxt_mp_t *mp; 185*1489St.nateldemoura@f5.com nxt_buf_t *b; 186*1489St.nateldemoura@f5.com nxt_int_t ret; 187*1489St.nateldemoura@f5.com nxt_uint_t i, n, j; 188*1489St.nateldemoura@f5.com nxt_array_t *modules, *mounts; 189*1489St.nateldemoura@f5.com nxt_module_t *module; 190*1489St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 191216Sigor@sysoev.ru 192216Sigor@sysoev.ru b = NULL; 193216Sigor@sysoev.ru 194216Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 195216Sigor@sysoev.ru if (mp == NULL) { 196216Sigor@sysoev.ru return b; 197216Sigor@sysoev.ru } 198216Sigor@sysoev.ru 199216Sigor@sysoev.ru ret = glob(path, 0, NULL, &glb); 200216Sigor@sysoev.ru 201250Sigor@sysoev.ru n = glb.gl_pathc; 202250Sigor@sysoev.ru 203250Sigor@sysoev.ru if (ret != 0) { 204250Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 205250Sigor@sysoev.ru "no modules matching: \"%s\" found", path); 206250Sigor@sysoev.ru n = 0; 207250Sigor@sysoev.ru } 208216Sigor@sysoev.ru 209250Sigor@sysoev.ru modules = nxt_array_create(mp, n, sizeof(nxt_module_t)); 210250Sigor@sysoev.ru if (modules == NULL) { 211250Sigor@sysoev.ru goto fail; 212250Sigor@sysoev.ru } 213250Sigor@sysoev.ru 214250Sigor@sysoev.ru for (i = 0; i < n; i++) { 215250Sigor@sysoev.ru name = glb.gl_pathv[i]; 216250Sigor@sysoev.ru 217250Sigor@sysoev.ru ret = nxt_discovery_module(task, mp, modules, name); 218250Sigor@sysoev.ru if (ret != NXT_OK) { 219216Sigor@sysoev.ru goto fail; 220216Sigor@sysoev.ru } 221250Sigor@sysoev.ru } 222216Sigor@sysoev.ru 223703Svbart@nginx.com size = nxt_length("[]"); 224250Sigor@sysoev.ru module = modules->elts; 225250Sigor@sysoev.ru n = modules->nelts; 226216Sigor@sysoev.ru 227250Sigor@sysoev.ru for (i = 0; i < n; i++) { 228356Svbart@nginx.com nxt_debug(task, "module: %d %V %V", 229356Svbart@nginx.com module[i].type, &module[i].version, &module[i].file); 230216Sigor@sysoev.ru 231703Svbart@nginx.com size += nxt_length("{\"type\": ,"); 232703Svbart@nginx.com size += nxt_length(" \"version\": \"\","); 233*1489St.nateldemoura@f5.com size += nxt_length(" \"file\": \"\","); 234*1489St.nateldemoura@f5.com size += nxt_length(" \"mounts\": []},"); 235216Sigor@sysoev.ru 236356Svbart@nginx.com size += NXT_INT_T_LEN 237250Sigor@sysoev.ru + module[i].version.length 238250Sigor@sysoev.ru + module[i].file.length; 239*1489St.nateldemoura@f5.com 240*1489St.nateldemoura@f5.com mounts = module[i].mounts; 241*1489St.nateldemoura@f5.com 242*1489St.nateldemoura@f5.com size += mounts->nelts * nxt_length("{\"src\": \"\", \"dst\": \"\", " 243*1489St.nateldemoura@f5.com "\"fstype\": \"\", \"flags\": , " 244*1489St.nateldemoura@f5.com "\"data\": \"\"},"); 245*1489St.nateldemoura@f5.com 246*1489St.nateldemoura@f5.com mnt = mounts->elts; 247*1489St.nateldemoura@f5.com 248*1489St.nateldemoura@f5.com for (j = 0; j < mounts->nelts; j++) { 249*1489St.nateldemoura@f5.com size += nxt_strlen(mnt[j].src) + nxt_strlen(mnt[j].dst) 250*1489St.nateldemoura@f5.com + nxt_strlen(mnt[j].fstype) + NXT_INT_T_LEN 251*1489St.nateldemoura@f5.com + (mnt[j].data == NULL ? 0 : nxt_strlen(mnt[j].data)); 252*1489St.nateldemoura@f5.com } 253250Sigor@sysoev.ru } 254216Sigor@sysoev.ru 255250Sigor@sysoev.ru b = nxt_buf_mem_alloc(mp, size, 0); 256250Sigor@sysoev.ru if (b == NULL) { 257250Sigor@sysoev.ru goto fail; 258250Sigor@sysoev.ru } 259216Sigor@sysoev.ru 260250Sigor@sysoev.ru b->completion_handler = nxt_discovery_completion_handler; 261216Sigor@sysoev.ru 262250Sigor@sysoev.ru p = b->mem.free; 263250Sigor@sysoev.ru end = b->mem.end; 264250Sigor@sysoev.ru *p++ = '['; 265216Sigor@sysoev.ru 266250Sigor@sysoev.ru for (i = 0; i < n; i++) { 267*1489St.nateldemoura@f5.com mounts = module[i].mounts; 268*1489St.nateldemoura@f5.com 269*1489St.nateldemoura@f5.com p = nxt_sprintf(p, end, "{\"type\": %d, \"version\": \"%V\", " 270*1489St.nateldemoura@f5.com "\"file\": \"%V\", \"mounts\": [", 271*1489St.nateldemoura@f5.com module[i].type, &module[i].version, &module[i].file); 272*1489St.nateldemoura@f5.com 273*1489St.nateldemoura@f5.com mnt = mounts->elts; 274*1489St.nateldemoura@f5.com for (j = 0; j < mounts->nelts; j++) { 275*1489St.nateldemoura@f5.com p = nxt_sprintf(p, end, 276*1489St.nateldemoura@f5.com "{\"src\": \"%s\", \"dst\": \"%s\", " 277*1489St.nateldemoura@f5.com "\"fstype\": \"%s\", \"flags\": %d, " 278*1489St.nateldemoura@f5.com "\"data\": \"%s\"},", 279*1489St.nateldemoura@f5.com mnt[j].src, mnt[j].dst, mnt[j].fstype, mnt[j].flags, 280*1489St.nateldemoura@f5.com mnt[j].data == NULL ? (u_char *) "" : mnt[j].data); 281*1489St.nateldemoura@f5.com } 282*1489St.nateldemoura@f5.com 283*1489St.nateldemoura@f5.com *p++ = ']'; 284*1489St.nateldemoura@f5.com *p++ = '}'; 285*1489St.nateldemoura@f5.com *p++ = ','; 286250Sigor@sysoev.ru } 287216Sigor@sysoev.ru 288250Sigor@sysoev.ru *p++ = ']'; 289*1489St.nateldemoura@f5.com 290*1489St.nateldemoura@f5.com if (nxt_slow_path(p >= end)) { 291*1489St.nateldemoura@f5.com nxt_alert(task, "discovery write past the buffer"); 292*1489St.nateldemoura@f5.com goto fail; 293*1489St.nateldemoura@f5.com } 294*1489St.nateldemoura@f5.com 295250Sigor@sysoev.ru b->mem.free = p; 296216Sigor@sysoev.ru 297216Sigor@sysoev.ru fail: 298216Sigor@sysoev.ru 299216Sigor@sysoev.ru globfree(&glb); 300216Sigor@sysoev.ru 301216Sigor@sysoev.ru return b; 302216Sigor@sysoev.ru } 303216Sigor@sysoev.ru 304216Sigor@sysoev.ru 305216Sigor@sysoev.ru static nxt_int_t 306216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules, 307216Sigor@sysoev.ru const char *name) 308216Sigor@sysoev.ru { 309*1489St.nateldemoura@f5.com void *dl; 310*1489St.nateldemoura@f5.com nxt_str_t version; 311*1489St.nateldemoura@f5.com nxt_int_t ret; 312*1489St.nateldemoura@f5.com nxt_uint_t i, j, n; 313*1489St.nateldemoura@f5.com nxt_array_t *mounts; 314*1489St.nateldemoura@f5.com nxt_module_t *module; 315*1489St.nateldemoura@f5.com nxt_app_type_t type; 316*1489St.nateldemoura@f5.com nxt_fs_mount_t *to; 317*1489St.nateldemoura@f5.com nxt_app_module_t *app; 318*1489St.nateldemoura@f5.com const nxt_fs_mount_t *from; 319216Sigor@sysoev.ru 320216Sigor@sysoev.ru /* 321216Sigor@sysoev.ru * Only memory allocation failure should return NXT_ERROR. 322216Sigor@sysoev.ru * Any module processing errors are ignored. 323216Sigor@sysoev.ru */ 324216Sigor@sysoev.ru ret = NXT_ERROR; 325216Sigor@sysoev.ru 326216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW); 327216Sigor@sysoev.ru 328216Sigor@sysoev.ru if (dl == NULL) { 329564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 330216Sigor@sysoev.ru return NXT_OK; 331216Sigor@sysoev.ru } 332216Sigor@sysoev.ru 333216Sigor@sysoev.ru app = dlsym(dl, "nxt_app_module"); 334216Sigor@sysoev.ru 335216Sigor@sysoev.ru if (app != NULL) { 336612Salexander.borisov@nginx.com nxt_log(task, NXT_LOG_NOTICE, "module: %V %s \"%s\"", 337612Salexander.borisov@nginx.com &app->type, app->version, name); 338258Sigor@sysoev.ru 339258Sigor@sysoev.ru if (app->compat_length != sizeof(compat) 340258Sigor@sysoev.ru || nxt_memcmp(app->compat, compat, sizeof(compat)) != 0) 341258Sigor@sysoev.ru { 342258Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name); 343258Sigor@sysoev.ru 344258Sigor@sysoev.ru goto done; 345258Sigor@sysoev.ru } 346216Sigor@sysoev.ru 347356Svbart@nginx.com type = nxt_app_parse_type(app->type.start, app->type.length); 348356Svbart@nginx.com 349356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 350494Spluknet@nginx.com nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", &app->type); 351356Svbart@nginx.com 352356Svbart@nginx.com goto done; 353356Svbart@nginx.com } 354356Svbart@nginx.com 355216Sigor@sysoev.ru module = modules->elts; 356216Sigor@sysoev.ru n = modules->nelts; 357216Sigor@sysoev.ru 358612Salexander.borisov@nginx.com version.start = (u_char *) app->version; 359612Salexander.borisov@nginx.com version.length = nxt_strlen(app->version); 360612Salexander.borisov@nginx.com 361216Sigor@sysoev.ru for (i = 0; i < n; i++) { 362356Svbart@nginx.com if (type == module[i].type 363612Salexander.borisov@nginx.com && nxt_strstr_eq(&module[i].version, &version)) 364258Sigor@sysoev.ru { 365216Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, 366216Sigor@sysoev.ru "ignoring %s module with the same " 367267Sigor@sysoev.ru "application language version %V %V as in %V", 368655Svbart@nginx.com name, &app->type, &version, &module[i].file); 369216Sigor@sysoev.ru 370216Sigor@sysoev.ru goto done; 371216Sigor@sysoev.ru } 372216Sigor@sysoev.ru } 373216Sigor@sysoev.ru 374216Sigor@sysoev.ru module = nxt_array_add(modules); 375216Sigor@sysoev.ru if (module == NULL) { 376216Sigor@sysoev.ru goto fail; 377216Sigor@sysoev.ru } 378216Sigor@sysoev.ru 379356Svbart@nginx.com module->type = type; 380216Sigor@sysoev.ru 381612Salexander.borisov@nginx.com nxt_str_dup(mp, &module->version, &version); 382612Salexander.borisov@nginx.com if (module->version.start == NULL) { 383216Sigor@sysoev.ru goto fail; 384216Sigor@sysoev.ru } 385216Sigor@sysoev.ru 386216Sigor@sysoev.ru module->file.length = nxt_strlen(name); 387216Sigor@sysoev.ru 388216Sigor@sysoev.ru module->file.start = nxt_mp_alloc(mp, module->file.length); 389216Sigor@sysoev.ru if (module->file.start == NULL) { 390216Sigor@sysoev.ru goto fail; 391216Sigor@sysoev.ru } 392216Sigor@sysoev.ru 393216Sigor@sysoev.ru nxt_memcpy(module->file.start, name, module->file.length); 394216Sigor@sysoev.ru 395*1489St.nateldemoura@f5.com module->mounts = nxt_array_create(mp, app->nmounts, 396*1489St.nateldemoura@f5.com sizeof(nxt_fs_mount_t)); 397*1489St.nateldemoura@f5.com 398*1489St.nateldemoura@f5.com if (nxt_slow_path(module->mounts == NULL)) { 399*1489St.nateldemoura@f5.com goto fail; 400*1489St.nateldemoura@f5.com } 401*1489St.nateldemoura@f5.com 402*1489St.nateldemoura@f5.com mounts = module->mounts; 403*1489St.nateldemoura@f5.com 404*1489St.nateldemoura@f5.com for (j = 0; j < app->nmounts; j++) { 405*1489St.nateldemoura@f5.com from = &app->mounts[j]; 406*1489St.nateldemoura@f5.com to = nxt_array_zero_add(mounts); 407*1489St.nateldemoura@f5.com if (nxt_slow_path(to == NULL)) { 408*1489St.nateldemoura@f5.com goto fail; 409*1489St.nateldemoura@f5.com } 410*1489St.nateldemoura@f5.com 411*1489St.nateldemoura@f5.com to->src = nxt_cstr_dup(mp, to->src, from->src); 412*1489St.nateldemoura@f5.com if (nxt_slow_path(to->src == NULL)) { 413*1489St.nateldemoura@f5.com goto fail; 414*1489St.nateldemoura@f5.com } 415*1489St.nateldemoura@f5.com 416*1489St.nateldemoura@f5.com to->dst = nxt_cstr_dup(mp, to->dst, from->dst); 417*1489St.nateldemoura@f5.com if (nxt_slow_path(to->dst == NULL)) { 418*1489St.nateldemoura@f5.com goto fail; 419*1489St.nateldemoura@f5.com } 420*1489St.nateldemoura@f5.com 421*1489St.nateldemoura@f5.com to->fstype = nxt_cstr_dup(mp, to->fstype, from->fstype); 422*1489St.nateldemoura@f5.com if (nxt_slow_path(to->fstype == NULL)) { 423*1489St.nateldemoura@f5.com goto fail; 424*1489St.nateldemoura@f5.com } 425*1489St.nateldemoura@f5.com 426*1489St.nateldemoura@f5.com if (from->data != NULL) { 427*1489St.nateldemoura@f5.com to->data = nxt_cstr_dup(mp, to->data, from->data); 428*1489St.nateldemoura@f5.com if (nxt_slow_path(to->data == NULL)) { 429*1489St.nateldemoura@f5.com goto fail; 430*1489St.nateldemoura@f5.com } 431*1489St.nateldemoura@f5.com } 432*1489St.nateldemoura@f5.com 433*1489St.nateldemoura@f5.com to->flags = from->flags; 434*1489St.nateldemoura@f5.com } 435*1489St.nateldemoura@f5.com 436216Sigor@sysoev.ru } else { 437564Svbart@nginx.com nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror()); 438216Sigor@sysoev.ru } 439216Sigor@sysoev.ru 440216Sigor@sysoev.ru done: 441216Sigor@sysoev.ru 442216Sigor@sysoev.ru ret = NXT_OK; 443216Sigor@sysoev.ru 444216Sigor@sysoev.ru fail: 445216Sigor@sysoev.ru 446216Sigor@sysoev.ru if (dlclose(dl) != 0) { 447564Svbart@nginx.com nxt_alert(task, "dlclose(\"%s\"), failed: \"%s\"", name, dlerror()); 448216Sigor@sysoev.ru } 449216Sigor@sysoev.ru 450216Sigor@sysoev.ru return ret; 451216Sigor@sysoev.ru } 452216Sigor@sysoev.ru 453216Sigor@sysoev.ru 454549Svbart@nginx.com static void 455549Svbart@nginx.com nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data) 456549Svbart@nginx.com { 457549Svbart@nginx.com nxt_mp_t *mp; 458549Svbart@nginx.com nxt_buf_t *b; 459549Svbart@nginx.com 460549Svbart@nginx.com b = obj; 461549Svbart@nginx.com mp = b->data; 462549Svbart@nginx.com 463549Svbart@nginx.com nxt_mp_destroy(mp); 464549Svbart@nginx.com } 465549Svbart@nginx.com 466549Svbart@nginx.com 467549Svbart@nginx.com static void 468549Svbart@nginx.com nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data) 469549Svbart@nginx.com { 4701488St.nateldemoura@f5.com nxt_signal_quit_handler(task, msg); 471549Svbart@nginx.com } 472549Svbart@nginx.com 473549Svbart@nginx.com 4741488St.nateldemoura@f5.com static nxt_int_t 4751488St.nateldemoura@f5.com nxt_app_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp) 4761488St.nateldemoura@f5.com { 477*1489St.nateldemoura@f5.com nxt_int_t cap_setid, cap_chroot; 4781488St.nateldemoura@f5.com nxt_int_t ret; 4791488St.nateldemoura@f5.com nxt_runtime_t *rt; 4801488St.nateldemoura@f5.com nxt_common_app_conf_t *app_conf; 481*1489St.nateldemoura@f5.com nxt_app_lang_module_t *lang; 4821488St.nateldemoura@f5.com 4831488St.nateldemoura@f5.com rt = task->thread->runtime; 4841488St.nateldemoura@f5.com app_conf = process->data.app; 4851488St.nateldemoura@f5.com cap_setid = rt->capabilities.setid; 486*1489St.nateldemoura@f5.com cap_chroot = rt->capabilities.chroot; 487*1489St.nateldemoura@f5.com 488*1489St.nateldemoura@f5.com lang = nxt_app_lang_module(rt, &app_conf->type); 489*1489St.nateldemoura@f5.com 490*1489St.nateldemoura@f5.com nxt_assert(lang != NULL); 4911488St.nateldemoura@f5.com 4921488St.nateldemoura@f5.com if (app_conf->isolation != NULL) { 493*1489St.nateldemoura@f5.com ret = nxt_app_set_isolation(task, app_conf->isolation, process); 4941488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 4951488St.nateldemoura@f5.com return ret; 4961488St.nateldemoura@f5.com } 4971488St.nateldemoura@f5.com } 4981488St.nateldemoura@f5.com 4991488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 5001488St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { 5011488St.nateldemoura@f5.com cap_setid = 1; 502*1489St.nateldemoura@f5.com cap_chroot = 1; 503*1489St.nateldemoura@f5.com } 504*1489St.nateldemoura@f5.com #endif 505*1489St.nateldemoura@f5.com 506*1489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 507*1489St.nateldemoura@f5.com if (process->isolation.rootfs != NULL) { 508*1489St.nateldemoura@f5.com if (!cap_chroot) { 509*1489St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, 510*1489St.nateldemoura@f5.com "The \"rootfs\" field requires privileges"); 511*1489St.nateldemoura@f5.com 512*1489St.nateldemoura@f5.com return NXT_ERROR; 513*1489St.nateldemoura@f5.com } 514*1489St.nateldemoura@f5.com 515*1489St.nateldemoura@f5.com if (lang->mounts != NULL && lang->mounts->nelts > 0) { 516*1489St.nateldemoura@f5.com ret = nxt_app_prepare_lang_mounts(task, process, lang->mounts); 517*1489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 518*1489St.nateldemoura@f5.com return NXT_ERROR; 519*1489St.nateldemoura@f5.com } 520*1489St.nateldemoura@f5.com } 5211488St.nateldemoura@f5.com } 5221488St.nateldemoura@f5.com #endif 5231488St.nateldemoura@f5.com 5241488St.nateldemoura@f5.com if (cap_setid) { 5251488St.nateldemoura@f5.com ret = nxt_process_creds_set(task, process, &app_conf->user, 5261488St.nateldemoura@f5.com &app_conf->group); 5271488St.nateldemoura@f5.com 5281488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 5291488St.nateldemoura@f5.com return ret; 5301488St.nateldemoura@f5.com } 5311488St.nateldemoura@f5.com 5321488St.nateldemoura@f5.com } else { 5331488St.nateldemoura@f5.com if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user, 5341488St.nateldemoura@f5.com nxt_strlen(rt->user_cred.user))) 5351488St.nateldemoura@f5.com { 5361488St.nateldemoura@f5.com nxt_alert(task, "cannot set user \"%V\" for app \"%V\": " 5371488St.nateldemoura@f5.com "missing capabilities", &app_conf->user, &app_conf->name); 5381488St.nateldemoura@f5.com 5391488St.nateldemoura@f5.com return NXT_ERROR; 5401488St.nateldemoura@f5.com } 5411488St.nateldemoura@f5.com 5421488St.nateldemoura@f5.com if (app_conf->group.length > 0 5431488St.nateldemoura@f5.com && !nxt_str_eq(&app_conf->group, (u_char *) rt->group, 5441488St.nateldemoura@f5.com nxt_strlen(rt->group))) 5451488St.nateldemoura@f5.com { 5461488St.nateldemoura@f5.com nxt_alert(task, "cannot set group \"%V\" for app \"%V\": " 5471488St.nateldemoura@f5.com "missing capabilities", &app_conf->group, 5481488St.nateldemoura@f5.com &app_conf->name); 5491488St.nateldemoura@f5.com 5501488St.nateldemoura@f5.com return NXT_ERROR; 5511488St.nateldemoura@f5.com } 5521488St.nateldemoura@f5.com } 5531488St.nateldemoura@f5.com 5541488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 5551488St.nateldemoura@f5.com ret = nxt_process_vldt_isolation_creds(task, process); 5561488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 5571488St.nateldemoura@f5.com return ret; 5581488St.nateldemoura@f5.com } 5591488St.nateldemoura@f5.com #endif 5601488St.nateldemoura@f5.com 5611488St.nateldemoura@f5.com return NXT_OK; 5621488St.nateldemoura@f5.com } 5631488St.nateldemoura@f5.com 5641488St.nateldemoura@f5.com 5651488St.nateldemoura@f5.com static nxt_int_t 5661488St.nateldemoura@f5.com nxt_app_setup(nxt_task_t *task, nxt_process_t *process) 5670Sigor@sysoev.ru { 568216Sigor@sysoev.ru nxt_int_t ret; 5691488St.nateldemoura@f5.com nxt_process_init_t *init; 570216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 571216Sigor@sysoev.ru nxt_common_app_conf_t *app_conf; 572141Smax.romanov@nginx.com 5731488St.nateldemoura@f5.com app_conf = process->data.app; 574141Smax.romanov@nginx.com 575216Sigor@sysoev.ru lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type); 576216Sigor@sysoev.ru if (nxt_slow_path(lang == NULL)) { 577564Svbart@nginx.com nxt_alert(task, "unknown application type: \"%V\"", &app_conf->type); 578216Sigor@sysoev.ru return NXT_ERROR; 579216Sigor@sysoev.ru } 580216Sigor@sysoev.ru 581216Sigor@sysoev.ru nxt_app = lang->module; 582216Sigor@sysoev.ru 583216Sigor@sysoev.ru if (nxt_app == NULL) { 584354Svbart@nginx.com nxt_debug(task, "application language module: %s \"%s\"", 585354Svbart@nginx.com lang->version, lang->file); 586216Sigor@sysoev.ru 587216Sigor@sysoev.ru nxt_app = nxt_app_module_load(task, lang->file); 5881239Smax.romanov@nginx.com if (nxt_slow_path(nxt_app == NULL)) { 5891239Smax.romanov@nginx.com return NXT_ERROR; 5901239Smax.romanov@nginx.com } 591216Sigor@sysoev.ru } 592216Sigor@sysoev.ru 593*1489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_environment(app_conf->environment) 594*1489St.nateldemoura@f5.com != NXT_OK)) 595*1489St.nateldemoura@f5.com { 596*1489St.nateldemoura@f5.com nxt_alert(task, "failed to set environment"); 597*1489St.nateldemoura@f5.com return NXT_ERROR; 598*1489St.nateldemoura@f5.com } 599*1489St.nateldemoura@f5.com 6001488St.nateldemoura@f5.com if (nxt_app->setup != NULL) { 6011488St.nateldemoura@f5.com ret = nxt_app->setup(task, process, app_conf); 602977Smax.romanov@gmail.com 603977Smax.romanov@gmail.com if (nxt_slow_path(ret != NXT_OK)) { 6041104Smax.romanov@nginx.com return ret; 605977Smax.romanov@gmail.com } 606977Smax.romanov@gmail.com } 607977Smax.romanov@gmail.com 608*1489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 609*1489St.nateldemoura@f5.com if (process->isolation.rootfs != NULL) { 610*1489St.nateldemoura@f5.com if (process->isolation.mounts != NULL) { 611*1489St.nateldemoura@f5.com ret = nxt_app_prepare_rootfs(task, process); 612*1489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 613*1489St.nateldemoura@f5.com return ret; 614*1489St.nateldemoura@f5.com } 615*1489St.nateldemoura@f5.com } 616*1489St.nateldemoura@f5.com 617*1489St.nateldemoura@f5.com ret = nxt_process_change_root(task, process); 618*1489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 619*1489St.nateldemoura@f5.com return NXT_ERROR; 620*1489St.nateldemoura@f5.com } 621*1489St.nateldemoura@f5.com } 622*1489St.nateldemoura@f5.com #endif 623*1489St.nateldemoura@f5.com 624277Sigor@sysoev.ru if (app_conf->working_directory != NULL 625277Sigor@sysoev.ru && app_conf->working_directory[0] != 0) 626271Smax.romanov@nginx.com { 627271Smax.romanov@nginx.com ret = chdir(app_conf->working_directory); 628271Smax.romanov@nginx.com 629271Smax.romanov@nginx.com if (nxt_slow_path(ret != 0)) { 630271Smax.romanov@nginx.com nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E", 631271Smax.romanov@nginx.com app_conf->working_directory, nxt_errno); 632271Smax.romanov@nginx.com 633271Smax.romanov@nginx.com return NXT_ERROR; 634271Smax.romanov@nginx.com } 635271Smax.romanov@nginx.com } 636271Smax.romanov@nginx.com 6371488St.nateldemoura@f5.com init = nxt_process_init(process); 638141Smax.romanov@nginx.com 6391488St.nateldemoura@f5.com init->start = nxt_app->start; 640141Smax.romanov@nginx.com 6411488St.nateldemoura@f5.com process->state = NXT_PROCESS_STATE_CREATED; 64220Sigor@sysoev.ru 6431488St.nateldemoura@f5.com return NXT_OK; 64420Sigor@sysoev.ru } 64520Sigor@sysoev.ru 64620Sigor@sysoev.ru 647216Sigor@sysoev.ru static nxt_app_module_t * 648216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name) 649216Sigor@sysoev.ru { 650216Sigor@sysoev.ru void *dl; 651216Sigor@sysoev.ru 652216Sigor@sysoev.ru dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY); 653216Sigor@sysoev.ru 654216Sigor@sysoev.ru if (dl != NULL) { 655216Sigor@sysoev.ru return dlsym(dl, "nxt_app_module"); 656216Sigor@sysoev.ru } 657216Sigor@sysoev.ru 658564Svbart@nginx.com nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror()); 659216Sigor@sysoev.ru 660216Sigor@sysoev.ru return NULL; 661216Sigor@sysoev.ru } 662216Sigor@sysoev.ru 663216Sigor@sysoev.ru 664678Svbart@nginx.com static nxt_int_t 665678Svbart@nginx.com nxt_app_set_environment(nxt_conf_value_t *environment) 666678Svbart@nginx.com { 667678Svbart@nginx.com char *env, *p; 668678Svbart@nginx.com uint32_t next; 669678Svbart@nginx.com nxt_str_t name, value; 670678Svbart@nginx.com nxt_conf_value_t *value_obj; 671678Svbart@nginx.com 672678Svbart@nginx.com if (environment != NULL) { 673678Svbart@nginx.com next = 0; 674678Svbart@nginx.com 675678Svbart@nginx.com for ( ;; ) { 676678Svbart@nginx.com value_obj = nxt_conf_next_object_member(environment, &name, &next); 677678Svbart@nginx.com if (value_obj == NULL) { 678678Svbart@nginx.com break; 679678Svbart@nginx.com } 680678Svbart@nginx.com 681678Svbart@nginx.com nxt_conf_get_string(value_obj, &value); 682678Svbart@nginx.com 683678Svbart@nginx.com env = nxt_malloc(name.length + value.length + 2); 684678Svbart@nginx.com if (nxt_slow_path(env == NULL)) { 685678Svbart@nginx.com return NXT_ERROR; 686678Svbart@nginx.com } 687678Svbart@nginx.com 688678Svbart@nginx.com p = nxt_cpymem(env, name.start, name.length); 689678Svbart@nginx.com *p++ = '='; 690678Svbart@nginx.com p = nxt_cpymem(p, value.start, value.length); 691678Svbart@nginx.com *p = '\0'; 692678Svbart@nginx.com 693678Svbart@nginx.com if (nxt_slow_path(putenv(env) != 0)) { 694678Svbart@nginx.com return NXT_ERROR; 695678Svbart@nginx.com } 696678Svbart@nginx.com } 697678Svbart@nginx.com } 698678Svbart@nginx.com 699678Svbart@nginx.com return NXT_OK; 700678Svbart@nginx.com } 701678Svbart@nginx.com 702678Svbart@nginx.com 7031488St.nateldemoura@f5.com static nxt_int_t 704*1489St.nateldemoura@f5.com nxt_app_set_isolation(nxt_task_t *task, nxt_conf_value_t *isolation, 7051488St.nateldemoura@f5.com nxt_process_t *process) 7061488St.nateldemoura@f5.com { 7071488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 708*1489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_namespaces(task, isolation, process) 709*1489St.nateldemoura@f5.com != NXT_OK)) 710*1489St.nateldemoura@f5.com { 711*1489St.nateldemoura@f5.com return NXT_ERROR; 712*1489St.nateldemoura@f5.com } 713*1489St.nateldemoura@f5.com #endif 714*1489St.nateldemoura@f5.com 715*1489St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 716*1489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_creds(task, isolation, process) 717*1489St.nateldemoura@f5.com != NXT_OK)) 718*1489St.nateldemoura@f5.com { 719*1489St.nateldemoura@f5.com return NXT_ERROR; 720*1489St.nateldemoura@f5.com } 721*1489St.nateldemoura@f5.com #endif 722*1489St.nateldemoura@f5.com 723*1489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 724*1489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_rootfs(task, isolation, process) 725*1489St.nateldemoura@f5.com != NXT_OK)) 726*1489St.nateldemoura@f5.com { 727*1489St.nateldemoura@f5.com return NXT_ERROR; 728*1489St.nateldemoura@f5.com } 729*1489St.nateldemoura@f5.com #endif 730*1489St.nateldemoura@f5.com 731*1489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 732*1489St.nateldemoura@f5.com if (nxt_slow_path(nxt_app_set_isolation_new_privs(task, isolation, process) 733*1489St.nateldemoura@f5.com != NXT_OK)) 734*1489St.nateldemoura@f5.com { 735*1489St.nateldemoura@f5.com return NXT_ERROR; 736*1489St.nateldemoura@f5.com } 737*1489St.nateldemoura@f5.com #endif 738*1489St.nateldemoura@f5.com 739*1489St.nateldemoura@f5.com return NXT_OK; 740*1489St.nateldemoura@f5.com } 741*1489St.nateldemoura@f5.com 742*1489St.nateldemoura@f5.com 743*1489St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 744*1489St.nateldemoura@f5.com 745*1489St.nateldemoura@f5.com static nxt_int_t 746*1489St.nateldemoura@f5.com nxt_app_set_isolation_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation, 747*1489St.nateldemoura@f5.com nxt_process_t *process) 748*1489St.nateldemoura@f5.com { 7491488St.nateldemoura@f5.com nxt_int_t ret; 7501488St.nateldemoura@f5.com nxt_conf_value_t *obj; 7511488St.nateldemoura@f5.com 7521488St.nateldemoura@f5.com static nxt_str_t nsname = nxt_string("namespaces"); 7531488St.nateldemoura@f5.com 7541488St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &nsname, NULL); 7551488St.nateldemoura@f5.com if (obj != NULL) { 7561488St.nateldemoura@f5.com ret = nxt_app_clone_flags(task, obj, &process->isolation.clone); 7571488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7581488St.nateldemoura@f5.com return NXT_ERROR; 7591488St.nateldemoura@f5.com } 7601488St.nateldemoura@f5.com } 7611488St.nateldemoura@f5.com 7621488St.nateldemoura@f5.com return NXT_OK; 7631488St.nateldemoura@f5.com } 7641488St.nateldemoura@f5.com 765*1489St.nateldemoura@f5.com #endif 766*1489St.nateldemoura@f5.com 767*1489St.nateldemoura@f5.com 768*1489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 769*1489St.nateldemoura@f5.com 770*1489St.nateldemoura@f5.com static nxt_int_t 771*1489St.nateldemoura@f5.com nxt_app_set_isolation_rootfs(nxt_task_t *task, nxt_conf_value_t *isolation, 772*1489St.nateldemoura@f5.com nxt_process_t *process) 773*1489St.nateldemoura@f5.com { 774*1489St.nateldemoura@f5.com nxt_str_t str; 775*1489St.nateldemoura@f5.com nxt_conf_value_t *obj; 776*1489St.nateldemoura@f5.com 777*1489St.nateldemoura@f5.com static nxt_str_t rootfs_name = nxt_string("rootfs"); 778*1489St.nateldemoura@f5.com 779*1489St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &rootfs_name, NULL); 780*1489St.nateldemoura@f5.com if (obj != NULL) { 781*1489St.nateldemoura@f5.com nxt_conf_get_string(obj, &str); 782*1489St.nateldemoura@f5.com 783*1489St.nateldemoura@f5.com if (nxt_slow_path(str.length <= 1 || str.start[0] != '/')) { 784*1489St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "rootfs requires an absolute path other " 785*1489St.nateldemoura@f5.com "than \"/\" but given \"%V\"", &str); 786*1489St.nateldemoura@f5.com 787*1489St.nateldemoura@f5.com return NXT_ERROR; 788*1489St.nateldemoura@f5.com } 789*1489St.nateldemoura@f5.com 790*1489St.nateldemoura@f5.com if (str.start[str.length - 1] == '/') { 791*1489St.nateldemoura@f5.com str.length--; 792*1489St.nateldemoura@f5.com } 793*1489St.nateldemoura@f5.com 794*1489St.nateldemoura@f5.com process->isolation.rootfs = nxt_mp_alloc(process->mem_pool, 795*1489St.nateldemoura@f5.com str.length + 1); 796*1489St.nateldemoura@f5.com 797*1489St.nateldemoura@f5.com if (nxt_slow_path(process->isolation.rootfs == NULL)) { 798*1489St.nateldemoura@f5.com return NXT_ERROR; 799*1489St.nateldemoura@f5.com } 800*1489St.nateldemoura@f5.com 801*1489St.nateldemoura@f5.com nxt_memcpy(process->isolation.rootfs, str.start, str.length); 802*1489St.nateldemoura@f5.com 803*1489St.nateldemoura@f5.com process->isolation.rootfs[str.length] = '\0'; 804*1489St.nateldemoura@f5.com } 805*1489St.nateldemoura@f5.com 806*1489St.nateldemoura@f5.com return NXT_OK; 807*1489St.nateldemoura@f5.com } 808*1489St.nateldemoura@f5.com 809*1489St.nateldemoura@f5.com #endif 810*1489St.nateldemoura@f5.com 811*1489St.nateldemoura@f5.com 812*1489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 813*1489St.nateldemoura@f5.com 814*1489St.nateldemoura@f5.com static nxt_int_t 815*1489St.nateldemoura@f5.com nxt_app_set_isolation_new_privs(nxt_task_t *task, nxt_conf_value_t *isolation, 816*1489St.nateldemoura@f5.com nxt_process_t *process) 817*1489St.nateldemoura@f5.com { 818*1489St.nateldemoura@f5.com nxt_conf_value_t *obj; 819*1489St.nateldemoura@f5.com 820*1489St.nateldemoura@f5.com static nxt_str_t new_privs_name = nxt_string("new_privs"); 821*1489St.nateldemoura@f5.com 822*1489St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &new_privs_name, NULL); 823*1489St.nateldemoura@f5.com if (obj != NULL) { 824*1489St.nateldemoura@f5.com process->isolation.new_privs = nxt_conf_get_boolean(obj); 825*1489St.nateldemoura@f5.com } 826*1489St.nateldemoura@f5.com 827*1489St.nateldemoura@f5.com return NXT_OK; 828*1489St.nateldemoura@f5.com } 829*1489St.nateldemoura@f5.com 830*1489St.nateldemoura@f5.com #endif 831*1489St.nateldemoura@f5.com 8321488St.nateldemoura@f5.com 8331488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 8341488St.nateldemoura@f5.com 8351488St.nateldemoura@f5.com static nxt_int_t 836*1489St.nateldemoura@f5.com nxt_app_set_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation, 8371488St.nateldemoura@f5.com nxt_process_t *process) 8381488St.nateldemoura@f5.com { 8391488St.nateldemoura@f5.com nxt_int_t ret; 8401488St.nateldemoura@f5.com nxt_clone_t *clone; 8411488St.nateldemoura@f5.com nxt_conf_value_t *array; 8421488St.nateldemoura@f5.com 8431488St.nateldemoura@f5.com static nxt_str_t uidname = nxt_string("uidmap"); 8441488St.nateldemoura@f5.com static nxt_str_t gidname = nxt_string("gidmap"); 8451488St.nateldemoura@f5.com 8461488St.nateldemoura@f5.com clone = &process->isolation.clone; 8471488St.nateldemoura@f5.com 8481488St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &uidname, NULL); 8491488St.nateldemoura@f5.com if (array != NULL) { 8501488St.nateldemoura@f5.com ret = nxt_app_isolation_credential_map(task, process->mem_pool, array, 8511488St.nateldemoura@f5.com &clone->uidmap); 8521488St.nateldemoura@f5.com 8531488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 8541488St.nateldemoura@f5.com return NXT_ERROR; 8551488St.nateldemoura@f5.com } 8561488St.nateldemoura@f5.com } 8571488St.nateldemoura@f5.com 8581488St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &gidname, NULL); 8591488St.nateldemoura@f5.com if (array != NULL) { 8601488St.nateldemoura@f5.com ret = nxt_app_isolation_credential_map(task, process->mem_pool, array, 8611488St.nateldemoura@f5.com &clone->gidmap); 8621488St.nateldemoura@f5.com 8631488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 8641488St.nateldemoura@f5.com return NXT_ERROR; 8651488St.nateldemoura@f5.com } 8661488St.nateldemoura@f5.com } 8671488St.nateldemoura@f5.com 8681488St.nateldemoura@f5.com return NXT_OK; 8691488St.nateldemoura@f5.com } 8701488St.nateldemoura@f5.com 8711488St.nateldemoura@f5.com 8721488St.nateldemoura@f5.com static nxt_int_t 8731488St.nateldemoura@f5.com nxt_app_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mp, 8741488St.nateldemoura@f5.com nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map) 8751488St.nateldemoura@f5.com { 8761488St.nateldemoura@f5.com nxt_int_t ret; 8771488St.nateldemoura@f5.com nxt_uint_t i; 8781488St.nateldemoura@f5.com nxt_conf_value_t *obj; 8791488St.nateldemoura@f5.com 8801488St.nateldemoura@f5.com static nxt_conf_map_t nxt_clone_map_entry_conf[] = { 8811488St.nateldemoura@f5.com { 8821488St.nateldemoura@f5.com nxt_string("container"), 8831488St.nateldemoura@f5.com NXT_CONF_MAP_INT, 8841488St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, container), 8851488St.nateldemoura@f5.com }, 8861488St.nateldemoura@f5.com 8871488St.nateldemoura@f5.com { 8881488St.nateldemoura@f5.com nxt_string("host"), 8891488St.nateldemoura@f5.com NXT_CONF_MAP_INT, 8901488St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, host), 8911488St.nateldemoura@f5.com }, 8921488St.nateldemoura@f5.com 8931488St.nateldemoura@f5.com { 8941488St.nateldemoura@f5.com nxt_string("size"), 8951488St.nateldemoura@f5.com NXT_CONF_MAP_INT, 8961488St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, size), 8971488St.nateldemoura@f5.com }, 8981488St.nateldemoura@f5.com }; 8991488St.nateldemoura@f5.com 9001488St.nateldemoura@f5.com map->size = nxt_conf_array_elements_count(map_array); 9011488St.nateldemoura@f5.com 9021488St.nateldemoura@f5.com if (map->size == 0) { 9031488St.nateldemoura@f5.com return NXT_OK; 9041488St.nateldemoura@f5.com } 9051488St.nateldemoura@f5.com 9061488St.nateldemoura@f5.com map->map = nxt_mp_alloc(mp, map->size * sizeof(nxt_clone_map_entry_t)); 9071488St.nateldemoura@f5.com if (nxt_slow_path(map->map == NULL)) { 9081488St.nateldemoura@f5.com return NXT_ERROR; 9091488St.nateldemoura@f5.com } 9101488St.nateldemoura@f5.com 9111488St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 9121488St.nateldemoura@f5.com obj = nxt_conf_get_array_element(map_array, i); 9131488St.nateldemoura@f5.com 9141488St.nateldemoura@f5.com ret = nxt_conf_map_object(mp, obj, nxt_clone_map_entry_conf, 9151488St.nateldemoura@f5.com nxt_nitems(nxt_clone_map_entry_conf), 9161488St.nateldemoura@f5.com map->map + i); 9171488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 9181488St.nateldemoura@f5.com nxt_alert(task, "clone map entry map error"); 9191488St.nateldemoura@f5.com return NXT_ERROR; 9201488St.nateldemoura@f5.com } 9211488St.nateldemoura@f5.com } 9221488St.nateldemoura@f5.com 9231488St.nateldemoura@f5.com return NXT_OK; 9241488St.nateldemoura@f5.com } 9251488St.nateldemoura@f5.com 9261488St.nateldemoura@f5.com #endif 9271488St.nateldemoura@f5.com 9281488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 9291488St.nateldemoura@f5.com 9301488St.nateldemoura@f5.com static nxt_int_t 9311488St.nateldemoura@f5.com nxt_app_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces, 9321488St.nateldemoura@f5.com nxt_clone_t *clone) 9331488St.nateldemoura@f5.com { 9341488St.nateldemoura@f5.com uint32_t index; 9351488St.nateldemoura@f5.com nxt_str_t name; 9361488St.nateldemoura@f5.com nxt_int_t flag; 9371488St.nateldemoura@f5.com nxt_conf_value_t *value; 9381488St.nateldemoura@f5.com 9391488St.nateldemoura@f5.com index = 0; 9401488St.nateldemoura@f5.com 9411488St.nateldemoura@f5.com for ( ;; ) { 9421488St.nateldemoura@f5.com value = nxt_conf_next_object_member(namespaces, &name, &index); 9431488St.nateldemoura@f5.com 9441488St.nateldemoura@f5.com if (value == NULL) { 9451488St.nateldemoura@f5.com break; 9461488St.nateldemoura@f5.com } 9471488St.nateldemoura@f5.com 9481488St.nateldemoura@f5.com flag = 0; 9491488St.nateldemoura@f5.com 9501488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 9511488St.nateldemoura@f5.com if (nxt_str_eq(&name, "credential", 10)) { 9521488St.nateldemoura@f5.com flag = CLONE_NEWUSER; 9531488St.nateldemoura@f5.com } 9541488St.nateldemoura@f5.com #endif 9551488St.nateldemoura@f5.com 9561488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWPID) 9571488St.nateldemoura@f5.com if (nxt_str_eq(&name, "pid", 3)) { 9581488St.nateldemoura@f5.com flag = CLONE_NEWPID; 9591488St.nateldemoura@f5.com } 9601488St.nateldemoura@f5.com #endif 9611488St.nateldemoura@f5.com 9621488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNET) 9631488St.nateldemoura@f5.com if (nxt_str_eq(&name, "network", 7)) { 9641488St.nateldemoura@f5.com flag = CLONE_NEWNET; 9651488St.nateldemoura@f5.com } 9661488St.nateldemoura@f5.com #endif 9671488St.nateldemoura@f5.com 9681488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUTS) 9691488St.nateldemoura@f5.com if (nxt_str_eq(&name, "uname", 5)) { 9701488St.nateldemoura@f5.com flag = CLONE_NEWUTS; 9711488St.nateldemoura@f5.com } 9721488St.nateldemoura@f5.com #endif 9731488St.nateldemoura@f5.com 9741488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNS) 9751488St.nateldemoura@f5.com if (nxt_str_eq(&name, "mount", 5)) { 9761488St.nateldemoura@f5.com flag = CLONE_NEWNS; 9771488St.nateldemoura@f5.com } 9781488St.nateldemoura@f5.com #endif 9791488St.nateldemoura@f5.com 9801488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWCGROUP) 9811488St.nateldemoura@f5.com if (nxt_str_eq(&name, "cgroup", 6)) { 9821488St.nateldemoura@f5.com flag = CLONE_NEWCGROUP; 9831488St.nateldemoura@f5.com } 9841488St.nateldemoura@f5.com #endif 9851488St.nateldemoura@f5.com 9861488St.nateldemoura@f5.com if (!flag) { 9871488St.nateldemoura@f5.com nxt_alert(task, "unknown namespace flag: \"%V\"", &name); 9881488St.nateldemoura@f5.com return NXT_ERROR; 9891488St.nateldemoura@f5.com } 9901488St.nateldemoura@f5.com 9911488St.nateldemoura@f5.com if (nxt_conf_get_boolean(value)) { 9921488St.nateldemoura@f5.com clone->flags |= flag; 9931488St.nateldemoura@f5.com } 9941488St.nateldemoura@f5.com } 9951488St.nateldemoura@f5.com 9961488St.nateldemoura@f5.com return NXT_OK; 9971488St.nateldemoura@f5.com } 9981488St.nateldemoura@f5.com 9991488St.nateldemoura@f5.com #endif 10001488St.nateldemoura@f5.com 10011488St.nateldemoura@f5.com 1002*1489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 1003*1489St.nateldemoura@f5.com 1004*1489St.nateldemoura@f5.com static nxt_int_t 1005*1489St.nateldemoura@f5.com nxt_app_prepare_lang_mounts(nxt_task_t *task, nxt_process_t *process, 1006*1489St.nateldemoura@f5.com nxt_array_t *lang_mounts) 1007*1489St.nateldemoura@f5.com { 1008*1489St.nateldemoura@f5.com u_char *p; 1009*1489St.nateldemoura@f5.com size_t i, n, rootfs_len, len; 1010*1489St.nateldemoura@f5.com nxt_mp_t *mp; 1011*1489St.nateldemoura@f5.com nxt_array_t *mounts; 1012*1489St.nateldemoura@f5.com const u_char *rootfs; 1013*1489St.nateldemoura@f5.com nxt_fs_mount_t *mnt, *lang_mnt; 1014*1489St.nateldemoura@f5.com 1015*1489St.nateldemoura@f5.com rootfs = process->isolation.rootfs; 1016*1489St.nateldemoura@f5.com rootfs_len = nxt_strlen(rootfs); 1017*1489St.nateldemoura@f5.com mp = process->mem_pool; 1018*1489St.nateldemoura@f5.com 1019*1489St.nateldemoura@f5.com /* copy to init mem pool */ 1020*1489St.nateldemoura@f5.com mounts = nxt_array_copy(mp, NULL, lang_mounts); 1021*1489St.nateldemoura@f5.com if (mounts == NULL) { 1022*1489St.nateldemoura@f5.com return NXT_ERROR; 1023*1489St.nateldemoura@f5.com } 1024*1489St.nateldemoura@f5.com 1025*1489St.nateldemoura@f5.com n = mounts->nelts; 1026*1489St.nateldemoura@f5.com mnt = mounts->elts; 1027*1489St.nateldemoura@f5.com lang_mnt = lang_mounts->elts; 1028*1489St.nateldemoura@f5.com 1029*1489St.nateldemoura@f5.com for (i = 0; i < n; i++) { 1030*1489St.nateldemoura@f5.com len = nxt_strlen(lang_mnt[i].dst); 1031*1489St.nateldemoura@f5.com 1032*1489St.nateldemoura@f5.com mnt[i].dst = nxt_mp_alloc(mp, rootfs_len + len + 1); 1033*1489St.nateldemoura@f5.com if (mnt[i].dst == NULL) { 1034*1489St.nateldemoura@f5.com return NXT_ERROR; 1035*1489St.nateldemoura@f5.com } 1036*1489St.nateldemoura@f5.com 1037*1489St.nateldemoura@f5.com p = nxt_cpymem(mnt[i].dst, rootfs, rootfs_len); 1038*1489St.nateldemoura@f5.com p = nxt_cpymem(p, lang_mnt[i].dst, len); 1039*1489St.nateldemoura@f5.com *p = '\0'; 1040*1489St.nateldemoura@f5.com } 1041*1489St.nateldemoura@f5.com 1042*1489St.nateldemoura@f5.com process->isolation.mounts = mounts; 1043*1489St.nateldemoura@f5.com 1044*1489St.nateldemoura@f5.com return NXT_OK; 1045*1489St.nateldemoura@f5.com } 1046*1489St.nateldemoura@f5.com 1047*1489St.nateldemoura@f5.com 1048*1489St.nateldemoura@f5.com 1049*1489St.nateldemoura@f5.com static nxt_int_t 1050*1489St.nateldemoura@f5.com nxt_app_prepare_rootfs(nxt_task_t *task, nxt_process_t *process) 1051*1489St.nateldemoura@f5.com { 1052*1489St.nateldemoura@f5.com size_t i, n; 1053*1489St.nateldemoura@f5.com nxt_int_t ret, hasproc; 1054*1489St.nateldemoura@f5.com struct stat st; 1055*1489St.nateldemoura@f5.com nxt_array_t *mounts; 1056*1489St.nateldemoura@f5.com const u_char *dst; 1057*1489St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 1058*1489St.nateldemoura@f5.com 1059*1489St.nateldemoura@f5.com hasproc = 0; 1060*1489St.nateldemoura@f5.com 1061*1489St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWPID) && (NXT_HAVE_CLONE_NEWNS) 1062*1489St.nateldemoura@f5.com nxt_fs_mount_t mount; 1063*1489St.nateldemoura@f5.com 1064*1489St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID) 1065*1489St.nateldemoura@f5.com && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) 1066*1489St.nateldemoura@f5.com { 1067*1489St.nateldemoura@f5.com /* 1068*1489St.nateldemoura@f5.com * This mount point will automatically be gone when the namespace is 1069*1489St.nateldemoura@f5.com * destroyed. 1070*1489St.nateldemoura@f5.com */ 1071*1489St.nateldemoura@f5.com 1072*1489St.nateldemoura@f5.com mount.fstype = (u_char *) "proc"; 1073*1489St.nateldemoura@f5.com mount.src = (u_char *) "proc"; 1074*1489St.nateldemoura@f5.com mount.dst = (u_char *) "/proc"; 1075*1489St.nateldemoura@f5.com mount.data = (u_char *) ""; 1076*1489St.nateldemoura@f5.com mount.flags = 0; 1077*1489St.nateldemoura@f5.com 1078*1489St.nateldemoura@f5.com ret = nxt_fs_mkdir_all(mount.dst, S_IRWXU | S_IRWXG | S_IRWXO); 1079*1489St.nateldemoura@f5.com if (nxt_fast_path(ret == NXT_OK)) { 1080*1489St.nateldemoura@f5.com ret = nxt_fs_mount(task, &mount); 1081*1489St.nateldemoura@f5.com if (nxt_fast_path(ret == NXT_OK)) { 1082*1489St.nateldemoura@f5.com hasproc = 1; 1083*1489St.nateldemoura@f5.com } 1084*1489St.nateldemoura@f5.com 1085*1489St.nateldemoura@f5.com } else { 1086*1489St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN, "mkdir(%s) %E", mount.dst, nxt_errno); 1087*1489St.nateldemoura@f5.com } 1088*1489St.nateldemoura@f5.com } 1089*1489St.nateldemoura@f5.com #endif 1090*1489St.nateldemoura@f5.com 1091*1489St.nateldemoura@f5.com mounts = process->isolation.mounts; 1092*1489St.nateldemoura@f5.com 1093*1489St.nateldemoura@f5.com n = mounts->nelts; 1094*1489St.nateldemoura@f5.com mnt = mounts->elts; 1095*1489St.nateldemoura@f5.com 1096*1489St.nateldemoura@f5.com for (i = 0; i < n; i++) { 1097*1489St.nateldemoura@f5.com dst = mnt[i].dst; 1098*1489St.nateldemoura@f5.com 1099*1489St.nateldemoura@f5.com if (nxt_slow_path(nxt_memcmp(mnt[i].fstype, "bind", 4) == 0 1100*1489St.nateldemoura@f5.com && stat((const char *) mnt[i].src, &st) != 0)) 1101*1489St.nateldemoura@f5.com { 1102*1489St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src); 1103*1489St.nateldemoura@f5.com continue; 1104*1489St.nateldemoura@f5.com } 1105*1489St.nateldemoura@f5.com 1106*1489St.nateldemoura@f5.com if (hasproc && nxt_memcmp(mnt[i].fstype, "proc", 4) == 0 1107*1489St.nateldemoura@f5.com && nxt_memcmp(mnt[i].dst, "/proc", 5) == 0) 1108*1489St.nateldemoura@f5.com { 1109*1489St.nateldemoura@f5.com continue; 1110*1489St.nateldemoura@f5.com } 1111*1489St.nateldemoura@f5.com 1112*1489St.nateldemoura@f5.com ret = nxt_fs_mkdir_all(dst, S_IRWXU | S_IRWXG | S_IRWXO); 1113*1489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 1114*1489St.nateldemoura@f5.com nxt_alert(task, "mkdir(%s) %E", dst, nxt_errno); 1115*1489St.nateldemoura@f5.com goto undo; 1116*1489St.nateldemoura@f5.com } 1117*1489St.nateldemoura@f5.com 1118*1489St.nateldemoura@f5.com ret = nxt_fs_mount(task, &mnt[i]); 1119*1489St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 1120*1489St.nateldemoura@f5.com goto undo; 1121*1489St.nateldemoura@f5.com } 1122*1489St.nateldemoura@f5.com } 1123*1489St.nateldemoura@f5.com 1124*1489St.nateldemoura@f5.com return NXT_OK; 1125*1489St.nateldemoura@f5.com 1126*1489St.nateldemoura@f5.com undo: 1127*1489St.nateldemoura@f5.com 1128*1489St.nateldemoura@f5.com n = i + 1; 1129*1489St.nateldemoura@f5.com 1130*1489St.nateldemoura@f5.com for (i = 0; i < n; i++) { 1131*1489St.nateldemoura@f5.com nxt_fs_unmount(mnt[i].dst); 1132*1489St.nateldemoura@f5.com } 1133*1489St.nateldemoura@f5.com 1134*1489St.nateldemoura@f5.com return NXT_ERROR; 1135*1489St.nateldemoura@f5.com } 1136*1489St.nateldemoura@f5.com 1137*1489St.nateldemoura@f5.com #endif 1138*1489St.nateldemoura@f5.com 1139*1489St.nateldemoura@f5.com 1140*1489St.nateldemoura@f5.com static u_char * 1141*1489St.nateldemoura@f5.com nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src) 1142*1489St.nateldemoura@f5.com { 1143*1489St.nateldemoura@f5.com u_char *p; 1144*1489St.nateldemoura@f5.com size_t len; 1145*1489St.nateldemoura@f5.com 1146*1489St.nateldemoura@f5.com len = nxt_strlen(src); 1147*1489St.nateldemoura@f5.com 1148*1489St.nateldemoura@f5.com if (dst == NULL) { 1149*1489St.nateldemoura@f5.com dst = nxt_mp_alloc(mp, len + 1); 1150*1489St.nateldemoura@f5.com if (nxt_slow_path(dst == NULL)) { 1151*1489St.nateldemoura@f5.com return NULL; 1152*1489St.nateldemoura@f5.com } 1153*1489St.nateldemoura@f5.com } 1154*1489St.nateldemoura@f5.com 1155*1489St.nateldemoura@f5.com p = nxt_cpymem(dst, src, len); 1156*1489St.nateldemoura@f5.com *p = '\0'; 1157*1489St.nateldemoura@f5.com 1158*1489St.nateldemoura@f5.com return dst; 1159*1489St.nateldemoura@f5.com } 1160*1489St.nateldemoura@f5.com 11611488St.nateldemoura@f5.com 1162216Sigor@sysoev.ru nxt_app_lang_module_t * 1163216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name) 1164216Sigor@sysoev.ru { 1165216Sigor@sysoev.ru u_char *p, *end, *version; 1166356Svbart@nginx.com size_t version_length; 1167216Sigor@sysoev.ru nxt_uint_t i, n; 1168356Svbart@nginx.com nxt_app_type_t type; 1169216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 1170216Sigor@sysoev.ru 1171216Sigor@sysoev.ru end = name->start + name->length; 1172216Sigor@sysoev.ru version = end; 1173216Sigor@sysoev.ru 1174216Sigor@sysoev.ru for (p = name->start; p < end; p++) { 1175216Sigor@sysoev.ru if (*p == ' ') { 1176216Sigor@sysoev.ru version = p + 1; 1177216Sigor@sysoev.ru break; 1178216Sigor@sysoev.ru } 1179216Sigor@sysoev.ru 1180216Sigor@sysoev.ru if (*p >= '0' && *p <= '9') { 1181216Sigor@sysoev.ru version = p; 1182216Sigor@sysoev.ru break; 1183216Sigor@sysoev.ru } 1184216Sigor@sysoev.ru } 1185216Sigor@sysoev.ru 1186356Svbart@nginx.com type = nxt_app_parse_type(name->start, p - name->start); 1187356Svbart@nginx.com 1188356Svbart@nginx.com if (type == NXT_APP_UNKNOWN) { 1189356Svbart@nginx.com return NULL; 1190356Svbart@nginx.com } 1191356Svbart@nginx.com 1192216Sigor@sysoev.ru version_length = end - version; 1193216Sigor@sysoev.ru 1194216Sigor@sysoev.ru lang = rt->languages->elts; 1195216Sigor@sysoev.ru n = rt->languages->nelts; 1196216Sigor@sysoev.ru 1197216Sigor@sysoev.ru for (i = 0; i < n; i++) { 1198354Svbart@nginx.com 1199354Svbart@nginx.com /* 1200354Svbart@nginx.com * Versions are sorted in descending order 1201354Svbart@nginx.com * so first match chooses the highest version. 1202354Svbart@nginx.com */ 1203354Svbart@nginx.com 1204356Svbart@nginx.com if (lang[i].type == type 1205354Svbart@nginx.com && nxt_strvers_match(lang[i].version, version, version_length)) 1206216Sigor@sysoev.ru { 1207216Sigor@sysoev.ru return &lang[i]; 1208216Sigor@sysoev.ru } 1209216Sigor@sysoev.ru } 1210216Sigor@sysoev.ru 1211216Sigor@sysoev.ru return NULL; 1212216Sigor@sysoev.ru } 1213216Sigor@sysoev.ru 1214216Sigor@sysoev.ru 1215510Salexander.borisov@nginx.com nxt_app_type_t 1216356Svbart@nginx.com nxt_app_parse_type(u_char *p, size_t length) 1217141Smax.romanov@nginx.com { 1218356Svbart@nginx.com nxt_str_t str; 1219356Svbart@nginx.com 1220356Svbart@nginx.com str.length = length; 1221356Svbart@nginx.com str.start = p; 1222356Svbart@nginx.com 1223804Svbart@nginx.com if (nxt_str_eq(&str, "external", 8) || nxt_str_eq(&str, "go", 2)) { 1224804Svbart@nginx.com return NXT_APP_EXTERNAL; 1225804Svbart@nginx.com 1226804Svbart@nginx.com } else if (nxt_str_eq(&str, "python", 6)) { 1227141Smax.romanov@nginx.com return NXT_APP_PYTHON; 1228141Smax.romanov@nginx.com 1229356Svbart@nginx.com } else if (nxt_str_eq(&str, "php", 3)) { 1230141Smax.romanov@nginx.com return NXT_APP_PHP; 1231141Smax.romanov@nginx.com 1232510Salexander.borisov@nginx.com } else if (nxt_str_eq(&str, "perl", 4)) { 1233510Salexander.borisov@nginx.com return NXT_APP_PERL; 1234584Salexander.borisov@nginx.com 1235584Salexander.borisov@nginx.com } else if (nxt_str_eq(&str, "ruby", 4)) { 1236584Salexander.borisov@nginx.com return NXT_APP_RUBY; 1237977Smax.romanov@gmail.com 1238977Smax.romanov@gmail.com } else if (nxt_str_eq(&str, "java", 4)) { 1239977Smax.romanov@gmail.com return NXT_APP_JAVA; 1240141Smax.romanov@nginx.com } 1241141Smax.romanov@nginx.com 1242141Smax.romanov@nginx.com return NXT_APP_UNKNOWN; 1243141Smax.romanov@nginx.com } 1244743Smax.romanov@nginx.com 1245743Smax.romanov@nginx.com 1246743Smax.romanov@nginx.com nxt_int_t 1247743Smax.romanov@nginx.com nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init) 1248743Smax.romanov@nginx.com { 1249743Smax.romanov@nginx.com nxt_port_t *my_port, *main_port; 1250743Smax.romanov@nginx.com nxt_runtime_t *rt; 1251743Smax.romanov@nginx.com 1252743Smax.romanov@nginx.com nxt_memzero(init, sizeof(nxt_unit_init_t)); 1253743Smax.romanov@nginx.com 1254743Smax.romanov@nginx.com rt = task->thread->runtime; 1255743Smax.romanov@nginx.com 1256743Smax.romanov@nginx.com main_port = rt->port_by_type[NXT_PROCESS_MAIN]; 1257743Smax.romanov@nginx.com if (nxt_slow_path(main_port == NULL)) { 1258743Smax.romanov@nginx.com return NXT_ERROR; 1259743Smax.romanov@nginx.com } 1260743Smax.romanov@nginx.com 1261743Smax.romanov@nginx.com my_port = nxt_runtime_port_find(rt, nxt_pid, 0); 1262743Smax.romanov@nginx.com if (nxt_slow_path(my_port == NULL)) { 1263743Smax.romanov@nginx.com return NXT_ERROR; 1264743Smax.romanov@nginx.com } 1265743Smax.romanov@nginx.com 1266743Smax.romanov@nginx.com init->ready_port.id.pid = main_port->pid; 1267743Smax.romanov@nginx.com init->ready_port.id.id = main_port->id; 1268743Smax.romanov@nginx.com init->ready_port.out_fd = main_port->pair[1]; 1269743Smax.romanov@nginx.com 1270743Smax.romanov@nginx.com nxt_fd_blocking(task, main_port->pair[1]); 1271743Smax.romanov@nginx.com 12721488St.nateldemoura@f5.com init->ready_stream = my_port->process->stream; 1273743Smax.romanov@nginx.com 1274743Smax.romanov@nginx.com init->read_port.id.pid = my_port->pid; 1275743Smax.romanov@nginx.com init->read_port.id.id = my_port->id; 1276743Smax.romanov@nginx.com init->read_port.in_fd = my_port->pair[0]; 1277743Smax.romanov@nginx.com 1278743Smax.romanov@nginx.com nxt_fd_blocking(task, my_port->pair[0]); 1279743Smax.romanov@nginx.com 1280743Smax.romanov@nginx.com init->log_fd = 2; 1281743Smax.romanov@nginx.com 1282743Smax.romanov@nginx.com return NXT_OK; 1283743Smax.romanov@nginx.com } 1284