]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pidref: add pidref_verify() helper
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Sep 2023 14:22:29 +0000 (16:22 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 28 Sep 2023 21:22:58 +0000 (23:22 +0200)
This new helper can be used after reading process info from procfs, to
verify that the data that was just read actually matches the pidfd, and
does not belong to some new process that just reused the numeric PID of
the process we originally pinned.

src/basic/pidref.c
src/basic/pidref.h

index 02d6832bd085b806179e79bf3b6d435b4983edb9..a9fbbf2c9061d832917df60215c8ccc3c63d6956 100644 (file)
@@ -240,6 +240,26 @@ int pidref_sigqueue(PidRef *pidref, int sig, int value) {
         return -ESRCH;
 }
 
         return -ESRCH;
 }
 
+int pidref_verify(PidRef *pidref) {
+        int r;
+
+        /* This is a helper that is supposed to be called after reading information from procfs via a
+         * PidRef. It ensures that the PID we track still matches the PIDFD we pin. If this value differs
+         * after a procfs read, we might have read the data from a recycled PID. */
+
+        if (!pidref_is_set(pidref))
+                return -ESRCH;
+
+        if (pidref->fd < 0)
+                return 0; /* If we don't have a pidfd we cannot validate it, hence we assume it's all OK → return 0 */
+
+        r = pidfd_verify_pid(pidref->fd, pidref->pid);
+        if (r < 0)
+                return r;
+
+        return 1; /* We have a pidfd and it still points to the PID we have, hence all is *really* OK → return 1 */
+}
+
 static void pidref_hash_func(const PidRef *pidref, struct siphash *state) {
         siphash24_compress(&pidref->pid, sizeof(pidref->pid), state);
 }
 static void pidref_hash_func(const PidRef *pidref, struct siphash *state) {
         siphash24_compress(&pidref->pid, sizeof(pidref->pid), state);
 }
index 835bafc96e44c70b959e5167010b370dd461cf3f..89f43157bac9ff786dc19e60e0fca892858254fb 100644 (file)
@@ -51,6 +51,8 @@ int pidref_kill(PidRef *pidref, int sig);
 int pidref_kill_and_sigcont(PidRef *pidref, int sig);
 int pidref_sigqueue(PidRef *pidfref, int sig, int value);
 
 int pidref_kill_and_sigcont(PidRef *pidref, int sig);
 int pidref_sigqueue(PidRef *pidfref, int sig, int value);
 
+int pidref_verify(PidRef *pidref);
+
 #define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
 
 extern const struct hash_ops pidref_hash_ops; /* Has destructor call for pidref_free(), i.e. expects heap allocated PidRef as keys */
 #define TAKE_PIDREF(p) TAKE_GENERIC((p), PidRef, PIDREF_NULL)
 
 extern const struct hash_ops pidref_hash_ops; /* Has destructor call for pidref_free(), i.e. expects heap allocated PidRef as keys */