1ff636
From 5d66d4942090a971de8df2c3de9ce143a208eb37 Mon Sep 17 00:00:00 2001
1ff636
From: Michal Schmidt <mschmidt@redhat.com>
1ff636
Date: Thu, 19 Feb 2015 23:12:38 +0100
1ff636
Subject: [PATCH] core, shared: in deserializing, match same files reached via
1ff636
 different paths
1ff636
1ff636
When dbus.socket is updated like this:
1ff636
-ListenStream=/var/run/dbus/system_bus_socket
1ff636
+ListenStream=/run/dbus/system_bus_socket
1ff636
... and daemon-reload is performed, bad things happen.
1ff636
During deserialization systemd does not recognize that the two paths
1ff636
refer to the same named socket and replaces the socket file with a new
1ff636
one. As a result, applications hang when they try talking to dbus.
1ff636
1ff636
Fix this by finding a match not only when the path names are equal, but
1ff636
also when they point to the same inode.
1ff636
In socket_address_equal() it is necessary to move the address size
1ff636
comparison into the abstract sockets branch. For path name sockets the
1ff636
comparison must not be done and for other families it is redundant
1ff636
(their sizes are constant and checked by socket_address_verify()).
1ff636
1ff636
FIFOs and special files can also have multiple pathnames, so compare the
1ff636
inodes for them as well. Note that previously the pathname checks used
1ff636
streq_ptr(), but the paths cannot be NULL.
1ff636
1ff636
Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1186018
1ff636
(cherry picked from commit c78e47a61fa8d9a21fece01c83e4c26ce0938d27)
1ff636
---
1ff636
 src/core/socket.c        |  6 +++---
1ff636
 src/shared/path-util.c   |  4 ++++
1ff636
 src/shared/path-util.h   |  1 +
1ff636
 src/shared/socket-util.c | 10 ++++------
1ff636
 4 files changed, 12 insertions(+), 9 deletions(-)
1ff636
1ff636
diff --git a/src/core/socket.c b/src/core/socket.c
Pablo Greco 48fc63
index 48c43a2880..88aae4815b 100644
1ff636
--- a/src/core/socket.c
1ff636
+++ b/src/core/socket.c
1ff636
@@ -2100,7 +2100,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
1ff636
 
1ff636
                         LIST_FOREACH(port, p, s->ports)
1ff636
                                 if (p->type == SOCKET_FIFO &&
1ff636
-                                    streq_ptr(p->path, value+skip))
1ff636
+                                    path_equal_or_files_same(p->path, value+skip))
1ff636
                                         break;
1ff636
 
1ff636
                         if (p) {
1ff636
@@ -2119,7 +2119,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
1ff636
 
1ff636
                         LIST_FOREACH(port, p, s->ports)
1ff636
                                 if (p->type == SOCKET_SPECIAL &&
1ff636
-                                    streq_ptr(p->path, value+skip))
1ff636
+                                    path_equal_or_files_same(p->path, value+skip))
1ff636
                                         break;
1ff636
 
1ff636
                         if (p) {
1ff636
@@ -2138,7 +2138,7 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
1ff636
 
1ff636
                         LIST_FOREACH(port, p, s->ports)
1ff636
                                 if (p->type == SOCKET_MQUEUE &&
1ff636
-                                    streq_ptr(p->path, value+skip))
1ff636
+                                    streq(p->path, value+skip))
1ff636
                                         break;
1ff636
 
1ff636
                         if (p) {
1ff636
diff --git a/src/shared/path-util.c b/src/shared/path-util.c
Pablo Greco 48fc63
index b9db7f1047..70bc1caa2a 100644
1ff636
--- a/src/shared/path-util.c
1ff636
+++ b/src/shared/path-util.c
1ff636
@@ -436,6 +436,10 @@ bool path_equal(const char *a, const char *b) {
1ff636
         }
1ff636
 }
1ff636
 
1ff636
+bool path_equal_or_files_same(const char *a, const char *b) {
1ff636
+        return path_equal(a, b) || files_same(a, b) > 0;
1ff636
+}
1ff636
+
1ff636
 char* path_join(const char *root, const char *path, const char *rest) {
1ff636
         assert(path);
1ff636
 
1ff636
diff --git a/src/shared/path-util.h b/src/shared/path-util.h
Pablo Greco 48fc63
index bd0d32473f..bcf116ed3d 100644
1ff636
--- a/src/shared/path-util.h
1ff636
+++ b/src/shared/path-util.h
1ff636
@@ -45,6 +45,7 @@ int path_make_relative(const char *from_dir, const char *to_path, char **_r);
1ff636
 char* path_kill_slashes(char *path);
1ff636
 char* path_startswith(const char *path, const char *prefix) _pure_;
1ff636
 bool path_equal(const char *a, const char *b) _pure_;
1ff636
+bool path_equal_or_files_same(const char *a, const char *b);
1ff636
 char* path_join(const char *root, const char *path, const char *rest);
1ff636
 
1ff636
 char** path_strv_make_absolute_cwd(char **l);
1ff636
diff --git a/src/shared/socket-util.c b/src/shared/socket-util.c
Pablo Greco 48fc63
index c6f64876be..c278d6f9d4 100644
1ff636
--- a/src/shared/socket-util.c
1ff636
+++ b/src/shared/socket-util.c
1ff636
@@ -325,9 +325,6 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
1ff636
         if (a->type != b->type)
1ff636
                 return false;
1ff636
 
1ff636
-        if (a->size != b->size)
1ff636
-                return false;
1ff636
-
1ff636
         if (socket_address_family(a) != socket_address_family(b))
1ff636
                 return false;
1ff636
 
1ff636
@@ -352,14 +349,16 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
1ff636
                 break;
1ff636
 
1ff636
         case AF_UNIX:
1ff636
-
1ff636
                 if ((a->sockaddr.un.sun_path[0] == 0) != (b->sockaddr.un.sun_path[0] == 0))
1ff636
                         return false;
1ff636
 
1ff636
                 if (a->sockaddr.un.sun_path[0]) {
1ff636
-                        if (!strneq(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, sizeof(a->sockaddr.un.sun_path)))
1ff636
+                        if (!path_equal_or_files_same(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path))
1ff636
                                 return false;
1ff636
                 } else {
1ff636
+                        if (a->size != b->size)
1ff636
+                                return false;
1ff636
+
1ff636
                         if (memcmp(a->sockaddr.un.sun_path, b->sockaddr.un.sun_path, a->size) != 0)
1ff636
                                 return false;
1ff636
                 }
1ff636
@@ -367,7 +366,6 @@ bool socket_address_equal(const SocketAddress *a, const SocketAddress *b) {
1ff636
                 break;
1ff636
 
1ff636
         case AF_NETLINK:
1ff636
-
1ff636
                 if (a->protocol != b->protocol)
1ff636
                         return false;
1ff636