[master] ecae7e0 Drastically shorten the windows where we leave our sockets closed in order to prevent other processes from stealing them.

Poul-Henning Kamp phk at FreeBSD.org
Mon Mar 16 15:16:28 CET 2015


commit ecae7e0919b8adea09c542774727c8b21c1b08ea
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Mon Mar 16 14:15:35 2015 +0000

    Drastically shorten the windows where we leave our sockets closed
    in order to prevent other processes from stealing them.
    
    (We have to close & reopen when the client dies, there is no unlisten(2))

diff --git a/bin/varnishd/common/heritage.h b/bin/varnishd/common/heritage.h
index 0321e2b..949853b 100644
--- a/bin/varnishd/common/heritage.h
+++ b/bin/varnishd/common/heritage.h
@@ -37,8 +37,8 @@ struct listen_sock {
 #define LISTEN_SOCK_MAGIC		0x999e4b57
 	VTAILQ_ENTRY(listen_sock)	list;
 	int				sock;
-	char				*name;
-	struct suckaddr			*addr;
+	const char			*name;
+	const struct suckaddr		*addr;
 };
 
 VTAILQ_HEAD(listen_sock_head, listen_sock);
diff --git a/bin/varnishd/mgt/mgt.h b/bin/varnishd/mgt/mgt.h
index 9c23cd7..7f42f87 100644
--- a/bin/varnishd/mgt/mgt.h
+++ b/bin/varnishd/mgt/mgt.h
@@ -42,8 +42,8 @@ extern int		exit_status;
 /* mgt_acceptor.c */
 
 void MAC_Arg(const char *);
-int MAC_open_sockets(struct cli *);
-void MAC_close_sockets(void);
+void MAC_reopen_sockets(struct cli *);
+int MAC_sockets_ready(struct cli *);
 
 /* mgt_child.c */
 extern pid_t child_pid;
diff --git a/bin/varnishd/mgt/mgt_acceptor.c b/bin/varnishd/mgt/mgt_acceptor.c
index faa90ff..1d9aa47 100644
--- a/bin/varnishd/mgt/mgt_acceptor.c
+++ b/bin/varnishd/mgt/mgt_acceptor.c
@@ -49,51 +49,62 @@
 #include "vss.h"
 #include "vtcp.h"
 
+
+static int
+mac_opensocket(struct listen_sock *ls, struct cli *cli)
+{
+	int fail;
+
+	CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
+	if (ls->sock > 0) {
+		mgt_child_inherit(ls->sock, NULL);
+		AZ(close(ls->sock));
+	}
+	ls->sock = VTCP_bind(ls->addr, NULL);
+	fail = errno;
+	if (ls->sock >= 0)
+		mgt_child_inherit(ls->sock, "sock");
+	if (cli != NULL && ls->sock < 0) {
+		VCLI_Out(cli, "Could not get socket %s: %s\n",
+		    ls->name, strerror(errno));
+	}
+	return (fail);
+}
+
 /*=====================================================================
- * Open and close the accept sockets.
- *
- * (The child is priv-sep'ed, so it can't do it.)
+ * Reopen the accept sockets to get rid of listen status.
  */
 
-int
-MAC_open_sockets(struct cli *cli)
+void
+MAC_reopen_sockets(struct cli *cli)
 {
 	struct listen_sock *ls;
-	int fail;
 
 	VJ_master(JAIL_MASTER_PRIVPORT);
-	VTAILQ_FOREACH(ls, &heritage.socks, list) {
-		assert(ls->sock < 0);
-		ls->sock = VTCP_bind(ls->addr, NULL);
-		if (ls->sock < 0)
-			break;
-		mgt_child_inherit(ls->sock, "sock");
-	}
-	fail = errno;
+	VTAILQ_FOREACH(ls, &heritage.socks, list)
+		(void)mac_opensocket(ls, cli);
 	VJ_master(JAIL_MASTER_LOW);
-	if (ls == NULL)
-		return (0);
-	MAC_close_sockets();
-	VCLI_Out(cli, "Could not get socket %s: %s\n",
-	    ls->name, strerror(fail));
-	errno = fail;
-	return (-1);
 }
 
