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