File fix-socket-crash.patch of Package systemd.openSUSE_12.1_Update
From a3416e3a6332e21840bcc284acc436116385b041 Mon Sep 17 00:00:00 2001
From: Michal Schmidt <mschmidt@redhat.com>
Date: Fri, 20 Jan 2012 23:44:22 +0100
Subject: [PATCH 1/3] socket: don't fail the socket on ENOTCONN
Albert Strasheim reported a socket unit with Accept=yes was failing
sometimes.
getpeername() returns ENOTCONN if the connection was killed by TCP RST.
The socket unit must not fail when it happens.
Reproducer available at:
https://bugzilla.redhat.com/show_bug.cgi?id=783344
---
src/socket.c | 36 ++++++++++++++++++++++++++----------
1 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/src/socket.c b/src/socket.c
index 7ddf326..a427b12 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1350,7 +1350,8 @@ static void socket_enter_running(Socket *s, int cfd) {
/* Flush all sockets by closing and reopening them */
socket_close_fds(s);
- if ((r = socket_watch_fds(s)) < 0) {
+ r = socket_watch_fds(s);
+ if (r < 0) {
log_warning("%s failed to watch sockets: %s", s->meta.id, strerror(-r));
socket_enter_stop_pre(s, false);
}
@@ -1378,9 +1379,11 @@ static void socket_enter_running(Socket *s, int cfd) {
break;
}
- if (!pending)
- if ((r = manager_add_job(s->meta.manager, JOB_START, UNIT(s->service), JOB_REPLACE, true, &error, NULL)) < 0)
+ if (!pending) {
+ r = manager_add_job(s->meta.manager, JOB_START, UNIT(s->service), JOB_REPLACE, true, &error, NULL);
+ if (r < 0)
goto fail;
+ }
socket_set_state(s, SOCKET_RUNNING);
} else {
@@ -1393,13 +1396,23 @@ static void socket_enter_running(Socket *s, int cfd) {
return;
}
- if ((r = socket_instantiate_service(s)) < 0)
+ r = socket_instantiate_service(s);
+ if (r < 0)
goto fail;
- if ((r = instance_from_socket(cfd, s->n_accepted, &instance)) < 0)
- goto fail;
+ r = instance_from_socket(cfd, s->n_accepted, &instance);
+ if (r < 0) {
+ if (r != -ENOTCONN)
+ goto fail;
+
+ /* ENOTCONN is legitimate if TCP RST was received.
+ * This connection is over, but the socket unit lives on. */
+ close_nointr_nofail(cfd);
+ return;
+ }
- if (!(prefix = unit_name_to_prefix(s->meta.id))) {
+ prefix = unit_name_to_prefix(s->meta.id);
+ if (!prefix) {
free(instance);
r = -ENOMEM;
goto fail;
@@ -1414,7 +1427,8 @@ static void socket_enter_running(Socket *s, int cfd) {
goto fail;
}
- if ((r = unit_add_name(UNIT(s->service), name)) < 0) {
+ r = unit_add_name(UNIT(s->service), name);
+ if (r < 0) {
free(name);
goto fail;
}
@@ -1428,13 +1442,15 @@ static void socket_enter_running(Socket *s, int cfd) {
unit_choose_id(UNIT(service), name);
free(name);
- if ((r = service_set_socket_fd(service, cfd, s)) < 0)
+ r = service_set_socket_fd(service, cfd, s);
+ if (r < 0)
goto fail;
cfd = -1;
s->n_connections ++;
- if ((r = manager_add_job(s->meta.manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL)) < 0)
+ r = manager_add_job(s->meta.manager, JOB_START, UNIT(service), JOB_REPLACE, true, &error, NULL);
+ if (r < 0)
goto fail;
/* Notify clients about changed counters */
--
1.7.7
From 63e4f26fa52cd89b26229ef042f4c0c650f9c8dc Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 14 Mar 2012 03:01:27 +0100
Subject: [PATCH 2/3] socket: if we fail to create an instantiated service for
a socket, don't put the socket in failure mode
An incoming connection that is immediately terminated might result in
getpeername() or a similar call failing. Hence it is quite possible that
while we are setting up an instantiated service for a socket we might
get an error and we shouldn't take this as hint to take the listening
socket down.
https://bugs.freedesktop.org/show_bug.cgi?id=45297
https://bugzilla.novell.com/show_bug.cgi?id=741590
---
src/socket.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/src/socket.c b/src/socket.c
index a427b12..a7f206f 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1461,7 +1461,6 @@ static void socket_enter_running(Socket *s, int cfd) {
fail:
log_warning("%s failed to queue socket startup job: %s", s->meta.id, bus_error(&error, r));
- socket_enter_stop_pre(s, false);
if (cfd >= 0)
close_nointr_nofail(cfd);
--
1.7.7
From 509e4e6bb6e8d8b9f701025673b5306d693955b0 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Wed, 14 Mar 2012 03:07:26 +0100
Subject: [PATCH 3/3] socket: make sure that the name for per-connection
services are unique
If a client connects to us repeatedly always using the same source port
and we instantiate a service for the incoming connection this might
clash with an old instance. Hence, include the connection number, the
same way we do it for AF_UNIX to make connections unique.
https://bugs.freedesktop.org/show_bug.cgi?id=45297
---
src/socket.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/socket.c b/src/socket.c
index a7f206f..1c1d1a4 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -549,7 +549,8 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
b = ntohl(remote.in.sin_addr.s_addr);
if (asprintf(&r,
- "%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
+ "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
+ nr,
a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,
ntohs(local.in.sin_port),
b >> 24, (b >> 16) & 0xFF, (b >> 8) & 0xFF, b & 0xFF,
@@ -571,7 +572,8 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
*b = remote.in6.sin6_addr.s6_addr+12;
if (asprintf(&r,
- "%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
+ "%u-%u.%u.%u.%u:%u-%u.%u.%u.%u:%u",
+ nr,
a[0], a[1], a[2], a[3],
ntohs(local.in6.sin6_port),
b[0], b[1], b[2], b[3],
@@ -581,7 +583,8 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) {
char a[INET6_ADDRSTRLEN], b[INET6_ADDRSTRLEN];
if (asprintf(&r,
- "%s:%u-%s:%u",
+ "%u-%s:%u-%s:%u",
+ nr,
inet_ntop(AF_INET6, &local.in6.sin6_addr, a, sizeof(a)),
ntohs(local.in6.sin6_port),
inet_ntop(AF_INET6, &remote.in6.sin6_addr, b, sizeof(b)),
--
1.7.7