[master] 25417c3 Refactor the VCC/CC invocations.
Poul-Henning Kamp
phk at FreeBSD.org
Tue Feb 10 16:18:15 CET 2015
commit 25417c3287d01f5c768b9c126f0eb3ce3459a99c
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Tue Feb 10 10:49:58 2015 +0000
Refactor the VCC/CC invocations.
Store C-src and compiled VCL under their VCL names, rather than
randomized names -- we know the VCL names are unique.
diff --git a/bin/varnishd/mgt/mgt_vcc.c b/bin/varnishd/mgt/mgt_vcc.c
index f18fe41..24fe666 100644
--- a/bin/varnishd/mgt/mgt_vcc.c
+++ b/bin/varnishd/mgt/mgt_vcc.c
@@ -1,6 +1,6 @@
/*-
* Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2011 Varnish Software AS
+ * Copyright (c) 2006-2015 Varnish Software AS
* All rights reserved.
*
* Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
@@ -58,6 +58,14 @@ struct vclprog {
int active;
};
+struct vcc_priv {
+ unsigned magic;
+#define VCC_PRIV_MAGIC 0x70080cb8
+ const char *src;
+ char *srcfile;
+ char *libfile;
+};
+
static VTAILQ_HEAD(, vclprog) vclhead = VTAILQ_HEAD_INITIALIZER(vclhead);
char *mgt_cc_cmd;
@@ -79,22 +87,23 @@ static const char * const builtin_vcl =
* Prepare the compiler command line
*/
static struct vsb *
-mgt_make_cc_cmd(const char *sf, const char *of)
+mgt_make_cc_cmd(const struct vcc_priv *vp)
{
struct vsb *sb;
int pct;
char *p;
+ CHECK_OBJ_NOTNULL(vp, VCC_PRIV_MAGIC);
sb = VSB_new_auto();
XXXAN(sb);
for (p = mgt_cc_cmd, pct = 0; *p; ++p) {
if (pct) {
switch (*p) {
case 's':
- VSB_cat(sb, sf);
+ VSB_cat(sb, vp->srcfile);
break;
case 'o':
- VSB_cat(sb, of);
+ VSB_cat(sb, vp->libfile);
break;
case '%':
VSB_putc(sb, '%');
@@ -121,13 +130,6 @@ mgt_make_cc_cmd(const char *sf, const char *of)
* Invoke system VCC compiler in a sub-process
*/
-struct vcc_priv {
- unsigned magic;
-#define VCC_PRIV_MAGIC 0x70080cb8
- char *sf;
- const char *vcl;
-};
-
static void
run_vcc(void *priv)
{
@@ -145,7 +147,7 @@ run_vcc(void *priv)
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->vcl);
+ csrc = VCC_Compile(vcc, sb, vp->src);
AZ(VSB_finish(sb));
if (VSB_len(sb))
printf("%s", VSB_data(sb));
@@ -153,15 +155,15 @@ run_vcc(void *priv)
if (csrc == NULL)
exit(2);
- fd = open(vp->sf, O_WRONLY);
+ fd = open(vp->srcfile, O_WRONLY|O_TRUNC|O_CREAT, 0600);
if (fd < 0) {
- fprintf(stderr, "Cannot open %s", vp->sf);
+ 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->sf);
+ fprintf(stderr, "Cannot write %s", vp->srcfile);
exit(2);
}
AZ(close(fd));
@@ -176,8 +178,17 @@ run_vcc(void *priv)
static void
run_cc(void *priv)
{
+ struct vcc_priv *vp;
+ struct vsb *cmdsb;
+
mgt_sandbox(SANDBOX_CC);
- (void)execl("/bin/sh", "/bin/sh", "-c", priv, (char*)0);
+ CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC);
+
+ /* Build the C-compiler command line */
+ cmdsb = mgt_make_cc_cmd(vp);
+
+ (void)umask(0177);
+ (void)execl("/bin/sh", "/bin/sh", "-c", VSB_data(cmdsb), (char*)0);
}
/*--------------------------------------------------------------------
@@ -187,18 +198,16 @@ run_cc(void *priv)
static void __match_proto__(sub_func_f)
run_dlopen(void *priv)
{
- const char *of;
void *dlh;
struct VCL_conf const *cnf;
-
- of = priv;
+ struct vcc_priv *vp;
mgt_sandbox(SANDBOX_VCLLOAD);
+ CAST_OBJ_NOTNULL(vp, priv, VCC_PRIV_MAGIC);
/* Try to load the object into this sub-process */
- if ((dlh = dlopen(of, RTLD_NOW | RTLD_LOCAL)) == NULL) {
- fprintf(stderr,
- "Compiled VCL program failed to load:\n %s\n",
+ if ((dlh = dlopen(vp->libfile, RTLD_NOW | RTLD_LOCAL)) == NULL) {
+ fprintf(stderr, "Compiled VCL program failed to load:\n %s\n",
dlerror());
exit(1);
}
@@ -224,121 +233,101 @@ run_dlopen(void *priv)
}
/*--------------------------------------------------------------------
- * Compile a VCL program, return shared object, errors in sb.
+ * Touch a filename and make it available to privsep-privs
*/
-static char *
-mgt_run_cc(const char *vcl, struct vsb *sb, int C_flag, unsigned *status)
+static int
+mgt_vcc_touchfile(const char *fn, struct vsb *sb)
{
- char *csrc;
- struct vsb *cmdsb;
- char sf[] = "./vcl.########.c";
- char of[sizeof sf + 1];
- char *retval;
- int sfd, i;
- unsigned subs;
- struct vcc_priv vp;
+ int i;
- *status = 0;
-
- /* Create temporary C source file */
- sfd = VFIL_tmpfile(sf);
- if (sfd < 0) {
- VSB_printf(sb, "Failed to create %s: %s", sf, strerror(errno));
- *status = 2;
- return (NULL);
- }
- if (fchown(sfd, mgt_param.uid, mgt_param.gid) != 0)
- if (geteuid() == 0)
- VSB_printf(sb, "Failed to change owner on %s: %s\n",
- sf, strerror(errno));
- AZ(close(sfd));
-
-
- /* Run the VCC compiler in a sub-process */
- INIT_OBJ(&vp, VCC_PRIV_MAGIC);
- vp.sf = sf;
- vp.vcl = vcl;
- subs = VSUB_run(sb, run_vcc, &vp, "VCC-compiler", -1);
- if (subs) {
- (void)unlink(sf);
- *status = subs;
- return (NULL);
- }
-
- if (C_flag) {
- csrc = VFIL_readfile(NULL, sf, NULL);
- XXXAN(csrc);
- (void)fputs(csrc, stdout);
- free(csrc);
- }
-
- /* Name the output shared library by "s/[.]c$/[.]so/" */
- memcpy(of, sf, sizeof sf);
- assert(sf[sizeof sf - 2] == 'c');
- of[sizeof sf - 2] = 's';
- of[sizeof sf - 1] = 'o';
- of[sizeof sf] = '\0';
-
- i = open(of, O_WRONLY|O_CREAT|O_TRUNC, 0600);
+ i = open(fn, O_WRONLY|O_CREAT|O_TRUNC, 0600);
if (i < 0) {
- VSB_printf(sb, "Failed to create %s: %s",
- of, strerror(errno));
- (void)unlink(sf);
- *status = 2;
- return (NULL);
+ VSB_printf(sb, "Failed to create %s: %s", fn, strerror(errno));
+ return (2);
}
if (fchown(i, mgt_param.uid, mgt_param.gid) != 0)
if (geteuid() == 0)
VSB_printf(sb, "Failed to change owner on %s: %s\n",
- of, strerror(errno));
+ fn, strerror(errno));
AZ(close(i));
+ return (0);
+}
- /* Build the C-compiler command line */
- cmdsb = mgt_make_cc_cmd(sf, of);
+/*--------------------------------------------------------------------
+ * Compile a VCL program, return shared object, errors in sb.
+ */
- /* Run the C-compiler in a sub-shell */
- subs = VSUB_run(sb, run_cc, VSB_data(cmdsb), "C-compiler", 10);
+static unsigned
+mgt_vcc_compile(struct vcc_priv *vp, struct vsb *sb, int C_flag)
+{
+ char *csrc;
+ unsigned subs;
- (void)unlink(sf);
- VSB_delete(cmdsb);
+ if (mgt_vcc_touchfile(vp->srcfile, sb))
+ return (2);
+ if (mgt_vcc_touchfile(vp->libfile, sb))
+ return (2);
- if (!subs)
- subs = VSUB_run(sb, run_dlopen, of, "dlopen", 10);
+ subs = VSUB_run(sb, run_vcc, vp, "VCC-compiler", -1);
+ if (subs)
+ return (subs);
- /* Ensure the file is readable to the unprivileged user */
- if (!subs) {
- i = chmod(of, 0755);
- if (i) {
- VSB_printf(sb, "Failed to set permissions on %s: %s",
- of, strerror(errno));
- subs = 2;
- }
+ if (C_flag) {
+ csrc = VFIL_readfile(NULL, vp->srcfile, NULL);
+ AN(csrc);
+ VSB_cat(sb, csrc);
}
- if (subs) {
- (void)unlink(of);
- *status = subs;
- return (NULL);
- }
+ subs = VSUB_run(sb, run_cc, vp, "C-compiler", 10);
+ if (subs)
+ return (subs);
+
+ subs = VSUB_run(sb, run_dlopen, vp, "dlopen", 10);
- retval = strdup(of);
- XXXAN(retval);
- return (retval);
+ return (subs);
}
/*--------------------------------------------------------------------*/
static char *
-mgt_VccCompile(struct vsb **sb, const char *b, int C_flag, unsigned *status)
+mgt_VccCompile(struct vsb **sb, const char *vclname, const char *vclsrc,
+ int C_flag, unsigned *status)
{
- char *vf;
+ struct vcc_priv vp;
*sb = VSB_new_auto();
XXXAN(*sb);
- vf = mgt_run_cc(b, *sb, C_flag, status);
+
+ INIT_OBJ(&vp, VCC_PRIV_MAGIC);
+ vp.src = vclsrc;
+
+ VSB_printf(*sb, "./vcl_%s.c", vclname);
+ AZ(VSB_finish(*sb));
+ vp.srcfile = strdup(VSB_data(*sb));
+ AN(vp.srcfile);
+ VSB_clear(*sb);
+
+ VSB_printf(*sb, "./vcl_%s.so", vclname);
AZ(VSB_finish(*sb));
- return (vf);
+ vp.libfile = strdup(VSB_data(*sb));
+ AN(vp.srcfile);
+ VSB_clear(*sb);
+
+ *status = mgt_vcc_compile(&vp, *sb, C_flag);
+
+ AZ(VSB_finish(*sb));
+
+ (void)unlink(vp.srcfile);
+ free(vp.srcfile);
+
+ if (*status) {
+ (void)unlink(vp.libfile);
+ free(vp.libfile);
+ return (NULL);
+ } else {
+ return (vp.libfile);
+ }
}
/*--------------------------------------------------------------------*/
@@ -427,7 +416,7 @@ mgt_vcc_default(const char *b_arg, const char *f_arg, char *vcl, int C_flag)
}
strcpy(buf, "boot");
- vf = mgt_VccCompile(&sb, vcl, C_flag, &status);
+ vf = mgt_VccCompile(&sb, buf, vcl, C_flag, &status);
free(vcl);
if (VSB_len(sb) > 0)
fprintf(stderr, "%s", VSB_data(sb));
@@ -527,7 +516,7 @@ mcf_config_inline(struct cli *cli, const char * const *av, void *priv)
return;
}
- vf = mgt_VccCompile(&sb, av[3], 0, &status);
+ vf = mgt_VccCompile(&sb, av[2], av[3], 0, &status);
if (VSB_len(sb) > 0)
VCLI_Out(cli, "%s\n", VSB_data(sb));
VSB_delete(sb);
@@ -572,7 +561,7 @@ mcf_config_load(struct cli *cli, const char * const *av, void *priv)
return;
}
- vf = mgt_VccCompile(&sb, vcl, 0, &status);
+ vf = mgt_VccCompile(&sb, av[2], vcl, 0, &status);
free(vcl);
if (VSB_len(sb) > 0)
More information about the varnish-commit
mailing list