-/*--------------------------------------------------------------------*/
+/*=====================================================================
+ * Make sure we have all our sockets (and try once more to get them)
+ */
 
-void
-MAC_close_sockets(void)
+int
+MAC_sockets_ready(struct cli *cli)
 {
+	int retval = 1;
 	struct listen_sock *ls;
 
+	VJ_master(JAIL_MASTER_PRIVPORT);
 	VTAILQ_FOREACH(ls, &heritage.socks, list) {
 		if (ls->sock < 0)
-			continue;
-		mgt_child_inherit(ls->sock, NULL);
-		AZ(close(ls->sock));
-		ls->sock = -1;
+			(void)mac_opensocket(ls, cli);
+		if (ls->sock < 0)
+			retval = 0;
 	}
+	VJ_master(JAIL_MASTER_LOW);
+	return (retval);
 }
 
 /*--------------------------------------------------------------------*/
@@ -111,26 +122,29 @@ mac_callback(void *priv, const struct suckaddr *sa)
 {
 	struct mac_help *mh;
 	struct listen_sock *ls;
-	int sock;
+	int fail;
 	char abuf[VTCP_ADDRBUFSIZE], pbuf[VTCP_PORTBUFSIZE];
 	char nbuf[VTCP_ADDRBUFSIZE+VTCP_PORTBUFSIZE+2];
 
 	CAST_OBJ_NOTNULL(mh, priv, MAC_HELP_MAGIC);
-	sock = VTCP_bind(sa, NULL);
-	if (sock < 0) {
-		*(mh->err) = strerror(errno);
-		return (0);
-	}
 
 	ALLOC_OBJ(ls, LISTEN_SOCK_MAGIC);
 	AN(ls);
+	ls->sock = -1;
+	ls->addr = sa;
+	fail = mac_opensocket(ls, NULL);
+	if (ls->sock < 0) {
+		*(mh->err) = strerror(fail);
+		FREE_OBJ(ls);
+		return (0);
+	}
 	if (VSA_Port(sa) == 0) {
 		/*
 		 * If the port number is zero, we adopt whatever port number
 		 * this VTCP_bind() found us, as if specified by argument.
 		 */
-		ls->addr = VTCP_my_suckaddr(sock);
-		VTCP_myname(sock, abuf, sizeof abuf, pbuf, sizeof pbuf);
+		ls->addr = VTCP_my_suckaddr(ls->sock);
+		VTCP_myname(ls->sock, abuf, sizeof abuf, pbuf, sizeof pbuf);
 		bprintf(nbuf, "%s:%s", abuf, pbuf);
 		ls->name = strdup(nbuf);
 	} else {
@@ -139,8 +153,6 @@ mac_callback(void *priv, const struct suckaddr *sa)
 	}
 	AN(ls->addr);
 	AN(ls->name);
-	AZ(close(sock));
-	ls->sock = -1;
 	VTAILQ_INSERT_TAIL(&heritage.socks, ls, list);
 	mh->good++;
 	return (0);
diff --git a/bin/varnishd/mgt/mgt_child.c b/bin/varnishd/mgt/mgt_child.c
index eca8af2..c8f92ea 100644
--- a/bin/varnishd/mgt/mgt_child.c
+++ b/bin/varnishd/mgt/mgt_child.c
@@ -303,7 +303,7 @@ mgt_launch_child(struct cli *cli)
 	if (child_state != CH_STOPPED && child_state != CH_DIED)
 		return;
 
-	if (MAC_open_sockets(cli) != 0) {
+	if (!MAC_sockets_ready(cli)) {
 		child_state = CH_STOPPED;
 		if (cli != NULL) {
 			VCLI_SetResult(cli, CLIS_CANT);
@@ -393,7 +393,7 @@ mgt_launch_child(struct cli *cli)
 	mgt_child_inherit(heritage.cli_out, NULL);
 	closex(&heritage.cli_out);
 
-	MAC_close_sockets();
+	MAC_reopen_sockets(cli);
 
 	child_std_vlu = VLU_New(NULL, child_line, 0);
 	AN(child_std_vlu);



More information about the varnish-commit mailing list