[master] ddc3902 Separate sandboxing of child processes to a separate source file in order to encapsulate the lack of of API coordination between different OS's in this arena.

Poul-Henning Kamp phk at varnish-cache.org
Wed Mar 2 14:06:19 CET 2011


commit ddc3902f9418a4b6c0037872ac41dcf8e8abea1a
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Mar 2 13:05:24 2011 +0000

    Separate sandboxing of child processes to a separate source file
    in order to encapsulate the lack of of API coordination between
    different OS's in this arena.

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index b8db6e0..1ca60b9 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -57,6 +57,7 @@ varnishd_SOURCES = \
 	mgt_cli.c \
 	mgt_param.c \
 	mgt_pool.c \
+	mgt_sandbox.c \
 	mgt_shmem.c \
 	mgt_vcc.c \
 	rfc2616.c \
diff --git a/bin/varnishd/mgt.h b/bin/varnishd/mgt.h
index 122d384..a2dc912 100644
--- a/bin/varnishd/mgt.h
+++ b/bin/varnishd/mgt.h
@@ -71,6 +71,9 @@ void MCF_ParamSet(struct cli *, const char *param, const char *val);
 void MCF_DumpRst(void);
 #endif
 
+/* mgt_sandbox.c */
+void mgt_sandbox(void);
+
 /* mgt_shmem.c */
 void mgt_SHM_Init(const char *arg);
 void mgt_SHM_Pid(void);
diff --git a/bin/varnishd/mgt_child.c b/bin/varnishd/mgt_child.c
index 8ae55c8..d8cbc59 100644
--- a/bin/varnishd/mgt_child.c
+++ b/bin/varnishd/mgt_child.c
@@ -46,18 +46,10 @@ SVNID("$Id$")
 #include <sys/types.h>
 #include <sys/wait.h>
 
-#ifdef HAVE_PRIV_H
-#include <priv.h>
-#endif
-
 #ifndef HAVE_SETPROCTITLE
 #include "compat/setproctitle.h"
 #endif
 
-#ifdef __linux__
-#include <sys/prctl.h>
-#endif
-
 #include "mgt.h"
 #include "vsm.h"
 #include "heritage.h"
@@ -280,44 +272,6 @@ close_sockets(void)
 
 /*--------------------------------------------------------------------*/
 
