diff options
author | Lennart Poettering <lennart@poettering.net> | 2023-11-23 18:12:44 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2024-01-02 17:57:35 +0100 |
commit | 0eccf7259ec9e891347adecf4326401a619b8848 (patch) | |
tree | 2d178a3ff6cfafda63855e2edb56986b944d8e2f /src | |
parent | socket-util: add helper for getting peer pidfd (diff) | |
download | systemd-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.c | 53 | ||||
-rw-r--r-- | src/shared/varlink.h | 2 |
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); |