mirror of
https://github.com/systemd/systemd.git
synced 2025-03-11 20:58:27 +03:00
Merge pull request #26114 from bluca/sd_login_pidfd
sd-login: add sd_pidfd_* APIs
This commit is contained in:
commit
fba1033151
@ -815,7 +815,15 @@ manpages = [
|
||||
'sd_pid_get_slice',
|
||||
'sd_pid_get_unit',
|
||||
'sd_pid_get_user_slice',
|
||||
'sd_pid_get_user_unit'],
|
||||
'sd_pid_get_user_unit',
|
||||
'sd_pidfd_get_cgroup',
|
||||
'sd_pidfd_get_machine_name',
|
||||
'sd_pidfd_get_owner_uid',
|
||||
'sd_pidfd_get_session',
|
||||
'sd_pidfd_get_slice',
|
||||
'sd_pidfd_get_unit',
|
||||
'sd_pidfd_get_user_slice',
|
||||
'sd_pidfd_get_user_unit'],
|
||||
'HAVE_PAM'],
|
||||
['sd_seat_get_active',
|
||||
'3',
|
||||
|
@ -25,6 +25,14 @@
|
||||
<refname>sd_pid_get_slice</refname>
|
||||
<refname>sd_pid_get_user_slice</refname>
|
||||
<refname>sd_pid_get_cgroup</refname>
|
||||
<refname>sd_pidfd_get_owner_uid</refname>
|
||||
<refname>sd_pidfd_get_session</refname>
|
||||
<refname>sd_pidfd_get_user_unit</refname>
|
||||
<refname>sd_pidfd_get_unit</refname>
|
||||
<refname>sd_pidfd_get_machine_name</refname>
|
||||
<refname>sd_pidfd_get_slice</refname>
|
||||
<refname>sd_pidfd_get_user_slice</refname>
|
||||
<refname>sd_pidfd_get_cgroup</refname>
|
||||
<refname>sd_peer_get_owner_uid</refname>
|
||||
<refname>sd_peer_get_session</refname>
|
||||
<refname>sd_peer_get_user_unit</refname>
|
||||
@ -90,6 +98,54 @@
|
||||
<paramdef>char **<parameter>cgroup</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_owner_uid</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>uid_t *<parameter>uid</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_session</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>char **<parameter>session</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_user_unit</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>char **<parameter>unit</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_unit</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>char **<parameter>unit</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_machine_name</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>char **<parameter>name</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_slice</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>char **<parameter>slice</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_user_slice</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>char **<parameter>slice</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_pidfd_get_cgroup</function></funcdef>
|
||||
<paramdef>int <parameter>pidfd</parameter></paramdef>
|
||||
<paramdef>char **<parameter>cgroup</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_peer_get_owner_uid</function></funcdef>
|
||||
<paramdef>int <parameter>fd</parameter></paramdef>
|
||||
@ -222,6 +278,20 @@
|
||||
functions is passed as 0, the operation is executed for the
|
||||
calling process.</para>
|
||||
|
||||
<para>The <function>sd_pidfd_get_owner_uid()</function>,
|
||||
<function>sd_pidfd_get_session()</function>,
|
||||
<function>sd_pidfd_get_user_unit()</function>,
|
||||
<function>sd_pidfd_get_unit()</function>,
|
||||
<function>sd_pidfd_get_machine_name()</function>,
|
||||
<function>sd_pidfd_get_slice()</function>,
|
||||
<function>sd_pidfd_get_user_slice()</function> and
|
||||
<function>sd_pidfd_get_cgroup()</function> calls operate similarly to their PID counterparts, but accept a
|
||||
<constant>PIDFD</constant> instead of a <constant>PID</constant>, which means they are not subject to recycle
|
||||
race conditions as the process is pinned by the file descriptor during the whole duration of the invocation.
|
||||
Note that these require a kernel that supports <constant>PIDFD</constant>. A suitable file descriptor may be
|
||||
acquired via
|
||||
<citerefentry project='man-pages'><refentrytitle>pidfd_open</refentrytitle><manvolnum>2</manvolnum></citerefentry>.</para>
|
||||
|
||||
<para>The <function>sd_peer_get_owner_uid()</function>,
|
||||
<function>sd_peer_get_session()</function>,
|
||||
<function>sd_peer_get_user_unit()</function>,
|
||||
|
@ -1456,6 +1456,20 @@ int pidfd_get_pid(int fd, pid_t *ret) {
|
||||
return parse_pid(p, ret);
|
||||
}
|
||||
|
||||
int pidfd_verify_pid(int pidfd, pid_t pid) {
|
||||
pid_t current_pid;
|
||||
int r;
|
||||
|
||||
assert(pidfd >= 0);
|
||||
assert(pid > 0);
|
||||
|
||||
r = pidfd_get_pid(pidfd, ¤t_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return current_pid != pid ? -ESRCH : 0;
|
||||
}
|
||||
|
||||
static int rlimit_to_nice(rlim_t limit) {
|
||||
if (limit <= 1)
|
||||
return PRIO_MAX-1; /* i.e. 19 */
|
||||
|
@ -190,6 +190,7 @@ assert_cc(TASKS_MAX <= (unsigned long) PID_T_MAX);
|
||||
})
|
||||
|
||||
int pidfd_get_pid(int fd, pid_t *ret);
|
||||
int pidfd_verify_pid(int pidfd, pid_t pid);
|
||||
|
||||
int setpriority_closest(int priority);
|
||||
|
||||
|
@ -658,7 +658,7 @@ static int method_get_unit_by_pidfd(sd_bus_message *message, void *userdata, sd_
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
_cleanup_free_ char *path = NULL;
|
||||
int r, pidfd;
|
||||
pid_t pid_early, pid_late;
|
||||
pid_t pid;
|
||||
Unit *u;
|
||||
|
||||
assert(message);
|
||||
@ -667,13 +667,13 @@ static int method_get_unit_by_pidfd(sd_bus_message *message, void *userdata, sd_
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid_early);
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to get PID from PIDFD: %m");
|
||||
|
||||
u = manager_get_unit_by_pid(m, pid_early);
|
||||
u = manager_get_unit_by_pid(m, pid);
|
||||
if (!u)
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid_early);
|
||||
return sd_bus_error_setf(error, BUS_ERROR_NO_UNIT_FOR_PID, "PID "PID_FMT" does not belong to any loaded unit.", pid);
|
||||
|
||||
r = mac_selinux_unit_access_check(u, message, "status", error);
|
||||
if (r < 0)
|
||||
@ -697,15 +697,14 @@ static int method_get_unit_by_pidfd(sd_bus_message *message, void *userdata, sd_
|
||||
|
||||
/* Double-check that the process is still alive and that the PID did not change before returning the
|
||||
* answer. */
|
||||
r = pidfd_get_pid(pidfd, &pid_late);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to get PID from PIDFD: %m");
|
||||
if (pid_early != pid_late)
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r == -ESRCH)
|
||||
return sd_bus_error_setf(error,
|
||||
BUS_ERROR_NO_SUCH_PROCESS,
|
||||
"The PIDFD's PID "PID_FMT" changed to "PID_FMT" during the lookup operation.",
|
||||
pid_early,
|
||||
pid_late);
|
||||
"The PIDFD's PID "PID_FMT" changed during the lookup operation.",
|
||||
pid);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to get PID from PIDFD: %m");
|
||||
|
||||
return sd_bus_send(NULL, reply, NULL);
|
||||
}
|
||||
|
@ -802,4 +802,12 @@ global:
|
||||
sd_bus_emit_signal_to;
|
||||
sd_bus_emit_signal_tov;
|
||||
sd_bus_message_new_signal_to;
|
||||
sd_pidfd_get_cgroup;
|
||||
sd_pidfd_get_machine_name;
|
||||
sd_pidfd_get_owner_uid;
|
||||
sd_pidfd_get_session;
|
||||
sd_pidfd_get_slice;
|
||||
sd_pidfd_get_unit;
|
||||
sd_pidfd_get_user_slice;
|
||||
sd_pidfd_get_user_unit;
|
||||
} LIBSYSTEMD_252;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "macro.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
@ -134,6 +135,206 @@ _public_ int sd_pid_get_cgroup(pid_t pid, char **cgroup) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_session(int pidfd, char **ret_session) {
|
||||
_cleanup_free_ char *session = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EBADF);
|
||||
assert_return(ret_session, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_session(pid, &session);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_session = TAKE_PTR(session);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_unit(int pidfd, char **ret_unit) {
|
||||
_cleanup_free_ char *unit = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EBADF);
|
||||
assert_return(ret_unit, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_unit(pid, &unit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_unit = TAKE_PTR(unit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_user_unit(int pidfd, char **ret_unit) {
|
||||
_cleanup_free_ char *unit = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EBADF);
|
||||
assert_return(ret_unit, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_user_unit(pid, &unit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_unit = TAKE_PTR(unit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_machine_name(int pidfd, char **ret_name) {
|
||||
_cleanup_free_ char *name = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EBADF);
|
||||
assert_return(ret_name, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_machine_name(pid, &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_name = TAKE_PTR(name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_slice(int pidfd, char **ret_slice) {
|
||||
_cleanup_free_ char *slice = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EBADF);
|
||||
assert_return(ret_slice, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_slice(pid, &slice);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_slice = TAKE_PTR(slice);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_user_slice(int pidfd, char **ret_slice) {
|
||||
_cleanup_free_ char *slice = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EBADF);
|
||||
assert_return(ret_slice, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_user_slice(pid, &slice);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_slice = TAKE_PTR(slice);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_owner_uid(int pidfd, uid_t *ret_uid) {
|
||||
uid_t uid;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EINVAL);
|
||||
assert_return(ret_uid, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_owner_uid(pid, &uid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_uid = uid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_pidfd_get_cgroup(int pidfd, char **ret_cgroup) {
|
||||
_cleanup_free_ char *cgroup = NULL;
|
||||
pid_t pid;
|
||||
int r;
|
||||
|
||||
assert_return(pidfd >= 0, -EBADF);
|
||||
assert_return(ret_cgroup, -EINVAL);
|
||||
|
||||
r = pidfd_get_pid(pidfd, &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_pid_get_cgroup(pid, &cgroup);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidfd_verify_pid(pidfd, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret_cgroup = TAKE_PTR(cgroup);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ int sd_peer_get_session(int fd, char **session) {
|
||||
struct ucred ucred = UCRED_INVALID;
|
||||
int r;
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "log.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "process-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
@ -44,6 +46,7 @@ TEST(login) {
|
||||
*type = NULL, *class = NULL, *state = NULL, *state2 = NULL,
|
||||
*seat = NULL, *session = NULL,
|
||||
*unit = NULL, *user_unit = NULL, *slice = NULL;
|
||||
_cleanup_close_ int pidfd = -EBADFD;
|
||||
int r;
|
||||
uid_t u, u2 = UID_INVALID;
|
||||
char *t, **seats = NULL, **sessions = NULL;
|
||||
@ -71,6 +74,35 @@ TEST(login) {
|
||||
log_info("sd_pid_get_cgroup(0, …) → %s / \"%s\"", e(r), strnull(cgroup));
|
||||
assert_se(IN_SET(r, 0, -ENOMEDIUM));
|
||||
|
||||
pidfd = pidfd_open(getpid_cached(), 0);
|
||||
if (pidfd >= 0) {
|
||||
_cleanup_free_ char *cgroup2 = NULL, *session2 = NULL,
|
||||
*unit2 = NULL, *user_unit2 = NULL, *slice2 = NULL;
|
||||
|
||||
r = sd_pidfd_get_unit(pidfd, &unit2);
|
||||
log_info("sd_pidfd_get_unit(pidfd, …) → %s / \"%s\"", e(r), strnull(unit2));
|
||||
assert_se(IN_SET(r, 0, -ENODATA));
|
||||
|
||||
r = sd_pidfd_get_user_unit(pidfd, &user_unit2);
|
||||
log_info("sd_pidfd_get_user_unit(pidfd, …) → %s / \"%s\"", e(r), strnull(user_unit2));
|
||||
assert_se(IN_SET(r, 0, -ENODATA));
|
||||
|
||||
r = sd_pidfd_get_slice(pidfd, &slice2);
|
||||
log_info("sd_pidfd_get_slice(pidfd, …) → %s / \"%s\"", e(r), strnull(slice2));
|
||||
assert_se(IN_SET(r, 0, -ENODATA));
|
||||
|
||||
r = sd_pidfd_get_owner_uid(pidfd, &u2);
|
||||
log_info("sd_pidfd_get_owner_uid(pidfd, …) → %s / "UID_FMT, e(r), u2);
|
||||
assert_se(IN_SET(r, 0, -ENODATA));
|
||||
|
||||
r = sd_pidfd_get_session(pidfd, &session2);
|
||||
log_info("sd_pidfd_get_session(pidfd, …) → %s / \"%s\"", e(r), strnull(session2));
|
||||
|
||||
r = sd_pidfd_get_cgroup(pidfd, &cgroup2);
|
||||
log_info("sd_pidfd_get_cgroup(pidfd, …) → %s / \"%s\"", e(r), strnull(cgroup2));
|
||||
assert_se(IN_SET(r, 0, -ENOMEDIUM));
|
||||
}
|
||||
|
||||
r = sd_uid_get_display(u2, &display_session);
|
||||
log_info("sd_uid_get_display("UID_FMT", …) → %s / \"%s\"", u2, e(r), strnull(display_session));
|
||||
if (u2 == UID_INVALID)
|
||||
|
@ -80,6 +80,18 @@ int sd_pid_get_machine_name(pid_t pid, char **machine);
|
||||
* hierarchy. */
|
||||
int sd_pid_get_cgroup(pid_t pid, char **cgroup);
|
||||
|
||||
/* Equivalent to the corresponding sd_pid_get* functions, but take a
|
||||
* PIDFD instead of a PID, to ensure there can be no possible PID
|
||||
* recycle issues before/after the calls. */
|
||||
int sd_pidfd_get_session(pid_t pid, char **session);
|
||||
int sd_pidfd_get_owner_uid(pid_t pid, uid_t *uid);
|
||||
int sd_pidfd_get_unit(pid_t pid, char **unit);
|
||||
int sd_pidfd_get_user_unit(pid_t pid, char **unit);
|
||||
int sd_pidfd_get_slice(pid_t pid, char **slice);
|
||||
int sd_pidfd_get_user_slice(pid_t pid, char **slice);
|
||||
int sd_pidfd_get_machine_name(pid_t pid, char **machine);
|
||||
int sd_pidfd_get_cgroup(pid_t pid, char **cgroup);
|
||||
|
||||
/* Similar to sd_pid_get_session(), but retrieves data about the peer
|
||||
* of a connected AF_UNIX socket */
|
||||
int sd_peer_get_session(int fd, char **session);
|
||||
|
Loading…
x
Reference in New Issue
Block a user