Blob Blame History Raw
From c7ba28481495df54477c54ee14bb6e7737ef772b Mon Sep 17 00:00:00 2001
From: Franck Bui <fbui@suse.com>
Date: Thu, 29 Sep 2016 19:44:34 +0200
Subject: [PATCH] pid1: don't return any error in manager_dispatch_notify_fd()
 (#4240)

If manager_dispatch_notify_fd() fails and returns an error then the handling of
service notifications will be disabled entirely leading to a compromised system.

For example pid1 won't be able to receive the WATCHDOG messages anymore and
will kill all services supposed to send such messages.
(cherry picked from commit 9987750e7a4c62e0eb8473603150596ba7c3a015)

(cherry picked from commit 39e5e97e68a9c1bca3bcfa6c9316a83dad0b072d)
---
 src/core/manager.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/src/core/manager.c b/src/core/manager.c
index 6bd32ed920..5092b1c5f6 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -1552,10 +1552,14 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
 
         n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
         if (n < 0) {
-                if (errno == EAGAIN || errno == EINTR)
-                        return 0;
+                if (!IN_SET(errno, EAGAIN, EINTR))
+                        log_error("Failed to receive notification message: %m");
 
-                return -errno;
+                /* It's not an option to return an error here since it
+                 * would disable the notification handler entirely. Services
+                 * wouldn't be able to send the WATCHDOG message for
+                 * example... */
+                return 0;
         }
         if (n == 0) {
                 log_debug("Got zero-length notification message. Ignoring.");
@@ -1582,7 +1586,8 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
                 r = fdset_new_array(&fds, fd_array, n_fds);
                 if (r < 0) {
                         close_many(fd_array, n_fds);
-                        return log_oom();
+                        log_oom();
+                        return 0;
                 }
         }