Commit ecae7e09 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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))
parent 3e53135c
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment