A prior patch highlighted the following leak: whenever any construction
step after bind() fails, the UNIX domain socket address (i.e., the
pathname in the filesystem) is leaked. Plug the leak by inserting a new
error handling section that unlinks the pathname.
Signed-off-by: Laszlo Ersek <lersek(a)redhat.com>
Reviewed-by: Richard W.M. Jones <rjones(a)redhat.com>
---
Notes:
v4:
- pick up Rich's R-b
- resolve rebase conflict near the
prepare_socket_activation_environment() call site, due to keeping
set_error() internal to that callee, in patch "socket activation:
clean up responsibilities of prep.sock.act.env.()"
context:-U12
generator/states-connect-socket-activation.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/generator/states-connect-socket-activation.c
b/generator/states-connect-socket-activation.c
index b20c3f1f10bb..752ee73bb62f 100644
--- a/generator/states-connect-socket-activation.c
+++ b/generator/states-connect-socket-activation.c
@@ -137,30 +137,30 @@ CONNECT_SA.START:
goto free_sockpath;
}
addr.sun_family = AF_UNIX;
memcpy (addr.sun_path, sockpath, strlen (sockpath) + 1);
if (bind (s, (struct sockaddr *) &addr, sizeof addr) == -1) {
set_error (errno, "bind: %s", sockpath);
goto close_socket;
}
if (listen (s, SOMAXCONN) == -1) {
set_error (errno, "listen");
- goto close_socket;
+ goto unlink_sockpath;
}
if (prepare_socket_activation_environment (&env) == -1)
/* prepare_socket_activation_environment() calls set_error() internally */
- goto close_socket;
+ goto unlink_sockpath;
pid = fork ();
if (pid == -1) {
set_error (errno, "fork");
goto empty_env;
}
if (pid == 0) { /* child - run command */
if (s != FIRST_SOCKET_ACTIVATION_FD) {
if (dup2 (s, FIRST_SOCKET_ACTIVATION_FD) == -1) {
nbd_internal_fork_safe_perror ("dup2");
_exit (126);
@@ -211,24 +211,28 @@ CONNECT_SA.START:
h->sact_sockpath = sockpath;
h->pid = pid;
h->connaddrlen = sizeof addr;
memcpy (&h->connaddr, &addr, h->connaddrlen);
next = %^CONNECT.START;
/* fall through, for releasing the temporaries */
empty_env:
string_vector_empty (&env);
+unlink_sockpath:
+ if (next == %.DEAD)
+ unlink (sockpath);
+
close_socket:
close (s);
free_sockpath:
if (next == %.DEAD)
free (sockpath);
rmdir_tmpdir:
if (next == %.DEAD)
rmdir (tmpdir);
free_tmpdir: