run_dlopen(void *priv) { void *dlh; struct VCL_conf const *cnf; struct vcc_priv *vp; VJ_subproc(JAIL_SUBPROC_VCLLOAD); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); /* Try to load the object into this sub-process */ if ((dlh = dlopen(vp->libfile, RTLD_NOW | RTLD_LOCAL)) == NULL) { fprintf(stderr, "Compiled VCL program failed to load:\n %s\n", dlerror()); exit(1); } cnf = dlsym(dlh, "VCL_conf"); if (cnf == NULL) { fprintf(stderr, "Compiled VCL program, metadata not found\n"); exit(1); } if (cnf->magic != VCL_CONF_MAGIC) { fprintf(stderr, "Compiled VCL program, mangled metadata\n"); exit(1); } if (dlclose(dlh)) { fprintf(stderr, "Compiled VCL program failed to unload:\n %s\n", dlerror()); exit(1); } exit(0); }
run_dlopen(void *priv) { struct vcc_priv *vp; VJ_subproc(JAIL_SUBPROC_VCLLOAD); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); if (VCL_TestLoad(vp->libfile)) exit(1); exit(0); }
run_vcc(void *priv) { struct vsb *csrc; struct vsb *sb = NULL; struct vcc_priv *vp; int fd, i, l; struct vcc *vcc; struct stevedore *stv; VJ_subproc(JAIL_SUBPROC_VCC); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); AZ(chdir(vp->dir)); vcc = VCC_New(); AN(vcc); VCC_Builtin_VCL(vcc, builtin_vcl); VCC_VCL_path(vcc, mgt_vcl_path); VCC_VMOD_path(vcc, mgt_vmod_path); VCC_Err_Unref(vcc, mgt_vcc_err_unref); VCC_Allow_InlineC(vcc, mgt_vcc_allow_inline_c); VCC_Unsafe_Path(vcc, mgt_vcc_unsafe_path); STV_Foreach(stv) VCC_Predef(vcc, "VCL_STEVEDORE", stv->ident); mgt_vcl_export_labels(vcc); csrc = VCC_Compile(vcc, &sb, vp->vclsrc, vp->vclsrcfile); AZ(VSB_finish(sb)); if (VSB_len(sb)) printf("%s", VSB_data(sb)); VSB_destroy(&sb); if (csrc == NULL) exit(2); fd = open(VGC_SRC, O_WRONLY|O_TRUNC|O_CREAT, 0600); if (fd < 0) { fprintf(stderr, "VCC cannot open %s", vp->csrcfile); exit(2); } l = VSB_len(csrc); i = write(fd, VSB_data(csrc), l); if (i != l) { fprintf(stderr, "VCC cannot write %s", vp->csrcfile); exit(2); } closefd(&fd); VSB_destroy(&csrc); exit(0); }
run_cc(void *priv) { struct vcc_priv *vp; struct vsb *sb; int pct; char *p; VJ_subproc(JAIL_SUBPROC_CC); CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); AZ(chdir(vp->dir)); sb = VSB_new_auto(); AN(sb); for (p = mgt_cc_cmd, pct = 0; *p; ++p) { if (pct) { switch (*p) { case 's': VSB_cat(sb, VGC_SRC); break; case 'o': VSB_cat(sb, VGC_LIB); break; case '%': VSB_putc(sb, '%'); break; default: VSB_putc(sb, '%'); VSB_putc(sb, *p); break; } pct = 0; } else if (*p == '%') { pct = 1; } else { VSB_putc(sb, *p); } } if (pct) VSB_putc(sb, '%'); AZ(VSB_finish(sb)); (void)umask(027); (void)execl("/bin/sh", "/bin/sh", "-c", VSB_data(sb), (char*)0); VSB_destroy(&sb); // For flexelint }
static void run_vcc(void *priv) { char *csrc; struct vsb *sb; struct vcc_priv *vp; int fd, i, l; CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC); VJ_subproc(JAIL_SUBPROC_VCC); sb = VSB_new_auto(); XXXAN(sb); VCC_VCL_dir(vcc, mgt_vcl_dir); VCC_VMOD_dir(vcc, mgt_vmod_dir); VCC_Err_Unref(vcc, mgt_vcc_err_unref); VCC_Allow_InlineC(vcc, mgt_vcc_allow_inline_c); VCC_Unsafe_Path(vcc, mgt_vcc_unsafe_path); csrc = VCC_Compile(vcc, sb, vp->src); AZ(VSB_finish(sb)); if (VSB_len(sb)) printf("%s", VSB_data(sb)); VSB_delete(sb); if (csrc == NULL) exit(2); fd = open(vp->srcfile, O_WRONLY|O_TRUNC|O_CREAT, 0600); if (fd < 0) { fprintf(stderr, "Cannot open %s", vp->srcfile); exit(2); } l = strlen(csrc); i = write(fd, csrc, l); if (i != l) { fprintf(stderr, "Cannot write %s", vp->srcfile); exit(2); } AZ(close(fd)); free(csrc); exit(0); }
static void mgt_launch_child(struct cli *cli) { pid_t pid; unsigned u; char *p; struct vev *e; int i, j, k, cp[2]; struct sigaction sa; if (child_state != CH_STOPPED && child_state != CH_DIED) return; if (!MAC_sockets_ready(cli)) { child_state = CH_STOPPED; if (cli != NULL) { VCLI_SetResult(cli, CLIS_CANT); return; } MGT_complain(C_ERR, "Child start failed: could not open sockets"); return; } child_state = CH_STARTING; /* Open pipe for mgr->child CLI */ AZ(pipe(cp)); heritage.cli_in = cp[0]; mgt_child_inherit(heritage.cli_in, "cli_in"); child_cli_out = cp[1]; /* Open pipe for child->mgr CLI */ AZ(pipe(cp)); heritage.cli_out = cp[1]; mgt_child_inherit(heritage.cli_out, "cli_out"); child_cli_in = cp[0]; /* * Open pipe for child stdout/err * NB: not inherited, because we dup2() it to stdout/stderr in child */ AZ(pipe(cp)); heritage.std_fd = cp[1]; child_output = cp[0]; AN(heritage.vsm); mgt_SHM_Size_Adjust(); AN(heritage.vsm); AN(heritage.param); if ((pid = fork()) < 0) { /* XXX */ perror("Could not fork child"); exit(1); } if (pid == 0) { /* Redirect stdin/out/err */ AZ(close(STDIN_FILENO)); assert(open("/dev/null", O_RDONLY) == STDIN_FILENO); assert(dup2(heritage.std_fd, STDOUT_FILENO) == STDOUT_FILENO); assert(dup2(heritage.std_fd, STDERR_FILENO) == STDERR_FILENO); /* * Close all FDs the child shouldn't know about * * We cannot just close these filedescriptors, some random * library routine might miss it later on and wantonly close * a FD we use at that point in time. (See bug #1841). * We close the FD and replace it with /dev/null instead, * That prevents security leakage, and gives the library * code a valid FD to close when it discovers the changed * circumstances. */ closelog(); for (i = STDERR_FILENO + 1; i < CLOSE_FD_UP_TO; i++) { if (vbit_test(fd_map, i)) continue; if (close(i) == 0) { k = open("/dev/null", O_RDONLY); assert(k >= 0); j = dup2(k, i); assert(j == i); AZ(close(k)); } } #ifdef HAVE_SETPROCTITLE setproctitle("Varnish-Chld %s", heritage.name); #endif if (mgt_param.sigsegv_handler) { memset(&sa, 0, sizeof sa); sa.sa_sigaction = child_sigsegv_handler; sa.sa_flags = SA_SIGINFO; (void)sigaction(SIGSEGV, &sa, NULL); (void)sigaction(SIGBUS, &sa, NULL); (void)sigaction(SIGABRT, &sa, NULL); } (void)signal(SIGINT, SIG_DFL); (void)signal(SIGTERM, SIG_DFL); VJ_subproc(JAIL_SUBPROC_WORKER); child_main(); exit(0); } assert(pid > 1); MGT_complain(C_DEBUG, "Child (%jd) Started", (intmax_t)pid); VSC_C_mgt->child_start = ++static_VSC_C_mgt.child_start; /* Close stuff the child got */ closex(&heritage.std_fd); mgt_child_inherit(heritage.cli_in, NULL); closex(&heritage.cli_in); mgt_child_inherit(heritage.cli_out, NULL); closex(&heritage.cli_out); child_std_vlu = VLU_New(NULL, child_line, 0); AN(child_std_vlu); AZ(ev_listen); e = vev_new(); XXXAN(e); e->fd = child_output; e->fd_flags = EV_RD; e->name = "Child listener"; e->callback = child_listener; AZ(vev_add(mgt_evb, e)); ev_listen = e; AZ(ev_poker); if (mgt_param.ping_interval > 0) { e = vev_new(); XXXAN(e); e->timeout = mgt_param.ping_interval; e->callback = child_poker; e->name = "child poker"; AZ(vev_add(mgt_evb, e)); ev_poker = e; } mgt_cli_start_child(child_cli_in, child_cli_out); child_pid = pid; if (mgt_push_vcls_and_start(cli, &u, &p)) { VCLI_SetResult(cli, u); MGT_complain(C_ERR, "Child (%jd) Pushing vcls failed:\n%s", (intmax_t)child_pid, p); free(p); child_state = CH_RUNNING; mgt_stop_child(); } else child_state = CH_RUNNING; }