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

openSUSE Build Service is sponsored by