[master] c19da9d minimal changes to the former solaris sandbox to use the new jail framework

Nils Goroll nils.goroll at uplex.de
Mon Feb 16 15:48:51 CET 2015


commit c19da9dad1fffa1cea5dca6ec389417d4d2c4c56
Author: Nils Goroll <nils.goroll at uplex.de>
Date:   Mon Feb 16 15:47:29 2015 +0100

    minimal changes to the former solaris sandbox to use the new jail framework

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index 1aebc43..aeef7c1 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -66,6 +66,7 @@ varnishd_SOURCES = \
 	mgt/mgt_cli.c \
 	mgt/mgt_jail.c \
 	mgt/mgt_jail_unix.c \
+	mgt/mgt_jail_solaris.c \
 	mgt/mgt_main.c \
 	mgt/mgt_param.c \
 	mgt/mgt_param_tbl.c \
diff --git a/bin/varnishd/mgt/mgt.h b/bin/varnishd/mgt/mgt.h
index 4aa707d..718e6a4 100644
--- a/bin/varnishd/mgt/mgt.h
+++ b/bin/varnishd/mgt/mgt.h
@@ -94,6 +94,7 @@ void VJ_master(enum jail_master_e jme);
 void VJ_subproc(enum jail_subproc_e jse);
 
 extern const struct jail_tech jail_tech_unix;
+extern const struct jail_tech jail_tech_solaris;
 
 /* mgt_main.c */
 extern struct VSC_C_mgt	*VSC_C_mgt;
