[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