void VJ_Init(const char *j_arg) { char **av; int i; if (j_arg != NULL) { av = VAV_Parse(j_arg, NULL, ARGV_COMMA); AN(av); if (av[0] != NULL) ARGV_ERR("-j argument: %s\n", av[0]); if (av[1] == NULL) ARGV_ERR("-j argument is emtpy\n"); vjt = pick(vj_choice, av[1], "jail"); CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC); (void)vjt->init(av + 2); VAV_Free(av); } else { /* * Go through list of jail technologies until one * succeeds, falling back to "none". */ for (i = 0; vj_choice[i].name != NULL; i++) { vjt = vj_choice[i].ptr; CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC); if (!vjt->init(NULL)) break; } } VSB_printf(vident, ",-j%s", vjt->name); }
void VJ_make_workdir(const char *dname) { int fd; AN(dname); CHECK_OBJ_NOTNULL(vjt, JAIL_TECH_MAGIC); if (vjt->make_workdir != NULL) { vjt->make_workdir(dname); return; } if (mkdir(dname, 0755) < 0 && errno != EEXIST) ARGV_ERR("Cannot create working directory '%s': %s\n", dname, strerror(errno)); if (chdir(dname) < 0) ARGV_ERR("Cannot change to working directory '%s': %s\n", dname, strerror(errno)); fd = open("_.testfile", O_RDWR|O_CREAT|O_EXCL, 0600); if (fd < 0) ARGV_ERR("Error: Cannot create test-file in %s (%s)\n" "Check permissions (or delete old directory)\n", dname, strerror(errno)); AZ(close(fd)); AZ(unlink("_.testfile")); }
static void sma_init(struct stevedore *parent, int ac, char * const *av) { const char *e; uintmax_t u; struct sma_sc *sc; ASSERT_MGT(); ALLOC_OBJ(sc, SMA_SC_MAGIC); AN(sc); sc->sma_max = SIZE_MAX; assert(sc->sma_max == SIZE_MAX); parent->priv = sc; AZ(av[ac]); if (ac > 1) ARGV_ERR("(-smalloc) too many arguments\n"); if (ac == 0 || *av[0] == '\0') return; e = str2bytes(av[0], &u, 0); if (e != NULL) ARGV_ERR("(-smalloc) size \"%s\": %s\n", av[0], e); if ((u != (uintmax_t)(size_t)u)) ARGV_ERR("(-smalloc) size \"%s\": too big\n", av[0]); if (u < 1024*1024) ARGV_ERR("(-smalloc) size \"%s\": too small, " "did you forget to specify M or G?\n", av[0]); sc->sma_max = u; }
void mgt_sandbox_init(void) { struct passwd *pwd; struct group *grp; struct vsb *sb; unsigned subs; /* Pick a sandbox */ #ifdef HAVE_SETPPRIV mgt_sandbox = mgt_sandbox_solaris; #else mgt_sandbox = mgt_sandbox_unix; #endif /* Test it */ sb = VSB_new_auto(); subs = VSUB_run(sb, run_sandbox_test, NULL, "SANDBOX-test", 10); VSB_delete(sb); if (subs) { MGT_complain(C_SECURITY, "Platform-specific sandbox failed - sandboxing disabled"); MGT_complain(C_SECURITY, "Varnish runs with elevated privileges"); mgt_sandbox = mgt_sandbox_null; } MCF_AddParams(mgt_parspec_sandbox); /* * If we have nobody/nogroup, use them as defaults for sandboxes, * else fall back to whoever we run as. */ if (getpwnam("nobody") != NULL) { MCF_SetDefault("user", "nobody"); } else { pwd = getpwuid(getuid()); if (pwd == NULL) ARGV_ERR("Neither user 'nobody' or my uid (%jd)" " found in password database.\n", (intmax_t)getuid()); MCF_SetDefault("user", pwd->pw_name); } endpwent(); if (getgrnam("nogroup") != NULL) { MCF_SetDefault("group", "nogroup"); } else { grp = getgrgid(getgid()); if (grp == NULL) ARGV_ERR("Neither group 'nogroup' or my gid (%jd)" " found in password database.\n", (intmax_t)getgid()); MCF_SetDefault("group", grp->gr_name); } endgrent(); }
void STV_Config(const char *spec) { char **av, buf[8]; const char *name; struct stevedore *stv; const struct stevedore *stv2; int ac; static unsigned seq = 0; av = MGT_NamedArg(spec, &name, "-s"); AN(av); if (av[1] == NULL) ARGV_ERR("-s argument lacks strategy {malloc, file, ...}\n"); for (ac = 0; av[ac + 2] != NULL; ac++) continue; stv2 = MGT_Pick(STV_choice, av[1], "storage"); AN(stv2); /* Append strategy to ident string */ VSB_printf(vident, ",-s%s", av[1]); av += 2; CHECK_OBJ_NOTNULL(stv2, STEVEDORE_MAGIC); ALLOC_OBJ(stv, STEVEDORE_MAGIC); AN(stv); *stv = *stv2; AN(stv->name); if (name == NULL) { bprintf(buf, "s%u", seq++); name = buf; } stv->ident = strdup(name); AN(stv->ident); stv_check_ident(spec, stv->ident); if (stv->init != NULL) stv->init(stv, ac, av); else if (ac != 0) ARGV_ERR("(-s %s) too many arguments\n", stv->name); AN(stv->allocobj); AN(stv->methods); if (!strcmp(stv->ident, TRANSIENT_STORAGE)) { AZ(stv_transient); stv_transient = stv; } else VTAILQ_INSERT_TAIL(&stevedores, stv, list); /* NB: Do not free av, stevedore gets to keep it */ }
int STV_GetFile(const char *fn, int *fdp, const char **fnp, const char *ctx) { int fd; struct stat st; int retval = 1; char buf[FILENAME_MAX]; AN(fn); AN(fnp); AN(fdp); *fnp = NULL; *fdp = -1; /* try to create a new file of this name */ fd = open(fn, O_RDWR | O_CREAT | O_EXCL | O_LARGEFILE, 0600); if (fd >= 0) { *fdp = fd; *fnp = fn; return (retval); } if (stat(fn, &st)) ARGV_ERR( "(%s) \"%s\" does not exist and could not be created\n", ctx, fn); if (S_ISDIR(st.st_mode)) { bprintf(buf, "%s/varnish.XXXXXX", fn); fd = mkstemp(buf); if (fd < 0) ARGV_ERR("(%s) \"%s\" mkstemp(%s) failed (%s)\n", ctx, fn, buf, strerror(errno)); AZ(unlink(buf)); *fnp = strdup(buf); AN(*fnp); retval = 2; } else if (S_ISREG(st.st_mode)) { fd = open(fn, O_RDWR | O_LARGEFILE); if (fd < 0) ARGV_ERR("(%s) \"%s\" could not open (%s)\n", ctx, fn, strerror(errno)); *fnp = fn; retval = 0; } else ARGV_ERR( "(%s) \"%s\" is neither file nor directory\n", ctx, fn); AZ(fstat(fd, &st)); if (!S_ISREG(st.st_mode)) ARGV_ERR("(%s) \"%s\" was not a file after opening\n", ctx, fn); *fdp = fd; return (retval); }
vju_init(char **args) { if (args == NULL) { /* Autoconfig */ if (geteuid() != 0) return (1); if (vju_getuid(VARNISH_USER)) return (1); } else { if (geteuid() != 0) ARGV_ERR("Unix Jail: Must be root.\n"); for (;*args != NULL; args++) { if (!strncmp(*args, "user="******"Unix jail: %s user not found.\n", (*args) + 5); continue; } if (!strncmp(*args, "workuser="******"Unix jail: %s user not found.\n", (*args) + 9); continue; } if (!strncmp(*args, "ccgroup=", 8)) { if (vju_getccgid((*args) + 8)) ARGV_ERR( "Unix jail: %s group not found.\n", (*args) + 8); continue; } ARGV_ERR("Unix jail: unknown sub-argument '%s'\n", *args); } if (vju_user == NULL && vju_getuid(VARNISH_USER)) ARGV_ERR("Unix jail: %s user not found.\n", VARNISH_USER); } AN(vju_user); vju_mgr_gid = getgid(); if (vju_wrkuser == NULL) (void)vju_getwrkuid(VCACHE_USER); if (vju_wrkuser != NULL && vju_wrkgid != vju_gid) ARGV_ERR("Unix jail: user %s and %s have " "different login groups\n", vju_user, vju_wrkuser); /* Do an explicit JAIL_MASTER_LOW */ AZ(setegid(vju_gid)); AZ(seteuid(vju_uid)); return (0); }
smp_fake_init(struct stevedore *parent, int ac, char * const *av) { (void)parent; (void)ac; (void)av; ARGV_ERR( "-spersistent has been deprecated, please see:\n" " https://www.varnish-cache.org/docs/trunk/phk/persistent.html\n" "for details.\n" ); }
void mgt_cli_telnet(const char *T_arg) { int error; const char *err; struct vsb *vsb; AN(T_arg); vsb = VSB_new_auto(); AN(vsb); error = VSS_resolver(T_arg, NULL, mct_callback, vsb, &err); if (err != NULL) ARGV_ERR("Could resolve -T argument to address\n\t%s\n", err); AZ(error); AZ(VSB_finish(vsb)); if (VSB_len(vsb) == 0) ARGV_ERR("-T %s could not be listened on.", T_arg); /* Save in shmem */ mgt_SHM_static_alloc(VSB_data(vsb), VSB_len(vsb) + 1, "Arg", "-T", ""); VSB_destroy(&vsb); }
void mgt_cli_master(const char *M_arg) { const char *err; int error; AN(M_arg); error = VSS_resolver(M_arg, NULL, marg_cb, NULL, &err); if (err != NULL) ARGV_ERR("Could resolve -M argument to address\n\t%s\n", err); AZ(error); if (VTAILQ_EMPTY(&m_addr_list)) ARGV_ERR("Could not resolve -M argument to address\n"); AZ(M_poker); M_poker = vev_new(); AN(M_poker); M_poker->timeout = M_poll; M_poker->callback = Marg_poker; M_poker->name = "-M poker"; AZ(vev_add(mgt_evb, M_poker)); }
static void smu_init(struct stevedore *parent, int ac, char * const *av) { const char *e; uintmax_t u; (void)parent; AZ(av[ac]); if (ac > 1) ARGV_ERR("(-sumem) too many arguments\n"); if (ac == 0 || *av[0] == '\0') return; e = VNUM_2bytes(av[0], &u, 0); if (e != NULL) ARGV_ERR("(-sumem) size \"%s\": %s\n", av[0], e); if ((u != (uintmax_t)(size_t)u)) ARGV_ERR("(-sumem) size \"%s\": too big\n", av[0]); smu_max = u; }
static void tcp_keep_probes(void) { const char *err; int s; s = VTCP_listen_on(":0", NULL, 10, &err); if (err != NULL) ARGV_ERR("Could not probe TCP keepalives: %s", err); assert(s > 0); tcp_probe(s, TCP_KEEPIDLE, "tcp_keepalive_time", 600); tcp_probe(s, TCP_KEEPCNT, "tcp_keepalive_probes", 5); tcp_probe(s, TCP_KEEPINTVL, "tcp_keepalive_intvl", 5); AZ(close(s)); }
static void stv_check_ident(const char *spec, const char *ident) { struct stevedore *stv; unsigned found = 0; if (!strcmp(ident, TRANSIENT_STORAGE)) found = (stv_transient != NULL); else { STV_Foreach(stv) if (!strcmp(stv->ident, ident)) { found = 1; break; } } if (found) ARGV_ERR("(-s %s) '%s' is already defined\n", spec, ident); }
uintmax_t STV_FileSize(int fd, const char *size, unsigned *granularity, const char *ctx) { uintmax_t l, fssize; unsigned bs; const char *q; int i; off_t o; struct stat st; AN(granularity); AN(ctx); AZ(fstat(fd, &st)); xxxassert(S_ISREG(st.st_mode)); AZ(VFIL_fsinfo(fd, &bs, &fssize, NULL)); /* Increase granularity if it is lower than the filesystem block size */ if (*granularity < bs) *granularity = bs; if ((size == NULL || *size == '\0') && st.st_size != 0) { /* * We have no size specification, but an existing file, * use its existing size. */ l = st.st_size; } else if (size == NULL || *size == '\0') { ARGV_ERR("(%s) no size specified\n", ctx); } else { AN(size); q = VNUM_2bytes(size, &l, 0); if (q != NULL) ARGV_ERR("(%s) size \"%s\": %s\n", ctx, size, q); if (l < 1024*1024) ARGV_ERR("(%s) size \"%s\": too small, " "did you forget to specify M or G?\n", ctx, size); if (l > fssize) ARGV_ERR("(%s) size \"%s\": larger than file system\n", ctx, size); } /* * This trickery wouldn't be necessary if X/Open would * just add OFF_MAX to <limits.h>... */ i = 0; while(1) { o = l; if (o == l && o > 0) break; l >>= 1; i++; } if (i) fprintf(stderr, "WARNING: (%s) file size reduced" " to %ju due to system \"off_t\" limitations\n", ctx, l); if (sizeof(void *) == 4 && l > INT32_MAX) { /*lint !e506 !e774 !e845 */ fprintf(stderr, "NB: Storage size limited to 2GB on 32 bit architecture,\n" "NB: otherwise we could run out of address space.\n" ); l = INT32_MAX; } /* Round down */ l -= (l % *granularity); return(l); }
vjn_init(char **args) { if (args != NULL && *args != NULL) ARGV_ERR("-jnone takes no arguments.\n"); return (0); }
void smp_mgt_init(struct stevedore *parent, int ac, char * const *av) { struct smp_sc *sc; struct smp_sign sgn; void *target; int i; ASSERT_MGT(); AZ(av[ac]); /* Necessary alignment. See also smp_object::__filler__ */ assert(sizeof(struct smp_object) % 8 == 0); #define SIZOF(foo) fprintf(stderr, \ "sizeof(%s) = %zu = 0x%zx\n", #foo, sizeof(foo), sizeof(foo)); SIZOF(struct smp_ident); SIZOF(struct smp_sign); SIZOF(struct smp_segptr); SIZOF(struct smp_object); #undef SIZOF /* See comments in storage_persistent.h */ assert(sizeof(struct smp_ident) == SMP_IDENT_SIZE); /* Allocate softc */ ALLOC_OBJ(sc, SMP_SC_MAGIC); XXXAN(sc); sc->parent = parent; sc->fd = -1; VTAILQ_INIT(&sc->segments); /* Argument processing */ if (ac != 2) ARGV_ERR("(-spersistent) wrong number of arguments\n"); i = STV_GetFile(av[0], &sc->fd, &sc->filename, "-spersistent"); if (i == 2) ARGV_ERR("(-spersistent) need filename (not directory)\n"); sc->align = sizeof(void*) * 2; sc->granularity = getpagesize(); sc->mediasize = STV_FileSize(sc->fd, av[1], &sc->granularity, "-spersistent"); AZ(ftruncate(sc->fd, sc->mediasize)); /* Try to determine correct mmap address */ i = read(sc->fd, &sgn, sizeof sgn); assert(i == sizeof sgn); if (!strcmp(sgn.ident, "SILO")) target = (void*)(uintptr_t)sgn.mapped; else target = NULL; sc->base = (void*)mmap(target, sc->mediasize, PROT_READ|PROT_WRITE, MAP_NOCORE | MAP_NOSYNC | MAP_SHARED, sc->fd, 0); if (sc->base == MAP_FAILED) ARGV_ERR("(-spersistent) failed to mmap (%s)\n", strerror(errno)); smp_def_sign(sc, &sc->idn, 0, "SILO"); sc->ident = SIGN_DATA(&sc->idn); i = smp_valid_silo(sc); if (i) { printf("Warning SILO (%s) not reloaded (reason=%d)\n", sc->filename, i); smp_newsilo(sc); } AZ(smp_valid_silo(sc)); smp_metrics(sc); parent->priv = sc; /* XXX: only for sendfile I guess... */ mgt_child_inherit(sc->fd, "storage_persistent"); }
uintmax_t STV_FileSize(int fd, const char *size, unsigned *granularity, const char *ctx) { uintmax_t l, fssize; unsigned bs; const char *q; int i; off_t o; struct stat st; AZ(fstat(fd, &st)); xxxassert(S_ISREG(st.st_mode)); bs = *granularity; fssize = stv_fsspace(fd, &bs); xxxassert(bs % *granularity == 0); if ((size == NULL || *size == '\0') && st.st_size != 0) { /* * We have no size specification, but an existing file, * use its existing size. */ l = st.st_size; } else { AN(size); q = str2bytes(size, &l, fssize); if (q != NULL) ARGV_ERR("(%s) size \"%s\": %s\n", size, ctx, q); if (l < 1024*1024) ARGV_ERR("(-spersistent) size \"%s\": too small, " "did you forget to specify M or G?\n", size); } /* * This trickery wouldn't be necessary if X/Open would * just add OFF_MAX to <limits.h>... */ i = 0; while(1) { o = l; if (o == l && o > 0) break; l >>= 1; i++; } if (i) fprintf(stderr, "WARNING: (%s) file size reduced" " to %ju due to system \"off_t\" limitations\n", ctx, l); else if (l - st.st_size > fssize) { l = fssize * 80 / 100; fprintf(stderr, "WARNING: (%s) file size reduced" " to %ju (80%% of available disk space)\n", ctx, l); } if (sizeof(void *) == 4 && l > INT32_MAX) { /*lint !e506 !e774 !e845 */ fprintf(stderr, "NB: Storage size limited to 2GB on 32 bit architecture,\n" "NB: otherwise we could run out of address space.\n" ); l = INT32_MAX; } /* round down to multiple of filesystem blocksize or pagesize */ l -= (l % bs); *granularity = bs; return(l); }