mirror of
https://github.com/systemd/systemd.git
synced 2025-01-26 14:04:03 +03:00
logind: introduce CreateSessionWithPIDFD()
This new D-Bus API uses pidfd to refer to the session leader. Also, pam_systemd will try to make use of it when pidfd support is available.
This commit is contained in:
parent
c895d047e3
commit
76f2191d8e
@ -80,6 +80,30 @@ node /org/freedesktop/login1 {
|
||||
out u vtnr,
|
||||
out b existing);
|
||||
@org.freedesktop.systemd1.Privileged("true")
|
||||
CreateSessionWithPIDFD(in u uid,
|
||||
in h pidfd,
|
||||
in s service,
|
||||
in s type,
|
||||
in s class,
|
||||
in s desktop,
|
||||
in s seat_id,
|
||||
in u vtnr,
|
||||
in s tty,
|
||||
in s display,
|
||||
in b remote,
|
||||
in s remote_user,
|
||||
in s remote_host,
|
||||
in t flags,
|
||||
in a(sv) properties,
|
||||
out s session_id,
|
||||
out o object_path,
|
||||
out s runtime_path,
|
||||
out h fifo_fd,
|
||||
out u uid,
|
||||
out s seat_id,
|
||||
out u vtnr,
|
||||
out b existing);
|
||||
@org.freedesktop.systemd1.Privileged("true")
|
||||
ReleaseSession(in s session_id);
|
||||
ActivateSession(in s session_id);
|
||||
ActivateSessionOnSeat(in s session_id,
|
||||
@ -294,6 +318,8 @@ node /org/freedesktop/login1 {
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="CreateSession()"/>
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="CreateSessionWithPIDFD()"/>
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="ReleaseSession()"/>
|
||||
|
||||
<variablelist class="dbus-method" generated="True" extra-ref="ActivateSession()"/>
|
||||
@ -525,10 +551,10 @@ node /org/freedesktop/login1 {
|
||||
structures consisting of <varname>what</varname>, <varname>who</varname>, <varname>why</varname>,
|
||||
<varname>mode</varname>, <varname>uid</varname> (user ID), and <varname>pid</varname> (process ID).</para>
|
||||
|
||||
<para><function>CreateSession()</function> and <function>ReleaseSession()</function> may be used to
|
||||
open or close login sessions. These calls should <emphasis>never</emphasis> be invoked directly by
|
||||
clients. Creating/closing sessions is exclusively the job of PAM and its
|
||||
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
<para><function>CreateSession()</function>, <function>CreateSessionWithPIDFD()</function>, and
|
||||
<function>ReleaseSession()</function> may be used to open or close login sessions. These calls should
|
||||
<emphasis>never</emphasis> be invoked directly by clients. Creating/closing sessions is exclusively the job
|
||||
of PAM and its <citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
module.</para>
|
||||
|
||||
<para><function>ActivateSession()</function> brings the session with the specified ID into the
|
||||
@ -1520,7 +1546,8 @@ node /org/freedesktop/login1/session/1 {
|
||||
<varname>HandleSuspendKeyLongPress</varname>, and
|
||||
<varname>HandleHibernateKeyLongPress</varname> were added in version 251.</para>
|
||||
<para><varname>StopIdleSessionUSec</varname> was added in version 252.</para>
|
||||
<para><function>PrepareForShutdownWithMetadata</function> was added in version 255.</para>
|
||||
<para><function>PrepareForShutdownWithMetadata</function> and
|
||||
<function>CreateSessionWithPIDFD()</function> were added in version 255.</para>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Session Objects</title>
|
||||
|
@ -677,36 +677,73 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu
|
||||
return sd_bus_send(NULL, reply, NULL);
|
||||
}
|
||||
|
||||
static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
|
||||
static int create_session(
|
||||
sd_bus_message *message,
|
||||
void *userdata,
|
||||
sd_bus_error *error,
|
||||
uid_t uid,
|
||||
pid_t pid,
|
||||
int pidfd,
|
||||
const char *service,
|
||||
const char *type,
|
||||
const char *class,
|
||||
const char *desktop,
|
||||
const char *cseat,
|
||||
uint32_t vtnr,
|
||||
const char *tty,
|
||||
const char *display,
|
||||
int remote,
|
||||
const char *remote_user,
|
||||
const char *remote_host,
|
||||
uint64_t flags) {
|
||||
|
||||
_cleanup_(pidref_done) PidRef leader = PIDREF_NULL;
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
_cleanup_free_ char *id = NULL;
|
||||
Session *session = NULL;
|
||||
uint32_t audit_id = 0;
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
User *user = NULL;
|
||||
Seat *seat = NULL;
|
||||
pid_t leader;
|
||||
uid_t uid;
|
||||
int remote;
|
||||
uint32_t vtnr = 0;
|
||||
SessionType t;
|
||||
SessionClass c;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
||||
assert_cc(sizeof(pid_t) == sizeof(uint32_t));
|
||||
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
|
||||
|
||||
r = sd_bus_message_read(message, "uusssssussbss",
|
||||
&uid, &leader, &service, &type, &class, &desktop, &cseat,
|
||||
&vtnr, &tty, &display, &remote, &remote_user, &remote_host);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!uid_is_valid(uid))
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UID");
|
||||
if (leader < 0 || leader == 1 || leader == getpid_cached())
|
||||
|
||||
if (flags != 0)
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags must be zero.");
|
||||
|
||||
if (pidfd >= 0) {
|
||||
r = pidref_set_pidfd(&leader, pidfd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else if (pid == 0) {
|
||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
||||
pid_t p;
|
||||
|
||||
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_creds_get_pid(creds, &p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = pidref_set_pid(&leader, p);
|
||||
if (r < 0)
|
||||
return r;
|
||||
} else {
|
||||
assert(pid > 0);
|
||||
|
||||
r = pidref_set_pid(&leader, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (leader.pid == 1 || leader.pid == getpid_cached())
|
||||
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
|
||||
|
||||
if (isempty(type))
|
||||
@ -805,21 +842,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
|
||||
c = SESSION_USER;
|
||||
}
|
||||
|
||||
if (leader == 0) {
|
||||
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
|
||||
|
||||
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Check if we are already in a logind session. Or if we are in user@.service
|
||||
* which is a special PAM session that avoids creating a logind session. */
|
||||
r = manager_get_user_by_pid(m, leader, NULL);
|
||||
r = manager_get_user_by_pid(m, leader.pid, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
@ -848,7 +873,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
|
||||
"Maximum number of sessions (%" PRIu64 ") reached, refusing further sessions.",
|
||||
m->sessions_max);
|
||||
|
||||
(void) audit_session_from_pid(leader, &audit_id);
|
||||
(void) audit_session_from_pid(leader.pid, &audit_id);
|
||||
if (audit_session_is_valid(audit_id)) {
|
||||
/* Keep our session IDs and the audit session IDs in sync */
|
||||
|
||||
@ -890,7 +915,7 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
|
||||
goto fail;
|
||||
|
||||
session_set_user(session, user);
|
||||
r = session_set_leader(session, leader);
|
||||
r = session_set_leader_consume(session, TAKE_PIDREF(leader));
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
@ -984,6 +1009,107 @@ fail:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
|
||||
pid_t leader;
|
||||
uid_t uid;
|
||||
int remote;
|
||||
uint32_t vtnr = 0;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
||||
assert_cc(sizeof(pid_t) == sizeof(uint32_t));
|
||||
assert_cc(sizeof(uid_t) == sizeof(uint32_t));
|
||||
|
||||
r = sd_bus_message_read(message,
|
||||
"uusssssussbss",
|
||||
&uid,
|
||||
&leader,
|
||||
&service,
|
||||
&type,
|
||||
&class,
|
||||
&desktop,
|
||||
&cseat,
|
||||
&vtnr,
|
||||
&tty,
|
||||
&display,
|
||||
&remote,
|
||||
&remote_user,
|
||||
&remote_host);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return create_session(
|
||||
message,
|
||||
userdata,
|
||||
error,
|
||||
uid,
|
||||
leader,
|
||||
/* pidfd = */ -EBADF,
|
||||
service,
|
||||
type,
|
||||
class,
|
||||
desktop,
|
||||
cseat,
|
||||
vtnr,
|
||||
tty,
|
||||
display,
|
||||
remote,
|
||||
remote_user,
|
||||
remote_host,
|
||||
/* flags = */ 0);
|
||||
}
|
||||
|
||||
static int method_create_session_pidfd(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
|
||||
int leaderfd = -EBADF;
|
||||
uid_t uid;
|
||||
int remote;
|
||||
uint32_t vtnr = 0;
|
||||
uint64_t flags;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_read(message,
|
||||
"uhsssssussbsst",
|
||||
&uid,
|
||||
&leaderfd,
|
||||
&service,
|
||||
&type,
|
||||
&class,
|
||||
&desktop,
|
||||
&cseat,
|
||||
&vtnr,
|
||||
&tty,
|
||||
&display,
|
||||
&remote,
|
||||
&remote_user,
|
||||
&remote_host,
|
||||
&flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return create_session(
|
||||
message,
|
||||
userdata,
|
||||
error,
|
||||
uid,
|
||||
/* pid = */ 0,
|
||||
leaderfd,
|
||||
service,
|
||||
type,
|
||||
class,
|
||||
desktop,
|
||||
cseat,
|
||||
vtnr,
|
||||
tty,
|
||||
display,
|
||||
remote,
|
||||
remote_user,
|
||||
remote_host,
|
||||
flags);
|
||||
}
|
||||
|
||||
static int method_release_session(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
Manager *m = ASSERT_PTR(userdata);
|
||||
Session *session;
|
||||
@ -3494,6 +3620,32 @@ static const sd_bus_vtable manager_vtable[] = {
|
||||
"b", existing),
|
||||
method_create_session,
|
||||
0),
|
||||
SD_BUS_METHOD_WITH_ARGS("CreateSessionWithPIDFD",
|
||||
SD_BUS_ARGS("u", uid,
|
||||
"h", pidfd,
|
||||
"s", service,
|
||||
"s", type,
|
||||
"s", class,
|
||||
"s", desktop,
|
||||
"s", seat_id,
|
||||
"u", vtnr,
|
||||
"s", tty,
|
||||
"s", display,
|
||||
"b", remote,
|
||||
"s", remote_user,
|
||||
"s", remote_host,
|
||||
"t", flags,
|
||||
"a(sv)", properties),
|
||||
SD_BUS_RESULT("s", session_id,
|
||||
"o", object_path,
|
||||
"s", runtime_path,
|
||||
"h", fifo_fd,
|
||||
"u", uid,
|
||||
"s", seat_id,
|
||||
"u", vtnr,
|
||||
"b", existing),
|
||||
method_create_session_pidfd,
|
||||
0),
|
||||
SD_BUS_METHOD_WITH_ARGS("ReleaseSession",
|
||||
SD_BUS_ARGS("s", session_id),
|
||||
SD_BUS_NO_RESULT,
|
||||
|
@ -810,6 +810,7 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
|
||||
_cleanup_close_ int fifo_fd = -EBADF;
|
||||
_cleanup_free_ char *p = NULL;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
@ -830,6 +831,10 @@ int session_send_create_reply(Session *s, sd_bus_error *error) {
|
||||
if (fifo_fd < 0)
|
||||
return fifo_fd;
|
||||
|
||||
r = session_watch_pidfd(s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* Update the session state file before we notify the client about the result. */
|
||||
session_save(s);
|
||||
|
||||
|
@ -170,22 +170,16 @@ void session_set_user(Session *s, User *u) {
|
||||
user_update_last_session_timer(u);
|
||||
}
|
||||
|
||||
int session_set_leader(Session *s, pid_t pid) {
|
||||
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
|
||||
int session_set_leader_consume(Session *s, PidRef _leader) {
|
||||
_cleanup_(pidref_done) PidRef pidref = _leader;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(pidref_is_set(&pidref));
|
||||
|
||||
if (!pid_is_valid(pid))
|
||||
return -EINVAL;
|
||||
|
||||
if (s->leader.pid == pid)
|
||||
if (pidref_equal(&s->leader, &pidref))
|
||||
return 0;
|
||||
|
||||
r = pidref_set_pid(&pidref, pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = hashmap_put(s->manager->sessions_by_leader, PID_TO_PTR(pidref.pid), s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -523,13 +517,13 @@ int session_load(Session *s) {
|
||||
}
|
||||
|
||||
if (leader) {
|
||||
pid_t pid;
|
||||
_cleanup_(pidref_done) PidRef p = PIDREF_NULL;
|
||||
|
||||
r = parse_pid(leader, &pid);
|
||||
r = pidref_set_pidstr(&p, leader);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Failed to parse leader PID of session: %s", leader);
|
||||
else {
|
||||
r = session_set_leader(s, pid);
|
||||
r = session_set_leader_consume(s, TAKE_PIDREF(p));
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to set session leader PID, ignoring: %m");
|
||||
}
|
||||
@ -884,6 +878,7 @@ int session_stop(Session *s, bool force) {
|
||||
return 0;
|
||||
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
|
||||
|
||||
if (s->seat)
|
||||
seat_evict_position(s->seat, s);
|
||||
@ -921,6 +916,7 @@ int session_finalize(Session *s) {
|
||||
LOG_MESSAGE("Removed session %s.", s->id));
|
||||
|
||||
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
|
||||
s->leader_pidfd_event_source = sd_event_source_unref(s->leader_pidfd_event_source);
|
||||
|
||||
if (s->seat)
|
||||
seat_evict_position(s->seat, s);
|
||||
@ -945,6 +941,8 @@ int session_finalize(Session *s) {
|
||||
seat_save(s->seat);
|
||||
}
|
||||
|
||||
pidref_done(&s->leader);
|
||||
|
||||
user_save(s->user);
|
||||
user_send_changed(s->user, "Display", NULL);
|
||||
|
||||
@ -1226,6 +1224,36 @@ static void session_remove_fifo(Session *s) {
|
||||
}
|
||||
}
|
||||
|
||||
static int session_dispatch_leader_pidfd(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
|
||||
Session *s = ASSERT_PTR(userdata);
|
||||
|
||||
assert(s->leader.fd == fd);
|
||||
session_stop(s, /* force= */ false);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int session_watch_pidfd(Session *s) {
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
|
||||
if (s->leader.fd < 0)
|
||||
return 0;
|
||||
|
||||
r = sd_event_add_io(s->manager->event, &s->leader_pidfd_event_source, s->leader.fd, EPOLLIN, session_dispatch_leader_pidfd, s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_event_source_set_priority(s->leader_pidfd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
(void) sd_event_source_set_description(s->leader_pidfd_event_source, "session-pidfd");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool session_may_gc(Session *s, bool drop_not_started) {
|
||||
int r;
|
||||
|
||||
@ -1237,6 +1265,12 @@ bool session_may_gc(Session *s, bool drop_not_started) {
|
||||
if (!s->user)
|
||||
return true;
|
||||
|
||||
r = pidref_is_alive(&s->leader);
|
||||
if (r < 0)
|
||||
log_debug_errno(r, "Unable to determine if leader PID " PID_FMT " is still alive, assuming not.", s->leader.pid);
|
||||
if (r > 0)
|
||||
return false;
|
||||
|
||||
if (s->fifo_fd >= 0) {
|
||||
if (pipe_eof(s->fifo_fd) <= 0)
|
||||
return false;
|
||||
@ -1282,7 +1316,7 @@ SessionState session_get_state(Session *s) {
|
||||
if (s->stopping || s->timer_event_source)
|
||||
return SESSION_CLOSING;
|
||||
|
||||
if (s->scope_job || s->fifo_fd < 0)
|
||||
if (s->scope_job || (!pidref_is_set(&s->leader) && s->fifo_fd < 0))
|
||||
return SESSION_OPENING;
|
||||
|
||||
if (session_is_active(s))
|
||||
|
@ -95,6 +95,7 @@ struct Session {
|
||||
char *fifo_path;
|
||||
|
||||
sd_event_source *fifo_event_source;
|
||||
sd_event_source *leader_pidfd_event_source;
|
||||
|
||||
bool idle_hint;
|
||||
dual_timestamp idle_hint_timestamp;
|
||||
@ -130,7 +131,7 @@ Session* session_free(Session *s);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(Session *, session_free);
|
||||
|
||||
void session_set_user(Session *s, User *u);
|
||||
int session_set_leader(Session *s, pid_t pid);
|
||||
int session_set_leader_consume(Session *s, PidRef _leader);
|
||||
bool session_may_gc(Session *s, bool drop_not_started);
|
||||
void session_add_to_gc_queue(Session *s);
|
||||
int session_activate(Session *s);
|
||||
@ -143,6 +144,7 @@ void session_set_type(Session *s, SessionType t);
|
||||
int session_set_display(Session *s, const char *display);
|
||||
int session_set_tty(Session *s, const char *tty);
|
||||
int session_create_fifo(Session *s);
|
||||
int session_watch_pidfd(Session *s);
|
||||
int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error);
|
||||
int session_stop(Session *s, bool force);
|
||||
int session_finalize(Session *s);
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "locale-util.h"
|
||||
#include "login-util.h"
|
||||
#include "macro.h"
|
||||
#include "missing_syscall.h"
|
||||
#include "pam-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
@ -780,6 +781,101 @@ static uint64_t pick_default_capability_ambient_set(
|
||||
(streq_ptr(service, "systemd-user") || !isempty(seat)) ? (UINT64_C(1) << CAP_WAKE_ALARM) : UINT64_MAX;
|
||||
}
|
||||
|
||||
typedef struct SessionContext {
|
||||
const uid_t uid;
|
||||
const pid_t pid;
|
||||
const char *service;
|
||||
const char *type;
|
||||
const char *class;
|
||||
const char *desktop;
|
||||
const char *seat;
|
||||
const uint32_t vtnr;
|
||||
const char *tty;
|
||||
const char *display;
|
||||
const bool remote;
|
||||
const char *remote_user;
|
||||
const char *remote_host;
|
||||
const char *memory_max;
|
||||
const char *tasks_max;
|
||||
const char *cpu_weight;
|
||||
const char *io_weight;
|
||||
const char *runtime_max_sec;
|
||||
} SessionContext;
|
||||
|
||||
static int create_session_message(sd_bus *bus, pam_handle_t *handle, const SessionContext *context, bool avoid_pidfd, sd_bus_message **ret) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
int r, pidfd = -EBADFD;
|
||||
|
||||
assert(bus);
|
||||
assert(handle);
|
||||
assert(context);
|
||||
|
||||
if (!avoid_pidfd) {
|
||||
pidfd = pidfd_open(getpid_cached(), 0);
|
||||
if (pidfd < 0 && !ERRNO_IS_NOT_SUPPORTED(errno))
|
||||
return -errno;
|
||||
}
|
||||
|
||||
r = bus_message_new_method_call(bus, &m, bus_login_mgr, pidfd >= 0 ? "CreateSessionWithPIDFD" : "CreateSession");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m,
|
||||
pidfd >= 0 ? "uhsssssussbss" : "uusssssussbss",
|
||||
(uint32_t) context->uid,
|
||||
pidfd >= 0 ? pidfd : context->pid,
|
||||
context->service,
|
||||
context->type,
|
||||
context->class,
|
||||
context->desktop,
|
||||
context->seat,
|
||||
context->vtnr,
|
||||
context->tty,
|
||||
context->display,
|
||||
context->remote,
|
||||
context->remote_user,
|
||||
context->remote_host);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (pidfd >= 0) {
|
||||
r = sd_bus_message_append(m, "t", UINT64_C(0));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = append_session_memory_max(handle, m, context->memory_max);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_runtime_max_sec(handle, m, context->runtime_max_sec);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_tasks_max(handle, m, context->tasks_max);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_cpu_weight(handle, m, context->cpu_weight);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_io_weight(handle, m, context->io_weight);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
*ret = TAKE_PTR(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_public_ PAM_EXTERN int pam_sm_open_session(
|
||||
pam_handle_t *handle,
|
||||
int flags,
|
||||
@ -963,52 +1059,32 @@ _public_ PAM_EXTERN int pam_sm_open_session(
|
||||
"memory_max=%s tasks_max=%s cpu_weight=%s io_weight=%s runtime_max_sec=%s",
|
||||
strna(memory_max), strna(tasks_max), strna(cpu_weight), strna(io_weight), strna(runtime_max_sec));
|
||||
|
||||
r = bus_message_new_method_call(bus, &m, bus_login_mgr, "CreateSession");
|
||||
if (r < 0)
|
||||
return pam_bus_log_create_error(handle, r);
|
||||
const SessionContext context = {
|
||||
.uid = ur->uid,
|
||||
.pid = 0,
|
||||
.service = service,
|
||||
.type = type,
|
||||
.class = class,
|
||||
.desktop = desktop,
|
||||
.seat = seat,
|
||||
.vtnr = vtnr,
|
||||
.tty = tty,
|
||||
.display = display,
|
||||
.remote = remote,
|
||||
.remote_user = remote_user,
|
||||
.remote_host = remote_host,
|
||||
.memory_max = memory_max,
|
||||
.tasks_max = tasks_max,
|
||||
.cpu_weight = cpu_weight,
|
||||
.io_weight = io_weight,
|
||||
.runtime_max_sec = runtime_max_sec,
|
||||
};
|
||||
|
||||
r = sd_bus_message_append(m, "uusssssussbss",
|
||||
(uint32_t) ur->uid,
|
||||
0,
|
||||
service,
|
||||
type,
|
||||
class,
|
||||
desktop,
|
||||
seat,
|
||||
vtnr,
|
||||
tty,
|
||||
display,
|
||||
remote,
|
||||
remote_user,
|
||||
remote_host);
|
||||
if (r < 0)
|
||||
return pam_bus_log_create_error(handle, r);
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return pam_bus_log_create_error(handle, r);
|
||||
|
||||
r = append_session_memory_max(handle, m, memory_max);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_runtime_max_sec(handle, m, runtime_max_sec);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_tasks_max(handle, m, tasks_max);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_cpu_weight(handle, m, cpu_weight);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = append_session_io_weight(handle, m, io_weight);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
r = create_session_message(bus,
|
||||
handle,
|
||||
&context,
|
||||
false /* avoid_pidfd = */,
|
||||
&m);
|
||||
if (r < 0)
|
||||
return pam_bus_log_create_error(handle, r);
|
||||
|
||||
@ -1019,7 +1095,23 @@ _public_ PAM_EXTERN int pam_sm_open_session(
|
||||
"Not creating session: %s", bus_error_message(&error, r));
|
||||
/* We are already in a session, don't do anything */
|
||||
goto success;
|
||||
} else {
|
||||
} else if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD)) {
|
||||
pam_debug_syslog(handle, debug,
|
||||
"CreateSessionWithPIDFD() API is not available, retrying with CreateSession().");
|
||||
|
||||
m = sd_bus_message_unref(m);
|
||||
r = create_session_message(bus,
|
||||
handle,
|
||||
&context,
|
||||
true /* avoid_pidfd = */,
|
||||
&m);
|
||||
if (r < 0)
|
||||
return pam_bus_log_create_error(handle, r);
|
||||
|
||||
sd_bus_error_free(&error);
|
||||
r = sd_bus_call(bus, m, LOGIN_SLOW_BUS_CALL_TIMEOUT_USEC, &error, &reply);
|
||||
}
|
||||
if (r < 0) {
|
||||
pam_syslog(handle, LOG_ERR,
|
||||
"Failed to create session: %s", bus_error_message(&error, r));
|
||||
return PAM_SESSION_ERR;
|
||||
|
Loading…
x
Reference in New Issue
Block a user