diff --git a/bin/varnishd/mgt/mgt_jail.c b/bin/varnishd/mgt/mgt_jail.c
index 00afa89..081e9e8 100644
--- a/bin/varnishd/mgt/mgt_jail.c
+++ b/bin/varnishd/mgt/mgt_jail.c
@@ -74,6 +74,7 @@ static const struct jail_tech jail_tech_none = {
 static const struct jail_tech *vjt;
 
 static const struct choice vj_choice[] = {
+	{ "solaris",	&jail_tech_solaris },
 	{ "unix",	&jail_tech_unix },
 	{ "none",	&jail_tech_none },
 	{ NULL,		NULL },
diff --git a/bin/varnishd/mgt/mgt_jail_solaris.c b/bin/varnishd/mgt/mgt_jail_solaris.c
new file mode 100644
index 0000000..ce610d1
--- /dev/null
+++ b/bin/varnishd/mgt/mgt_jail_solaris.c
@@ -0,0 +1,499 @@
+/*-
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * Copyright (c) 2011-2012 UPLEX - Nils Goroll Systemoptimierung
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *	   Nils Goroll <nils.goroll at uplex.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Sandboxing child processes on Solaris
+ * =====================================
+ *
+ * Note on use of symbolic PRIV_* constants
+ * ----------------------------------------
+ *
+ * We assume backwards compatibility only for Solaris Releases after the
+ * OpenSolaris Launch. For privileges which existed at the time of the
+ * OpenSolaris Launch, we use the constants from sys/priv_names.h and assert
+ * that priv_addset must succeed.
+ *
+ * For privileges which have been added later, we need to use priv strings in
+ * order not to break builds of varnish on older platforms. To remain binary
+ * compatible, we can't assert that priv_addset succeeds, but we may assert that
+ * it either succeeds or fails with EINVAL.
+ *
+ * See priv_setop_check()
+ *
+ * Note on introduction of new privileges (or: lack of forward compatibility)
+ * --------------------------------------------------------------------------
+ *
+ * For optimal build and binary forward comatibility, we could use subtractive
+ * set specs like
+ *
+ *       basic,!file_link_any,!proc_exec,!proc_fork,!proc_info,!proc_session
+ *
+ * which would implicitly keep any privileges newly introduced to the 'basic'
+ * set.
+ *
+ * But we have a preference for making an informed decision about which
+ * privileges varnish sandboxes should have, so we prefer to risk breaking
+ * varnish temporarily on newer kernels and be notified of missing privileges
+ * through bug reports.
+ *
+ * Notes on the SNOCD flag
+ * -----------------------
+ *
+ * On Solaris, any uid/gid fiddling which can be interpreted as 'waiving
+ * privileges' will lead to the processes' SNOCD flag being set, disabling core
+ * dumps unless explicitly allowed using coreadm (see below). There is no
+ * equivalent to Linux PR_SET_DUMPABLE. The only way to clear the flag is a call
+ * to some form of exec(). The presence of the SNOCD flag also prevents many
+ * process manipulations from other processes with the same uid/gid unless they
+ * have the proc_owner privilege.
+ *
+ * Thus, if we want to run sandboxes with a different uid/gid than the master
+ * process, we cannot avoid the SNOCD flag for those sandboxes not exec'ing
+ * (VCC, VCLLOAD, WORKER).
+ *
+ *
+ * We should, however, avoid to accidentally set the SNOCD flag when setting
+ * privileges (see https://www.varnish-cache.org/trac/ticket/671 )
+ *
+ * When changing the logic herein, always check with mdb -k. Replace _PID_ with
+ * the pid of your varnish child, the result should be 0, otherwise a regression
+ * has been introduced.
+ *
+ * > 0t_PID_::pid2proc | ::print proc_t p_flag | >a
+ * > (<a & 0x10000000)=X
+ *		0
+ *
+ * (a value of 0x10000000 indicates that SNOCD is set)
+ *
+ * How to get core dumps of the worker process on Solaris
+ * ------------------------------------------------------
+ *
+ * (see previous paragraph for explanation).
+ *
+ * Two options:
+ *
+ * - start the varnish master process under the same user/group given for the -u
+ *   / -g command line option and elevated privileges but without proc_setid,
+ *   e.g.:
+ *
+ *	pfexec ppriv -e -s A=basic,net_privaddr,sys_resource varnish ...
+ *
+ * - allow coredumps of setid processes (ignoring SNOCD)
+ *
+ *   See coreadm(1M) - global-setid / proc-setid
+ *
+ * brief histroy of privileges introduced since OpenSolaris Launch
+ * ---------------------------------------------------------------
+ *
+ * (from hg log -gp usr/src/uts/common/os/priv_defs
+ *    or git log -p usr/src/uts/common/os/priv_defs)
+ *
+ * ARC cases are not necessarily accurate (induced from commit msg)
+ *
+ * privileges used here marked with *
+ *
+ * ILlumos ticket
+ * ARC case	    hg/git commit  first release
+ *
+ * PSARC/2006/155?  37f4a3e2bd99   onnv_37
+ * - file_downgrade_sl
+ * - file_upgrade_sl
+ * - net_bindmlp
+ * - net_mac_aware
+ * - sys_trans_label
+ * - win_colormap
+ * - win_config
+ * - win_dac_read
+ * - win_dac_write
+ * - win_devices
+ * - win_dga
+ * - win_downgrade_sl
+ * - win_fontpath
+ * - win_mac_read
+ * - win_mac_write
+ * - win_selection
+ * - win_upgrade_sl
+ *
+ * PSARC/2006/218   5dbf296c1e57   onnv_39
+ * - graphics_access
+ * - graphics_map
+ *
+ * PSARC/2006/366   aaf16568054b   onnv_57
+ * - net_config
+ *
+ * PSARC/2007/315?  3047ad28a67b   onnv_77
+ * - file_flag_set
+ *
+ * PSARC/2007/560?  3047ad28a67b   onnv_77
+ * - sys_smb
+ *
+ * PSARC 2008/046   47f6aa7a8077   onnv_85
+ * - contract_identify
+ *
+ * PSARC 2008/289   79a9dac325d9   onnv_92
+ * - virt_manage
+ * - xvm_control
+ *
+ * PSARC 2008/473   eff7960d93cd   onnv_98
+ * - sys_dl_config
+ *
+ * PSARC/2006/475   faf256d5c16c   onnv_103
+ * - net_observability
+ *
+ * PSARC/2009/317   8e29565352fc   onnv_117
+ * - sys_ppp_config
+ *
+ * PSARC/2009/373   3be00c4a6835   onnv_125
+ * - sys_iptun_config
+ *
+ * PSARC/2008/252   e209937a4f19   onnv_128
+ * - net_mac_implicit
+ *
+ * PSARC/2009/685   8eca52188202   onnv_132
+ * * net_access
+ *
+ * PSARC/2009/378   63678502e95e   onnv_140
+ * * file_read
+ * * file_write
+ *
+ * PSARC/2010/181   15439b11d535   onnv_142
+ * - sys_res_bind
+ *
+ * unknown	    unknown	   Solaris11
+ * - sys_flow_config
+ * - sys_share
+ *
+ * IL3923	    24d819e6779c   Illumos
+ * - proc_prioup
+ *
+ */
+
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include "mgt/mgt.h"
+
+#include "common/heritage.h"
+#include "common/params.h"
+
+#ifndef HAVE_SETPPRIV
+
+/* ============================================================
+ * on platforms without setppriv, fail the init to mark that
+ * this jail is unavailable
+ */
+
+static int __match_proto__(jail_init_f)
+vjs_init(char **args)
+{
+	(void) args;
+	return 1;
+}
+
+const struct jail_tech jail_tech_solaris = {
+	.magic =	JAIL_TECH_MAGIC,
+	.name =	"solaris (unavailable)",
+	.init =	vjs_init,
+};
+
+#else /* HAVE_SETPPRIV */
+
+#ifdef HAVE_PRIV_H
+#include <priv.h>
+#endif
+
+/* ============================================================
+ * the real thing
+ */
+
+static int __match_proto__(jail_init_f)
+vjs_init(char **args)
+{
+	(void) args;
+	return 0;
+}
+
+/* for priv_delset() and priv_addset() */
+static inline int
+priv_setop_check(int a) {
+	if (a == 0)
+		return (1);
+	if (errno == EINVAL)
+		return (1);
+	return (0);
+}
+
+#define priv_setop_assert(a) assert(priv_setop_check(a))
+
+/*
+ * we try to add all possible privileges to waive them later.
+ *
+ * when doing so, we need to expect EPERM
+ */
+
+/* for setppriv */
+static inline int
+setppriv_check(int a) {
+	if (a == 0)
+		return (1);
+	if (errno == EPERM)
+		return (1);
+	return (0);
+}
+
+#define setppriv_assert(a) assert(setppriv_check(a))
+
+static void
+vjs_add_inheritable(priv_set_t *pset, enum jail_subproc_e jse)
+{
+	switch (jse) {
+	case JAIL_SUBPROC_VCC:
+		/* for /etc/resolv.conf and /etc/hosts */
+		priv_setop_assert(priv_addset(pset, "file_read"));
+		break;
+	case JAIL_SUBPROC_CC:
+		priv_setop_assert(priv_addset(pset, PRIV_PROC_EXEC));
+		priv_setop_assert(priv_addset(pset, PRIV_PROC_FORK));
+		priv_setop_assert(priv_addset(pset, "file_read"));
+		priv_setop_assert(priv_addset(pset, "file_write"));
+		break;
+	case JAIL_SUBPROC_VCLLOAD:
+		break;
+	case JAIL_SUBPROC_WORKER:
+		break;
+	default:
+		INCOMPL();
+	}
+}
+
+/*
+ * effective is initialized from inheritable (see vjs_waive)
+ * so only additionally required privileges need to be added here
+ */
+
+static void
+vjs_add_effective(priv_set_t *pset, enum jail_subproc_e jse)
+{
+	switch (jse) {
+	case JAIL_SUBPROC_VCC:
+		priv_setop_assert(priv_addset(pset, "file_write"));
+		break;
+	case JAIL_SUBPROC_CC:
+		break;
+	case JAIL_SUBPROC_VCLLOAD:
+		priv_setop_assert(priv_addset(pset, "file_read"));
+	case JAIL_SUBPROC_WORKER:
+		priv_setop_assert(priv_addset(pset, "net_access"));
+		priv_setop_assert(priv_addset(pset, "file_read"));
+		priv_setop_assert(priv_addset(pset, "file_write"));
+		break;
+	default:
+		INCOMPL();
+	}
+}
+
+/*
+ * permitted is initialized from effective (see vjs_waive)
+ * so only additionally required privileges need to be added here
+ */
+
+static void
+vjs_add_permitted(priv_set_t *pset, enum jail_subproc_e jse)
+{
+	switch (jse) {
+	case JAIL_SUBPROC_VCC:
+	case JAIL_SUBPROC_CC:
+	case JAIL_SUBPROC_VCLLOAD:
+		break;
+	case JAIL_SUBPROC_WORKER:
+		/* for raising limits in cache_waiter_ports.c */
+		AZ(priv_addset(pset, PRIV_SYS_RESOURCE));
+		break;
+	default:
+		INCOMPL();
+	}
+}
+
+/*
+ * additional privileges needed by vjs_privsep -
+ * will get waived in vjs_waive
+ */
+static void
+vjs_add_initial(priv_set_t *pset, enum jail_subproc_e jse)
+{
+	(void)jse;
+
+	/* for setgid/setuid */
+	AZ(priv_addset(pset, PRIV_PROC_SETID));
+}
+
+/*
+ * if we are not yet privilege-aware already (ie we have been started
+ * not-privilege aware with euid 0), we try to grab any privileges we
+ * will need later.
+ * We will reduce to least privileges in vjs_waive
+ *
+ * We need to become privilege-aware to avoid setuid resetting them.
+ */
+
+static void
+vjs_setup(enum jail_subproc_e jse)
+{
+	priv_set_t *priv_all;
+
+	if (! (priv_all = priv_allocset())) {
+		REPORT(LOG_ERR,
+		    "Sandbox warning: "
+		    " vjs_setup - priv_allocset failed: errno=%d (%s)",
+		    errno, strerror(errno));
+		return;
+	}
+
+	priv_emptyset(priv_all);
+
+	vjs_add_inheritable(priv_all, jse);
+	vjs_add_effective(priv_all, jse);
+	vjs_add_permitted(priv_all, jse);
+	vjs_add_initial(priv_all, jse);
+
+	/* try to get all possible privileges, expect EPERM here */
+	setppriv_assert(setppriv(PRIV_ON, PRIV_PERMITTED, priv_all));
+	setppriv_assert(setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_all));
+	setppriv_assert(setppriv(PRIV_ON, PRIV_INHERITABLE, priv_all));
+
+	priv_freeset(priv_all);
+}
+
+static void
+vjs_privsep(enum jail_subproc_e jse)
+{
+	(void)jse;
+
+	if (priv_ineffect(PRIV_PROC_SETID)) {
+		if (getgid() != mgt_param.gid)
+			XXXAZ(setgid(mgt_param.gid));
+		if (getuid() != mgt_param.uid)
+			XXXAZ(setuid(mgt_param.uid));
+	} else {
+		REPORT(LOG_INFO,
+		    "Privilege %s missing, will not change uid/gid",
+		    PRIV_PROC_SETID);
+	}
+}
+
+/*
+ * Waive most privileges in the child
+ *
+ * as of onnv_151a, we should end up with:
+ *
+ * > ppriv -v #pid of varnish child
+ * PID:  .../varnishd ...
+ * flags = PRIV_AWARE
+ *      E: file_read,file_write,net_access
+ *      I: none
+ *      P: file_read,file_write,net_access,sys_resource
+ *      L: file_read,file_write,net_access,sys_resource
+ *
+ * We should keep sys_resource in P in order to adjust our limits if we need to
+ */
+
+static void
+vjs_waive(enum jail_subproc_e jse)
+{
+	priv_set_t *effective, *inheritable, *permitted;
+
+	if (!(effective = priv_allocset()) ||
+	    !(inheritable = priv_allocset()) ||
+	    !(permitted = priv_allocset())) {
+		REPORT(LOG_ERR,
+		    "Sandbox warning: "
+		    " mgt_sandbox_waive - priv_allocset failed: errno=%d (%s)",
+		    errno, strerror(errno));
+		return;
+	}
+
+	/*
+	 * simple scheme:
+	 *     (inheritable subset-of effective) subset-of permitted
+	 */
+
+	priv_emptyset(inheritable);
+	vjs_add_inheritable(inheritable, jse);
+
+	priv_copyset(inheritable, effective);
+	vjs_add_effective(effective, jse);
+
+	priv_copyset(effective, permitted);
+	vjs_add_permitted(permitted, jse);
+
+	/*
+	 * invert the sets and clear privileges such that setppriv will always
+	 * succeed
+	 */
+	priv_inverse(inheritable);
+	priv_inverse(effective);
+	priv_inverse(permitted);
+
+	AZ(setppriv(PRIV_OFF, PRIV_LIMIT, permitted));
+	AZ(setppriv(PRIV_OFF, PRIV_PERMITTED, permitted));
+	AZ(setppriv(PRIV_OFF, PRIV_EFFECTIVE, effective));
+	AZ(setppriv(PRIV_OFF, PRIV_INHERITABLE, inheritable));
+
+	priv_freeset(inheritable);
+	priv_freeset(effective);
+	priv_freeset(permitted);
+}
+
+static void __match_proto__(jail_subproc_f)
+vjs_subproc(enum jail_subproc_e jse)
+{
+	vjs_setup(jse);
+	vjs_privsep(jse);
+	vjs_waive(jse);
+}
+
+// XXX TODO
+static void __match_proto__(jail_master_f)
+vjs_master(enum jail_master_e jme)
+{
+	(void)jme;
+}
+
+const struct jail_tech jail_tech_solaris = {
+	.magic =	JAIL_TECH_MAGIC,
+	.name =	"solaris",
+	.init =	vjs_init,
+	.master =	vjs_master,
+	.subproc =	vjs_subproc,
+};
+
+#endif /* HAVE_SETPPRIV */
diff --git a/bin/varnishd/mgt/mgt_sandbox_solaris.c b/bin/varnishd/mgt/mgt_sandbox_solaris.c
deleted file mode 100644
index 8f4497f..0000000
--- a/bin/varnishd/mgt/mgt_sandbox_solaris.c
+++ /dev/null
@@ -1,464 +0,0 @@
-/*-
- * Copyright (c) 2006-2011 Varnish Software AS
- * Copyright (c) 2011-2012 UPLEX - Nils Goroll Systemoptimierung
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *	   Nils Goroll <nils.goroll at uplex.de>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * Sandboxing child processes on Solaris
- * =====================================
- *
- * Note on use of symbolic PRIV_* constants
- * ----------------------------------------
- *
- * We assume backwards compatibility only for Solaris Releases after the
- * OpenSolaris Launch. For privileges which existed at the time of the
- * OpenSolaris Launch, we use the constants from sys/priv_names.h and assert
- * that priv_addset must succeed.
- *
- * For privileges which have been added later, we need to use priv strings in
- * order not to break builds of varnish on older platforms. To remain binary
- * compatible, we can't assert that priv_addset succeeds, but we may assert that
- * it either succeeds or fails with EINVAL.
- *
- * See priv_setop_check()
- *
- * Note on introduction of new privileges (or: lack of forward compatibility)
- * --------------------------------------------------------------------------
- *
- * For optimal build and binary forward comatibility, we could use subtractive
- * set specs like
- *
- *       basic,!file_link_any,!proc_exec,!proc_fork,!proc_info,!proc_session
- *
- * which would implicitly keep any privileges newly introduced to the 'basic'
- * set.
- *
- * But we have a preference for making an informed decision about which
- * privileges varnish sandboxes should have, so we prefer to risk breaking
- * varnish temporarily on newer kernels and be notified of missing privileges
- * through bug reports.
- *
- * Notes on the SNOCD flag
- * -----------------------
- *
- * On Solaris, any uid/gid fiddling which can be interpreted as 'waiving
- * privileges' will lead to the processes' SNOCD flag being set, disabling core
- * dumps unless explicitly allowed using coreadm (see below). There is no
- * equivalent to Linux PR_SET_DUMPABLE. The only way to clear the flag is a call
- * to some form of exec(). The presence of the SNOCD flag also prevents many
- * process manipulations from other processes with the same uid/gid unless they
- * have the proc_owner privilege.
- *
- * Thus, if we want to run sandboxes with a different uid/gid than the master
- * process, we cannot avoid the SNOCD flag for those sandboxes not exec'ing
- * (VCC, VCLLOAD, WORKER).
- *
- *
- * We should, however, avoid to accidentally set the SNOCD flag when setting
- * privileges (see https://www.varnish-cache.org/trac/ticket/671 )
- *
- * When changing the logic herein, always check with mdb -k. Replace _PID_ with
- * the pid of your varnish child, the result should be 0, otherwise a regression
- * has been introduced.
- *
- * > 0t_PID_::pid2proc | ::print proc_t p_flag | >a
- * > (<a & 0x10000000)=X
- *		0
- *
- * (a value of 0x10000000 indicates that SNOCD is set)
- *
- * How to get core dumps of the worker process on Solaris
- * ------------------------------------------------------
- *
- * (see previous paragraph for explanation).
- *
- * Two options:
- *
- * - start the varnish master process under the same user/group given for the -u
- *   / -g command line option and elevated privileges but without proc_setid,
- *   e.g.:
- *
- *	pfexec ppriv -e -s A=basic,net_privaddr,sys_resource varnish ...
- *
- * - allow coredumps of setid processes (ignoring SNOCD)
- *
- *   See coreadm(1M) - global-setid / proc-setid
- *
- * brief histroy of privileges introduced since OpenSolaris Launch
- * ---------------------------------------------------------------
- *
- * (from hg log -gp usr/src/uts/common/os/priv_defs
- *    or git log -p usr/src/uts/common/os/priv_defs)
- *
- * ARC cases are not necessarily accurate (induced from commit msg)
- *
- * privileges used here marked with *
- *
- * ILlumos ticket
- * ARC case	    hg/git commit  first release
- *
- * PSARC/2006/155?  37f4a3e2bd99   onnv_37
- * - file_downgrade_sl
- * - file_upgrade_sl
- * - net_bindmlp
- * - net_mac_aware
- * - sys_trans_label
- * - win_colormap
- * - win_config
- * - win_dac_read
- * - win_dac_write
- * - win_devices
- * - win_dga
- * - win_downgrade_sl
- * - win_fontpath
- * - win_mac_read
- * - win_mac_write
- * - win_selection
- * - win_upgrade_sl
- *
- * PSARC/2006/218   5dbf296c1e57   onnv_39
- * - graphics_access
- * - graphics_map
- *
- * PSARC/2006/366   aaf16568054b   onnv_57
- * - net_config
- *
- * PSARC/2007/315?  3047ad28a67b   onnv_77
- * - file_flag_set
- *
- * PSARC/2007/560?  3047ad28a67b   onnv_77
- * - sys_smb
- *
- * PSARC 2008/046   47f6aa7a8077   onnv_85
- * - contract_identify
- *
- * PSARC 2008/289   79a9dac325d9   onnv_92
- * - virt_manage
- * - xvm_control
- *
- * PSARC 2008/473   eff7960d93cd   onnv_98
- * - sys_dl_config
- *
- * PSARC/2006/475   faf256d5c16c   onnv_103
- * - net_observability
- *
- * PSARC/2009/317   8e29565352fc   onnv_117
- * - sys_ppp_config
- *
- * PSARC/2009/373   3be00c4a6835   onnv_125
- * - sys_iptun_config
- *
- * PSARC/2008/252   e209937a4f19   onnv_128
- * - net_mac_implicit
- *
- * PSARC/2009/685   8eca52188202   onnv_132
- * * net_access
- *
- * PSARC/2009/378   63678502e95e   onnv_140
- * * file_read
- * * file_write
- *
- * PSARC/2010/181   15439b11d535   onnv_142
- * - sys_res_bind
- *
- * unknown	    unknown	   Solaris11
- * - sys_flow_config
- * - sys_share
- *
- * IL3923	    24d819e6779c   Illumos
- * - proc_prioup
- *
- */
-
-#include "config.h"
-
-#ifdef HAVE_SETPPRIV
-
-#ifdef HAVE_PRIV_H
-#include <priv.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include "mgt/mgt.h"
-
-#include "common/heritage.h"
-#include "common/params.h"
-
-/*--------------------------------------------------------------------
- */
-
-/* for priv_delset() and priv_addset() */
-static inline int
-priv_setop_check(int a) {
-	if (a == 0)
-		return (1);
-	if (errno == EINVAL)
-		return (1);
-	return (0);
-}
-
-#define priv_setop_assert(a) assert(priv_setop_check(a))
-
-/*
- * we try to add all possible privileges to waive them later.
- *
- * when doing so, we need to expect EPERM
- */
-
-/* for setppriv */
-static inline int
-setppriv_check(int a) {
-	if (a == 0)
-		return (1);
-	if (errno == EPERM)
-		return (1);
-	return (0);
-}
-
-#define setppriv_assert(a) assert(setppriv_check(a))
-
-static void
-mgt_sandbox_solaris_add_inheritable(priv_set_t *pset, enum sandbox_e who)
-{
-	switch (who) {
-	case SANDBOX_VCC:
-		/* for /etc/resolv.conf and /etc/hosts */
-		priv_setop_assert(priv_addset(pset, "file_read"));
-		break;
-	case SANDBOX_CC:
-		priv_setop_assert(priv_addset(pset, PRIV_PROC_EXEC));
-		priv_setop_assert(priv_addset(pset, PRIV_PROC_FORK));
-		priv_setop_assert(priv_addset(pset, "file_read"));
-		priv_setop_assert(priv_addset(pset, "file_write"));
-		break;
-	case SANDBOX_VCLLOAD:
-		break;
-	case SANDBOX_WORKER:
-		break;
-	default:
-		INCOMPL();
-	}
-}
-
-/*
- * effective is initialized from inheritable (see mgt_sandbox_solaris_waive)
- * so only additionally required privileges need to be added here
- */
-
-static void
-mgt_sandbox_solaris_add_effective(priv_set_t *pset, enum sandbox_e who)
-{
-	switch (who) {
-	case SANDBOX_VCC:
-		priv_setop_assert(priv_addset(pset, "file_write"));
-		break;
-	case SANDBOX_CC:
-		break;
-	case SANDBOX_VCLLOAD:
-		priv_setop_assert(priv_addset(pset, "file_read"));
-	case SANDBOX_WORKER:
-		priv_setop_assert(priv_addset(pset, "net_access"));
-		priv_setop_assert(priv_addset(pset, "file_read"));
-		priv_setop_assert(priv_addset(pset, "file_write"));
-		break;
-	default:
-		INCOMPL();
-	}
-}
-
-/*
- * permitted is initialized from effective (see mgt_sandbox_solaris_waive)
- * so only additionally required privileges need to be added here
- */
-
-static void
-mgt_sandbox_solaris_add_permitted(priv_set_t *pset, enum sandbox_e who)
-{
-	switch (who) {
-	case SANDBOX_VCC:
-	case SANDBOX_CC:
-	case SANDBOX_VCLLOAD:
-		break;
-	case SANDBOX_WORKER:
-		/* for raising limits in cache_waiter_ports.c */
-		AZ(priv_addset(pset, PRIV_SYS_RESOURCE));
-		break;
-	default:
-		INCOMPL();
-	}
-}
-
-/*
- * additional privileges needed by mgt_sandbox_solaris_privsep -
- * will get waived in mgt_sandbox_solaris_waive
- */
-static void
-mgt_sandbox_solaris_add_initial(priv_set_t *pset, enum sandbox_e who)
-{
-	(void)who;
-
-	/* for setgid/setuid */
-	AZ(priv_addset(pset, PRIV_PROC_SETID));
-}
-
-/*
- * if we are not yet privilege-aware already (ie we have been started
- * not-privilege aware with euid 0), we try to grab any privileges we
- * will need later.
- * We will reduce to least privileges in mgt_sandbox_solaris_waive
- *
- * We need to become privilege-aware to avoid setuid resetting them.
- */
-
-static void
-mgt_sandbox_solaris_init(enum sandbox_e who)
-{
-	priv_set_t *priv_all;
-
-	if (! (priv_all = priv_allocset())) {
-		REPORT(LOG_ERR,
-		    "Sandbox warning: "
-		    " mgt_sandbox_init - priv_allocset failed: errno=%d (%s)",
-		    errno, strerror(errno));
-		return;
-	}
-
-	priv_emptyset(priv_all);
-
-	mgt_sandbox_solaris_add_inheritable(priv_all, who);
-	mgt_sandbox_solaris_add_effective(priv_all, who);
-	mgt_sandbox_solaris_add_permitted(priv_all, who);
-	mgt_sandbox_solaris_add_initial(priv_all, who);
-
-	/* try to get all possible privileges, expect EPERM here */
-	setppriv_assert(setppriv(PRIV_ON, PRIV_PERMITTED, priv_all));
-	setppriv_assert(setppriv(PRIV_ON, PRIV_EFFECTIVE, priv_all));
-	setppriv_assert(setppriv(PRIV_ON, PRIV_INHERITABLE, priv_all));
-
-	priv_freeset(priv_all);
-}
-
-static void
-mgt_sandbox_solaris_privsep(enum sandbox_e who)
-{
-	(void)who;
-
-	if (priv_ineffect(PRIV_PROC_SETID)) {
-		if (getgid() != mgt_param.gid)
-			XXXAZ(setgid(mgt_param.gid));
-		if (getuid() != mgt_param.uid)
-			XXXAZ(setuid(mgt_param.uid));
-	} else {
-		REPORT(LOG_INFO,
-		    "Privilege %s missing, will not change uid/gid",
-		    PRIV_PROC_SETID);
-	}
-}
-
-/*
- * Waive most privileges in the child
- *
- * as of onnv_151a, we should end up with:
- *
- * > ppriv -v #pid of varnish child
- * PID:  .../varnishd ...
- * flags = PRIV_AWARE
- *      E: file_read,file_write,net_access
- *      I: none
- *      P: file_read,file_write,net_access,sys_resource
- *      L: file_read,file_write,net_access,sys_resource
- *
- * We should keep sys_resource in P in order to adjust our limits if we need to
- */
-
-static void
-mgt_sandbox_solaris_waive(enum sandbox_e who)
-{
-	priv_set_t *effective, *inheritable, *permitted;
-
-	if (!(effective = priv_allocset()) ||
-	    !(inheritable = priv_allocset()) ||
-	    !(permitted = priv_allocset())) {
-		REPORT(LOG_ERR,
-		    "Sandbox warning: "
-		    " mgt_sandbox_waive - priv_allocset failed: errno=%d (%s)",
-		    errno, strerror(errno));
-		return;
-	}
-
-	/*
-	 * simple scheme:
-	 *     (inheritable subset-of effective) subset-of permitted
-	 */
-
-	priv_emptyset(inheritable);
-	mgt_sandbox_solaris_add_inheritable(inheritable, who);
-
-	priv_copyset(inheritable, effective);
-	mgt_sandbox_solaris_add_effective(effective, who);
-
-	priv_copyset(effective, permitted);
-	mgt_sandbox_solaris_add_permitted(permitted, who);
-
-	/*
-	 * invert the sets and clear privileges such that setppriv will always
-	 * succeed
-	 */
-	priv_inverse(inheritable);
-	priv_inverse(effective);
-	priv_inverse(permitted);
-
-	AZ(setppriv(PRIV_OFF, PRIV_LIMIT, permitted));
-	AZ(setppriv(PRIV_OFF, PRIV_PERMITTED, permitted));
-	AZ(setppriv(PRIV_OFF, PRIV_EFFECTIVE, effective));
-	AZ(setppriv(PRIV_OFF, PRIV_INHERITABLE, inheritable));
-
-	priv_freeset(inheritable);
-	priv_freeset(effective);
-	priv_freeset(permitted);
-}
-
-void __match_proto__(mgt_sandbox_f)
-mgt_sandbox_solaris(enum sandbox_e who)
-{
-	/*
-	 * XXX - clarify with phk:
-	 * there is no "all-or-nothing" for the solaris sandbox, even
-	 * if we cant setuid, we can still do useful things and waive
-	 * most privileges.
-	 */
-	if (who == SANDBOX_TESTING)
-		exit(0);
-
-	mgt_sandbox_solaris_init(who);
-	mgt_sandbox_solaris_privsep(who);
-	mgt_sandbox_solaris_waive(who);
-}
-#endif /* HAVE_SETPPRIV */



More information about the varnish-commit mailing list