]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
notify: add support for MANAGERPIDFDID
authorLennart Poettering <lennart@poettering.net>
Sun, 19 Jan 2025 20:43:43 +0000 (21:43 +0100)
committerLennart Poettering <lennart@poettering.net>
Mon, 20 Jan 2025 20:51:40 +0000 (21:51 +0100)
src/notify/notify.c

index 6afb9560c659642c7f6a728a70dd148bb0305a83..1c5b5e7be3d647022c76bfc7b5e3a193fd4d06d4 100644 (file)
@@ -80,28 +80,49 @@ static int help(void) {
         return 0;
 }
 
-static pid_t manager_pid(void) {
-        const char *e;
-        pid_t pid;
+static int get_manager_pid(PidRef *ret) {
         int r;
 
+        assert(ret);
+
         /* If we run as a service managed by systemd --user the $MANAGERPID environment variable points to
          * the service manager's PID. */
-        e = getenv("MANAGERPID");
-        if (!e)
+        const char *e = getenv("MANAGERPID");
+        if (!e) {
+                *ret = PIDREF_NULL;
                 return 0;
+        }
 
-        r = parse_pid(e, &pid);
-        if (r < 0) {
-                log_warning_errno(r, "$MANAGERPID is set to an invalid PID, ignoring: %s", e);
-                return 0;
+        _cleanup_(pidref_done) PidRef manager = PIDREF_NULL;
+        r = pidref_set_pidstr(&manager, e);
+        if (r < 0)
+                return log_warning_errno(r, "$MANAGERPID is set to an invalid PID, ignoring: %s", e);
+
+        e = getenv("MANAGERPIDFDID");
+        if (e) {
+                uint64_t manager_pidfd_id;
+
+                r = safe_atou64(e, &manager_pidfd_id);
+                if (r < 0)
+                        return log_warning_errno(r, "$MANAGERPIDFDID is not set to a valid inode number, ignoring: %s", e);
+
+                r = pidref_acquire_pidfd_id(&manager);
+                if (r < 0)
+                        return log_warning_errno(r, "Unable to acquire pidfd ID for manager: %m");
+
+                if (manager_pidfd_id != manager.fd_id) {
+                        log_debug("$MANAGERPIDFDID doesn't match process currently referenced by $MANAGERPID, suppressing.");
+                        *ret = PIDREF_NULL;
+                        return 0;
+                }
         }
 
-        return pid;
+        *ret = TAKE_PIDREF(manager);
+        return 1;
 }
 
 static int pidref_parent_if_applicable(PidRef *ret) {
-        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
+        _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL, manager = PIDREF_NULL;
         int r;
 
         assert(ret);
@@ -112,12 +133,18 @@ static int pidref_parent_if_applicable(PidRef *ret) {
 
         /* Don't send from PID 1 or the service manager's PID (which might be distinct from 1, if we are a
          * --user service). That'd just be confusing for the service manager. */
-        if (pidref.pid <= 1 ||
-            pidref.pid == manager_pid())
-                return pidref_set_self(ret);
+        if (pidref.pid == 1)
+                goto from_self;
+
+        r = get_manager_pid(&manager);
+        if (r > 0 && pidref_equal(&pidref, &manager))
+                goto from_self;
 
         *ret = TAKE_PIDREF(pidref);
         return 0;
+
+from_self:
+        return pidref_set_self(ret);
 }
 
 static int parse_argv(int argc, char *argv[]) {