-/* Waive all privileges in the child, it does not need any */
-
-static inline void
-waive_privileges(void)
-{
-
-#ifdef HAVE_SETPPRIV
-	priv_set_t *empty, *minimal;
-
-	if (!(empty = priv_allocset()) ||
-	    !(minimal = priv_allocset())) {
-		perror("priv_allocset_failed");
-		return;
-	}
-	priv_emptyset(empty);
-	priv_emptyset(minimal);
-
-	/* new privilege, silently ignore any errors if it doesn't exist */
-	priv_addset(minimal, "net_access");
-
-#define SETPPRIV(which, set)				       \
-	if (setppriv(PRIV_SET, which, set))		       \
-		perror("Waiving privileges failed on " #which)
-
-	/* need to set I after P to avoid SNOCD being set */
-	SETPPRIV(PRIV_LIMIT, minimal);
-	SETPPRIV(PRIV_PERMITTED, minimal); /* implies PRIV_EFFECTIVE */
-	SETPPRIV(PRIV_INHERITABLE, empty);
-
-	priv_freeset(empty);
-	priv_freeset(minimal);
-#else
-	return;
-#endif
-}
-
-/*--------------------------------------------------------------------*/
-
 static void
 start_child(struct cli *cli)
 {
@@ -370,19 +324,6 @@ start_child(struct cli *cli)
 		exit(1);
 	}
 	if (pid == 0) {
-		if (geteuid() == 0) {
-			XXXAZ(setgid(params->gid));
-			XXXAZ(setuid(params->uid));
-		}
-
-		/* On Linux >= 2.4, you need to set the dumpable flag
-		   to get core dumps after you have done a setuid. */
-#ifdef __linux__
-		if (prctl(PR_SET_DUMPABLE, 1) != 0) {
-		  printf("Could not set dumpable bit.  Core dumps turned "
-			 "off\n");
-		}
-#endif
 
 		/* Redirect stdin/out/err */
 		AZ(close(STDIN_FILENO));
@@ -397,14 +338,13 @@ start_child(struct cli *cli)
 				continue;
 			(void)(close(i) == 0);
 		}
-		printf("\n");
-
-		waive_privileges();
-
 		setproctitle("Varnish-Chld %s", heritage.name);
 
 		(void)signal(SIGINT, SIG_DFL);
 		(void)signal(SIGTERM, SIG_DFL);
+
+		mgt_sandbox();
+
 		child_main();
 
 		exit(1);
diff --git a/bin/varnishd/mgt_sandbox.c b/bin/varnishd/mgt_sandbox.c
new file mode 100644
index 0000000..c6ec1e8
--- /dev/null
+++ b/bin/varnishd/mgt_sandbox.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2006-2011 Linpro AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * 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
+ *
+ * The worker/manager process border is one of the major security barriers
+ * in Varnish, and therefore subject to whatever restrictions we have access
+ * to under the given operating system.
+ *
+ * Unfortunately there is no consensus on APIs for this purpose, so each
+ * operating system will require its own methods.
+ *
+ * This sourcefile tries to encapsulate the resulting mess on place.
+ *
+ * TODO:
+ *	Unix:	chroot
+ *	FreeBSD: jail
+ *	FreeBSD: capsicum
+ */
+
+#include "config.h"
+
+#include "svnid.h"
+SVNID("$Id$")
+
+#include <stdio.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#ifdef HAVE_PRIV_H
+#include <priv.h>
+#endif
+
+#ifndef HAVE_SETPROCTITLE
+#include "compat/setproctitle.h"
+#endif
+
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
+#include "mgt.h"
+#include "heritage.h"
+
+/*--------------------------------------------------------------------*/
+
+/* Waive all privileges in the child, it does not need any */
+
+void
+mgt_sandbox(void)
+{
+
+	if (geteuid() == 0) {
+		XXXAZ(setgid(params->gid));
+		XXXAZ(setuid(params->uid));
+	} else {
+		REPORT0(LOG_INFO, "Not running as root, no priv-sep");
+	}
+
+	/* On Linux >= 2.4, you need to set the dumpable flag
+	   to get core dumps after you have done a setuid. */
+
+#ifdef __linux__
+	if (prctl(PR_SET_DUMPABLE, 1) != 0)
+		REPORT0(LOG_INFO,
+		    "Could not set dumpable bit.  Core dumps turned off\n");
+#endif
+
+#ifdef HAVE_SETPPRIV
+	priv_set_t *empty, *minimal;
+
+	if (!(empty = priv_allocset()) ||
+	    !(minimal = priv_allocset())) {
+		REPORT0(LOG_ERR, "priv_allocset_failed");
+	} else {
+		priv_emptyset(empty);
+		priv_emptyset(minimal);
+
+		/*
+		 * new privilege,
+		 * silently ignore any errors if it doesn't exist
+		 */
+		priv_addset(minimal, "net_access");
+
+#define SETPPRIV(which, set)				       		\
+		if (setppriv(PRIV_SET, which, set))			\
+			REPORT0(LOG_ERR,				\
+			    "Waiving privileges failed on " #which)
+
+		/* need to set I after P to avoid SNOCD being set */
+		SETPPRIV(PRIV_LIMIT, minimal);
+		SETPPRIV(PRIV_PERMITTED, minimal); /* implies PRIV_EFFECTIVE */
+		SETPPRIV(PRIV_INHERITABLE, empty);
+
+		priv_freeset(empty);
+		priv_freeset(minimal);
+	}
+#endif
+
+}



More information about the varnish-commit mailing list