pidref: hookup PID_AUTOMATIC special pid_t value with PidRef
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.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+12
-2
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user