]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
service: new NotifyAccess= value for control processes (#4212) 4745/head
authorJouke Witteveen <j.witteveen@gmail.com>
Thu, 24 Nov 2016 09:56:32 +0000 (10:56 +0100)
committerJouke Witteveen <j.witteveen@gmail.com>
Tue, 29 Nov 2016 22:20:04 +0000 (23:20 +0100)
Setting NotifyAccess=exec allows notifications coming directly from any
control process.

man/systemd.service.xml
src/core/service.c
src/core/service.h

index 3ba6ab34dbbaa95a804ba6d75e2621be9fcd8294..67c68d2f8b5bcd7a98d0604691f38c81374a222e 100644 (file)
         notification socket, as accessible via the
         <citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>
         call. Takes one of <option>none</option> (the default),
-        <option>main</option> or <option>all</option>. If
-        <option>none</option>, no daemon status updates are accepted
-        from the service processes, all status update messages are
-        ignored. If <option>main</option>, only service updates sent
-        from the main process of the service are accepted. If
+        <option>main</option>, <option>exec</option> or
+        <option>all</option>. If <option>none</option>, no daemon status
+        updates are accepted from the service processes, all status
+        update messages are ignored. If <option>main</option>, only
+        service updates sent from the main process of the service are
+        accepted. If <option>exec</option>, only service updates sent
+        from any of the control processes originating from one of the
+        <varname>Exec*=</varname> commands are accepted. If
         <option>all</option>, all services updates from all members of
         the service's control group are accepted. This option should
         be set to open access to the notification socket when using
index bb67bdf84caa28b0bef037f7db0dac758059e03b..c68a7122b629573667a18dac55a363f4839f724b 100644 (file)
@@ -1179,6 +1179,25 @@ static int service_collect_fds(Service *s, int **fds, char ***fd_names) {
         return rn_fds;
 }
 
+static bool service_exec_needs_notify_socket(Service *s, ExecFlags flags) {
+        assert(s);
+
+        /* Notifications are accepted depending on the process and
+         * the access setting of the service:
+         *     process: \ access:  NONE  MAIN  EXEC   ALL
+         *     main                  no   yes   yes   yes
+         *     control               no    no   yes   yes
+         *     other (forked)        no    no    no   yes */
+
+        if (flags & EXEC_IS_CONTROL)
+                /* A control process */
+                return IN_SET(s->notify_access, NOTIFY_EXEC, NOTIFY_ALL);
+
+        /* We only spawn main processes and control processes, so any
+         * process that is not a control process is a main process */
+        return s->notify_access != NOTIFY_NONE;
+}
+
 static int service_spawn(
                 Service *s,
                 ExecCommand *c,
@@ -1252,7 +1271,7 @@ static int service_spawn(
         if (!our_env)
                 return -ENOMEM;
 
-        if ((flags & EXEC_IS_CONTROL) ? s->notify_access == NOTIFY_ALL : s->notify_access != NOTIFY_NONE)
+        if (service_exec_needs_notify_socket(s, flags))
                 if (asprintf(our_env + n_env++, "NOTIFY_SOCKET=%s", UNIT(s)->manager->notify_socket) < 0)
                         return -ENOMEM;
 
@@ -3061,7 +3080,18 @@ static void service_notify_message(Unit *u, pid_t pid, char **tags, FDSet *fds)
                 if (s->main_pid != 0)
                         log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid);
                 else
-                        log_unit_debug(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID which is currently not known", pid);
+                        log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID which is currently not known", pid);
+                return;
+        } else if (s->notify_access == NOTIFY_EXEC && pid != s->main_pid && pid != s->control_pid) {
+                if (s->main_pid != 0 && s->control_pid != 0)
+                        log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT" and control PID "PID_FMT,
+                                         pid, s->main_pid, s->control_pid);
+                else if (s->main_pid != 0)
+                        log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID "PID_FMT, pid, s->main_pid);
+                else if (s->control_pid != 0)
+                        log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for control PID "PID_FMT, pid, s->control_pid);
+                else
+                        log_unit_warning(u, "Got notification message from PID "PID_FMT", but reception only permitted for main PID and control PID which are currently not known", pid);
                 return;
         } else
                 log_unit_debug(u, "Got notification message from PID "PID_FMT" (%s)", pid, isempty(cc) ? "n/a" : cc);
@@ -3388,6 +3418,7 @@ DEFINE_STRING_TABLE_LOOKUP(service_exec_command, ServiceExecCommand);
 static const char* const notify_access_table[_NOTIFY_ACCESS_MAX] = {
         [NOTIFY_NONE] = "none",
         [NOTIFY_MAIN] = "main",
+        [NOTIFY_EXEC] = "exec",
         [NOTIFY_ALL] = "all"
 };
 
index 278cc1ceb8de5031189f321e8cbefae23781e887..e09722a952fd7da5148efb0c86049eef53afc504 100644 (file)
@@ -65,6 +65,7 @@ typedef enum NotifyAccess {
         NOTIFY_NONE,
         NOTIFY_ALL,
         NOTIFY_MAIN,
+        NOTIFY_EXEC,
         _NOTIFY_ACCESS_MAX,
         _NOTIFY_ACCESS_INVALID = -1
 } NotifyAccess;