]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
pidref: hookup PID_AUTOMATIC special pid_t value with PidRef
authorLennart Poettering <lennart@poettering.net>
Mon, 14 Oct 2024 10:31:57 +0000 (12:31 +0200)
committerLennart Poettering <lennart@poettering.net>
Mon, 14 Oct 2024 10:44:36 +0000 (12:44 +0200)
The PID_AUTOMATIC value is now properly recognized by the PidRef logic
too. This needed some massaging of header includes, to ensure pidref.h
can access process-util.h's definitions and vice versa.

src/basic/namespace-util.h
src/basic/pidref.c
src/basic/pidref.h
src/basic/process-util.h
src/libsystemd/sd-json/json-util.c
src/test/test-pidref.c

index 0a7616443dbe161c86a5bd69dbf4266b8c8bdb56..c9e1da39ab4e4f70141646f829c91bf7bd4d74fe 100644 (file)
@@ -3,9 +3,11 @@
 
 #include <sys/types.h>
 
+typedef enum NamespaceType NamespaceType;
+
 #include "pidref.h"
 
-typedef enum NamespaceType {
+enum NamespaceType {
         NAMESPACE_CGROUP,
         NAMESPACE_IPC,
         NAMESPACE_NET,
@@ -16,7 +18,7 @@ typedef enum NamespaceType {
         NAMESPACE_TIME,
         _NAMESPACE_TYPE_MAX,
         _NAMESPACE_TYPE_INVALID = -EINVAL,
-} NamespaceType;
+};
 
 extern const struct namespace_info {
         const char *proc_name;
index 8529236c5ec80ec303840b83485a9b301e1e7264..1defe863e2b3e6ade74f2a3abafb371ac6bae1fe 100644 (file)
@@ -428,6 +428,10 @@ int pidref_wait_for_terminate(const PidRef *pidref, siginfo_t *ret) {
         }
 }
 
+bool pidref_is_automatic(const PidRef *pidref) {
+        return pidref && pid_is_automatic(pidref->pid);
+}
+
 static void pidref_hash_func(const PidRef *pidref, struct siphash *state) {
         siphash24_compress_typesafe(pidref->pid, state);
 }
index 4738c6eb5d50032f7c0cec57c090b1125e31e066..8647f4bd23bf489c473a2d4f91fe5633ba22c3e4 100644 (file)
@@ -1,18 +1,26 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+typedef struct PidRef PidRef;
+
 #include "macro.h"
+#include "process-util.h"
 
 /* An embeddable structure carrying a reference to a process. Supposed to be used when tracking processes continuously. */
-typedef struct PidRef {
+struct PidRef {
         pid_t pid;      /* always valid */
         int fd;         /* only valid if pidfd are available in the kernel, and we manage to get an fd */
         uint64_t fd_id; /* the inode number of pidfd. only useful in kernel 6.9+ where pidfds live in
                            their own pidfs and each process comes with a unique inode number */
-} PidRef;
+};
 
 #define PIDREF_NULL (const PidRef) { .fd = -EBADF }
 
+/* A special pidref value that we are using when a PID shall be automatically acquired from some surrounding
+ * context, for example connection peer. Much like PIDREF_NULL it will be considerd unset by
+ * pidref_is_set().*/
+#define PIDREF_AUTOMATIC (const PidRef) { .pid = PID_AUTOMATIC, .fd = -EBADF }
+
 /* Turns a pid_t into a PidRef structure on-the-fly *without* acquiring a pidfd for it. (As opposed to
  * pidref_set_pid() which does so *with* acquiring one, see below) */
 #define PIDREF_MAKE_FROM_PID(x) (PidRef) { .pid = (x), .fd = -EBADF }
@@ -21,6 +29,8 @@ static inline bool pidref_is_set(const PidRef *pidref) {
         return pidref && pidref->pid > 0;
 }
 
+bool pidref_is_automatic(const PidRef *pidref);
+
 int pidref_acquire_pidfd_id(PidRef *pidref);
 bool pidref_equal(PidRef *a, PidRef *b);
 
index 2efe89e1359a633fac558cfe0259a796543cf505..c282df7701e7901bcfa245ac9f18934f783d454e 100644 (file)
@@ -15,6 +15,7 @@
 #include "format-util.h"
 #include "macro.h"
 #include "namespace-util.h"
+#include "pidref.h"
 #include "time-util.h"
 
 #define procfs_file_alloca(pid, field)                                  \
@@ -148,7 +149,7 @@ static inline bool sched_priority_is_valid(int i) {
         return i >= 0 && i <= sched_get_priority_max(SCHED_RR);
 }
 
-#define PID_AUTOMATIC ((pid_t) INT_MIN) /* special value indicating "acquire pid from connection peer */
+#define PID_AUTOMATIC ((pid_t) INT_MIN) /* special value indicating "acquire pid from connection peer" */
 #define PID_INVALID   ((pid_t) 0)       /* default value for "invalid pid" */
 
 static inline bool pid_is_valid(pid_t p) {
index 2ff4587565407e6c7ca14e4034b9f5d9e003d553..0c1dea566af22f51d7547a5434399f6c514f70e0 100644 (file)
@@ -185,7 +185,13 @@ int json_dispatch_pidref(const char *name, sd_json_variant *variant, sd_json_dis
          * above. If SD_JSON_STRICT is set this will acquire a pidfd for the process, and validate that the
          * auxiliary fields match it. Otherwise, this will just store the pid and the pidfd inode number (the
          * latter not if the provided boot id differs from the local one), and not attempt to get a pidfd for
-         * it, or authenticate it. */
+         * it, or authenticate it.
+         *
+         * If SD_JSON_RELAX is specified, a specified but zero/empty PID will be mapped to PIDREF_AUTOMATIC,
+         * which is supposed to indicate that the PID shall be automatically derived, typically from the
+         * connection peer.
+         *
+         * Note that SD_JSON_RELAX and SD_JSON_STRICT can be combined. */
 
         if (sd_json_variant_is_null(variant)) {
                 pidref_done(p);
@@ -220,6 +226,13 @@ int json_dispatch_pidref(const char *name, sd_json_variant *variant, sd_json_dis
         } else
                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' is neither a numeric PID nor a PID object.", strna(name));
 
+        /* If SD_JSON_RELAX is set then we'll take a specified but zero field as request for "automic" PID derivation */
+        if ((flags & SD_JSON_RELAX) && data.pid == 0 && data.fd_id == 0 && sd_id128_is_null(data.boot_id)) {
+                pidref_done(p);
+                *p = PIDREF_AUTOMATIC;
+                return 0;
+        }
+
         /* Before casting the 64bit data.pid field to pid_t, let's ensure it fits the pid_t range. */
         if (data.pid > PID_T_MAX || !pid_is_valid(data.pid))
                 return json_log(variant, flags, SYNTHETIC_ERRNO(EINVAL), "JSON field '%s' does not contain a valid PID.", strna(name));
index 53ed10d15374086c6ba1feaa86f8397c3b4d6195..7298b36596805f29d2ebcee362db82bddaf98f88 100644 (file)
@@ -224,4 +224,20 @@ TEST(pidref_verify) {
         assert_se(pidref_verify(&pidref) == (pidref.fd >= 0));
 }
 
+TEST(pidref_is_automatic) {
+        assert_se(!pidref_is_automatic(NULL));
+        assert_se(!pidref_is_automatic(&PIDREF_NULL));
+        assert_se(!pidref_is_automatic(&PIDREF_MAKE_FROM_PID(1)));
+        assert_se(!pidref_is_automatic(&PIDREF_MAKE_FROM_PID(getpid_cached())));
+        assert_se(pidref_is_automatic(&PIDREF_AUTOMATIC));
+
+        assert_se(!pid_is_automatic(0));
+        assert_se(!pid_is_automatic(1));
+        assert_se(!pid_is_automatic(getpid_cached()));
+        assert_se(pid_is_automatic(PID_AUTOMATIC));
+
+        assert_se(!pidref_is_set(&PIDREF_AUTOMATIC));
+        assert_se(!pid_is_valid(PID_AUTOMATIC));
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);