summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-11-23 18:12:44 +0100
committerLennart Poettering <lennart@poettering.net>2024-01-02 17:57:35 +0100
commit0eccf7259ec9e891347adecf4326401a619b8848 (patch)
tree2d178a3ff6cfafda63855e2edb56986b944d8e2f /src
parentsocket-util: add helper for getting peer pidfd (diff)
downloadsystemd-0eccf7259ec9e891347adecf4326401a619b8848.tar.xz
systemd-0eccf7259ec9e891347adecf4326401a619b8848.zip
varlink: add new helper varlink_get_peer_pidref() for getting PidRef of peer
Diffstat (limited to 'src')
-rw-r--r--src/shared/varlink.c53
-rw-r--r--src/shared/varlink.h2
2 files changed, 55 insertions, 0 deletions
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
index 12a27fcb8d..4664d6b2a6 100644
--- a/src/shared/varlink.c
+++ b/src/shared/varlink.c
@@ -171,6 +171,7 @@ struct Varlink {
JsonVariant *current;
VarlinkSymbol *current_method;
+ int peer_pidfd;
struct ucred ucred;
bool ucred_acquired:1;
@@ -361,6 +362,8 @@ static int varlink_new(Varlink **ret) {
.timeout = VARLINK_DEFAULT_TIMEOUT_USEC,
.af = -1,
+
+ .peer_pidfd = -EBADF,
};
*ret = v;
@@ -638,6 +641,8 @@ static void varlink_clear(Varlink *v) {
sigterm_wait(v->exec_pid);
v->exec_pid = 0;
}
+
+ v->peer_pidfd = safe_close(v->peer_pidfd);
}
static Varlink* varlink_destroy(Varlink *v) {
@@ -2591,6 +2596,54 @@ int varlink_get_peer_pid(Varlink *v, pid_t *ret) {
return 0;
}
+static int varlink_acquire_pidfd(Varlink *v) {
+ assert(v);
+
+ if (v->peer_pidfd >= 0)
+ return 0;
+
+ v->peer_pidfd = getpeerpidfd(v->fd);
+ if (v->peer_pidfd < 0)
+ return v->peer_pidfd;
+
+ return 0;
+}
+
+int varlink_get_peer_pidref(Varlink *v, PidRef *ret) {
+ int r;
+
+ assert_return(v, -EINVAL);
+ assert_return(ret, -EINVAL);
+
+ /* Returns r > 0 if we acquired the pidref via SO_PEERPIDFD (i.e. if we can use it for
+ * authentication). Returns == 0 if we didn't, and the pidref should not be used for
+ * authentication. */
+
+ r = varlink_acquire_pidfd(v);
+ if (r < 0)
+ return r;
+
+ if (v->peer_pidfd < 0) {
+ pid_t pid;
+
+ r = varlink_get_peer_pid(v, &pid);
+ if (r < 0)
+ return r;
+
+ r = pidref_set_pid(ret, pid);
+ if (r < 0)
+ return r;
+
+ return 0; /* didn't get pidfd securely */
+ }
+
+ r = pidref_set_pidfd(ret, v->peer_pidfd);
+ if (r < 0)
+ return r;
+
+ return 1; /* got pidfd securely */
+}
+
int varlink_set_relative_timeout(Varlink *v, usec_t timeout) {
assert_return(v, -EINVAL);
assert_return(timeout > 0, -EINVAL);
diff --git a/src/shared/varlink.h b/src/shared/varlink.h
index c60f695be7..ad8e9cc46d 100644
--- a/src/shared/varlink.h
+++ b/src/shared/varlink.h
@@ -4,6 +4,7 @@
#include "sd-event.h"
#include "json.h"
+#include "pidref.h"
#include "time-util.h"
#include "varlink-idl.h"
@@ -139,6 +140,7 @@ void* varlink_get_userdata(Varlink *v);
int varlink_get_peer_uid(Varlink *v, uid_t *ret);
int varlink_get_peer_pid(Varlink *v, pid_t *ret);
+int varlink_get_peer_pidref(Varlink *v, PidRef *ret);
int varlink_set_relative_timeout(Varlink *v, usec_t usec);