pidref: add explicit concept of "remote" PidRef
This PidRef just track some data, but cannot be used for any active operation. Background: for https://github.com/systemd/systemd/pull/34703 it makes sense to track explicitly if some PidRef is not a local one, so that we never attempt to for example "kill a remote process" and thus acccidentally hit the wrong process (i.e. a local one by the same PID).
This commit is contained in:
+34
-3
@@ -6,10 +6,35 @@ 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. */
|
||||
/* An embeddable structure carrying a reference to a process. Supposed to be used when tracking processes
|
||||
* continuously. This combines a PID, a modern Linux pidfd and the 64bit inode number of the pidfd into one
|
||||
* structure. Note that depending on kernel support the pidfd might not be initialized, and if it is
|
||||
* initialized then fd_id might still not be initialized (because the concept was added to the kernel much
|
||||
* later than pidfds themselves).
|
||||
*
|
||||
* There are three special states a PidRef can be in:
|
||||
*
|
||||
* 1. It can be *unset*. Use pidref_is_set() to detect this case. Most operations attempted on such a PidRef
|
||||
* will fail with -ESRCH. Use PIDREF_NULL for initializing a PidRef in this state.
|
||||
*
|
||||
* 2. It can be marked as *automatic*. This is a special state indicating that a process reference is
|
||||
* supposed to be derived automatically from the current context. This is used by the Varlink/JSON
|
||||
* dispatcher as indication that a PidRef shall be derived from the connection peer, but might be
|
||||
* otherwise used too. When marked *automatic* the PidRef will also be considered *unset*, hence most
|
||||
* operations will fail with -ESRCH, as above.
|
||||
*
|
||||
* 3. It can be marked as *remote*. This is useful when deserializing a PidRef structure from an IPC message
|
||||
* or similar, and it has been determined that the given PID definitely doesn't refer to a local
|
||||
* process. In this case the PidRef logic will refrain from trying to acquire a pidfd for the
|
||||
* process. Moreover, most operations will fail with -EREMOTE. Only PidRef structures that are not marked
|
||||
* *unset* can be marked *remote*.
|
||||
*/
|
||||
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 */
|
||||
pid_t pid; /* > 0 if the PidRef is set, otherwise set to PID_AUTOMATIC if automatic mode is
|
||||
* desired, or 0 otherwise. */
|
||||
int fd; /* only valid if pidfd are available in the kernel, and we manage to get an fd. If we
|
||||
* know that the PID is not from the local machine we set this to -EREMOTE, otherwise
|
||||
* we use -EBADF as indicator the fd is invalid. */
|
||||
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 */
|
||||
};
|
||||
@@ -31,6 +56,12 @@ static inline bool pidref_is_set(const PidRef *pidref) {
|
||||
|
||||
bool pidref_is_automatic(const PidRef *pidref);
|
||||
|
||||
static inline bool pidref_is_remote(const PidRef *pidref) {
|
||||
/* If the fd is set to -EREMOTE we assume PidRef does not refer to a local PID, but on another
|
||||
* machine (and we just got the PidRef initialized due to deserialization of some RPC message) */
|
||||
return pidref_is_set(pidref) && pidref->fd == -EREMOTE;
|
||||
}
|
||||
|
||||
int pidref_acquire_pidfd_id(PidRef *pidref);
|
||||
bool pidref_equal(PidRef *a, PidRef *b);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user