xaccess: Rework from boolean into a list of tags
XDG_SESSION_EXTRA_DEVICE_ACCESS will now take a colon-separated list of identifiers. For every identifier $ID, the session is granted access to all devices tagged as "xaccess-$ID" in udev. Fixes: #40634
This commit is contained in:
@@ -1246,7 +1246,7 @@ node /org/freedesktop/login1/session/1 {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s RemoteUser = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b ExtraDeviceAccess = ...;
|
||||
readonly as ExtraDeviceAccess = ['...', ...];
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly s Service = '...';
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
@@ -1541,9 +1541,9 @@ node /org/freedesktop/login1/session/1 {
|
||||
<para><varname>RemoteHost</varname> and <varname>RemoteUser</varname> encode the remote host and user
|
||||
if this is a remote session, or an empty string otherwise.</para>
|
||||
|
||||
<para><varname>ExtraDeviceAccess</varname> encodes whether the session is granted access to additional
|
||||
hardware devices, typically useful for for graphical, remote session. If true, the session is granted
|
||||
access to all devices tagged with <literal>xaccess</literal> in udev.</para>
|
||||
<para><varname>ExtraDeviceAccess</varname> encodes the set of additional hardware devices that the session
|
||||
is granted access to. For every <literal><replaceable>ID</replaceable></literal> in the list, the session
|
||||
is granted access to all devices tagged with <literal>xaccess-<replaceable>ID</replaceable></literal> in udev.</para>
|
||||
|
||||
<para><varname>Service</varname> encodes the PAM service name that registered the session.</para>
|
||||
|
||||
|
||||
+3
-4
@@ -408,10 +408,9 @@
|
||||
<varlistentry>
|
||||
<term><varname>$XDG_SESSION_EXTRA_DEVICE_ACCESS</varname></term>
|
||||
|
||||
<listitem><para>Whether or not the session shall be granted additional hardware device access,
|
||||
typically useful for graphical, remote session. If true, the session is granted access to all
|
||||
devices tagged with <literal>xaccess</literal> in udev. Typically, rendering device nodes of
|
||||
the GPU are tagged like this.</para>
|
||||
<listitem><para>The set of additional hardware devices that the session shall be granted access to.
|
||||
For every <literal><replaceable>ID</replaceable></literal> in the list, the session is granted
|
||||
access to all devices tagged with <literal>xaccess-<replaceable>ID</replaceable></literal> in udev.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -926,7 +926,7 @@ manpages = [
|
||||
'sd_session_get_uid',
|
||||
'sd_session_get_username',
|
||||
'sd_session_get_vt',
|
||||
'sd_session_has_extra_device_access',
|
||||
'sd_session_get_extra_device_access',
|
||||
'sd_session_is_remote'],
|
||||
'HAVE_PAM'],
|
||||
['sd_uid_get_state',
|
||||
|
||||
+6
-5
@@ -191,12 +191,13 @@
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>Tag <literal>xaccess</literal></term>
|
||||
<term>Tag <literal>xaccess-*</literal></term>
|
||||
|
||||
<listitem><para>When set, access to this device is granted to sessions
|
||||
created with <literal>ExtraDeviceAccess</literal>. This is typically useful
|
||||
for graphical, remote sessions. As the <literal>ExtraDeviceAccess</literal>
|
||||
sessions open and close, access to the device is updated accordingly.</para>
|
||||
<listitem><para>When <literal>xaccess-<replaceable>ID</replaceable></literal>
|
||||
is set, access to this device is granted to sessions created with
|
||||
<literal><replaceable>ID</replaceable></literal> listed in <literal>ExtraDeviceAccess</literal>.
|
||||
As the sessions with some <literal>ExtraDeviceAccess</literal> open and close,
|
||||
access to the device is updated accordingly.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v260"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<refname>sd_session_get_remote_host</refname>
|
||||
<refname>sd_session_get_remote_user</refname>
|
||||
<refname>sd_session_get_leader</refname>
|
||||
<refname>sd_session_has_extra_device_access</refname>
|
||||
<refname>sd_session_get_extra_device_access</refname>
|
||||
<refpurpose>Determine state of a specific session</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
@@ -143,8 +143,9 @@
|
||||
</funcprototype>
|
||||
|
||||
<funcprototype>
|
||||
<funcdef>int <function>sd_session_has_extra_device_access</function></funcdef>
|
||||
<funcdef>int <function>sd_session_get_extra_device_access</function></funcdef>
|
||||
<paramdef>const char *<parameter>session</parameter></paramdef>
|
||||
<paramdef>char ***<parameter>ret_ids</parameter></paramdef>
|
||||
</funcprototype>
|
||||
</funcsynopsis>
|
||||
</refsynopsisdiv>
|
||||
@@ -280,11 +281,11 @@
|
||||
session identifier. This function will return an error if the seat
|
||||
does not support VTs.</para>
|
||||
|
||||
<para><function>sd_session_has_extra_device_access()</function> may
|
||||
be used to determine whether the session is granted access to
|
||||
additional hardware devices, typically useful for for graphical,
|
||||
remote session. If true, the session is granted access to all
|
||||
devices tagged with <literal>xaccess</literal> in udev.</para>
|
||||
<para><function>sd_session_get_extra_device_access()</function> may
|
||||
be used to determine which additional hardware devices the session
|
||||
is granted access to. For every <literal><replaceable>ID</replaceable></literal>
|
||||
in the list, the session is granted access to all devices tagged with
|
||||
<literal>xaccess-<replaceable>ID</replaceable></literal> in udev.</para>
|
||||
|
||||
<para>If the <varname>session</varname> parameter of any of these
|
||||
functions is passed as <constant>NULL</constant>, the operation is
|
||||
@@ -296,9 +297,8 @@
|
||||
<title>Return Value</title>
|
||||
|
||||
<para>If the test succeeds,
|
||||
<function>sd_session_is_active()</function>,
|
||||
<function>sd_session_is_remote()</function>, and
|
||||
<function>sd_session_has_extra_device_access()</function>
|
||||
<function>sd_session_is_active()</function> and
|
||||
<function>sd_session_is_remote()</function>
|
||||
return a positive integer; if it fails, 0. On success,
|
||||
<function>sd_session_get_state()</function>,
|
||||
<function>sd_session_get_uid()</function>,
|
||||
@@ -310,9 +310,10 @@
|
||||
<function>sd_session_get_display()</function>,
|
||||
<function>sd_session_get_leader()</function>,
|
||||
<function>sd_session_get_remote_user()</function>,
|
||||
<function>sd_session_get_remote_host()</function> and
|
||||
<function>sd_session_get_tty()</function> return 0 or
|
||||
a positive integer. On failure, these calls return a
|
||||
<function>sd_session_get_remote_host()</function>,
|
||||
<function>sd_session_get_tty()</function>, and
|
||||
<function>sd_session_get_extra_device_access()</function>
|
||||
return 0 or a positive integer. On failure, these calls return a
|
||||
negative errno-style error code.</para>
|
||||
|
||||
<refsect2>
|
||||
@@ -366,7 +367,7 @@
|
||||
<para><function>sd_session_get_username()</function>,
|
||||
<function>sd_session_get_start_time()</function>, and
|
||||
<function>sd_session_get_leader()</function> were added in version 254.</para>
|
||||
<para><function>sd_session_has_extra_device_access()</function> was added in version 260.</para>
|
||||
<para><function>sd_session_get_extra_device_access()</function> was added in version 260.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@@ -1088,5 +1088,5 @@ global:
|
||||
|
||||
LIBSYSTEMD_260 {
|
||||
global:
|
||||
sd_session_has_extra_device_access;
|
||||
sd_session_get_extra_device_access;
|
||||
} LIBSYSTEMD_259;
|
||||
|
||||
@@ -264,6 +264,8 @@ enum {
|
||||
SD_JSON_BUILD_PAIR_CONDITION(condition, name, SD_JSON_BUILD_UNSIGNED(value))
|
||||
#define JSON_BUILD_PAIR_CONDITION_BOOLEAN(condition, name, value) \
|
||||
SD_JSON_BUILD_PAIR_CONDITION(condition, name, SD_JSON_BUILD_BOOLEAN(value))
|
||||
#define JSON_BUILD_PAIR_CONDITION_STRV(condition, name, value) \
|
||||
SD_JSON_BUILD_PAIR_CONDITION(condition, name, SD_JSON_BUILD_STRV(value))
|
||||
|
||||
int json_variant_new_pidref(sd_json_variant **ret, PidRef *pidref);
|
||||
int json_variant_new_devnum(sd_json_variant **ret, dev_t devnum);
|
||||
|
||||
@@ -677,7 +677,7 @@ _public_ int sd_session_is_remote(const char *session) {
|
||||
return parse_boolean(s);
|
||||
}
|
||||
|
||||
_public_ int sd_session_has_extra_device_access(const char *session) {
|
||||
_public_ int sd_session_get_extra_device_access(const char *session, char ***ret_ids) {
|
||||
_cleanup_free_ char *p = NULL, *s = NULL;
|
||||
int r;
|
||||
|
||||
@@ -690,10 +690,21 @@ _public_ int sd_session_has_extra_device_access(const char *session) {
|
||||
return -ENXIO;
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (isempty(s))
|
||||
return -ENODATA;
|
||||
|
||||
return parse_boolean(s);
|
||||
_cleanup_strv_free_ char **ids = NULL;
|
||||
size_t n_ids = 0;
|
||||
if (!isempty(s)) {
|
||||
ids = strv_split(s, /* separators= */ NULL);
|
||||
if (!ids)
|
||||
return -ENOMEM;
|
||||
|
||||
n_ids = strv_length(ids);
|
||||
}
|
||||
|
||||
if (ret_ids)
|
||||
*ret_ids = TAKE_PTR(ids);
|
||||
|
||||
return n_ids;
|
||||
}
|
||||
|
||||
_public_ int sd_session_get_state(const char *session, char **ret_state) {
|
||||
|
||||
@@ -898,7 +898,7 @@ int manager_create_session(
|
||||
bool remote,
|
||||
const char *remote_user,
|
||||
const char *remote_host,
|
||||
bool extra_device_access,
|
||||
char * const *extra_device_access,
|
||||
Session **ret_session) {
|
||||
|
||||
bool mangle_class = false;
|
||||
@@ -1005,7 +1005,6 @@ int manager_create_session(
|
||||
|
||||
session->original_type = session->type = type;
|
||||
session->remote = remote;
|
||||
session->extra_device_access = extra_device_access;
|
||||
session->vtnr = vtnr;
|
||||
session->class = class;
|
||||
|
||||
@@ -1055,6 +1054,10 @@ int manager_create_session(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
r = strv_copy_unless_empty(extra_device_access, &session->extra_device_access);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
if (seat) {
|
||||
r = seat_attach_session(seat, session);
|
||||
if (r < 0)
|
||||
@@ -1229,7 +1232,7 @@ static int manager_create_session_by_bus(
|
||||
remote,
|
||||
remote_user,
|
||||
remote_host,
|
||||
/* extra_device_access= */ false,
|
||||
/* extra_device_access= */ NULL,
|
||||
&session);
|
||||
if (r == -EBUSY)
|
||||
return sd_bus_error_set(error, BUS_ERROR_SESSION_BUSY, "Already running in a session or user slice");
|
||||
|
||||
@@ -57,7 +57,7 @@ int manager_create_session(
|
||||
bool remote,
|
||||
const char *remote_user,
|
||||
const char *remote_host,
|
||||
bool extra_device_access,
|
||||
char * const *extra_device_access,
|
||||
Session **ret_session);
|
||||
|
||||
extern const BusObjectImplementation manager_object;
|
||||
|
||||
@@ -985,7 +985,7 @@ static const sd_bus_vtable session_vtable[] = {
|
||||
SD_BUS_PROPERTY("Remote", "b", bus_property_get_bool, offsetof(Session, remote), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RemoteHost", "s", NULL, offsetof(Session, remote_host), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RemoteUser", "s", NULL, offsetof(Session, remote_user), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ExtraDeviceAccess", "b", bus_property_get_bool, offsetof(Session, extra_device_access), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ExtraDeviceAccess", "as", NULL, offsetof(Session, extra_device_access), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Session, service), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Desktop", "s", NULL, offsetof(Session, desktop), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Session, scope), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
|
||||
+33
-15
@@ -45,6 +45,7 @@
|
||||
#include "process-util.h"
|
||||
#include "serialize.h"
|
||||
#include "string-table.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "user-record.h"
|
||||
@@ -210,6 +211,7 @@ Session* session_free(Session *s) {
|
||||
free(s->remote_user);
|
||||
free(s->service);
|
||||
free(s->desktop);
|
||||
strv_free(s->extra_device_access);
|
||||
|
||||
hashmap_remove(s->manager->sessions, s->id);
|
||||
|
||||
@@ -278,24 +280,37 @@ static void session_save_devices(Session *s, FILE *f) {
|
||||
}
|
||||
}
|
||||
|
||||
static int trigger_xaccess(void) {
|
||||
static int trigger_xaccess(char * const *extra_devices) {
|
||||
int r;
|
||||
|
||||
if (strv_isempty(extra_devices))
|
||||
return 0;
|
||||
|
||||
_cleanup_strv_free_ char **tags = NULL;
|
||||
r = strv_extend_strv_biconcat(&tags, "xaccess-", (const char * const *)extra_devices, /* suffix= */ NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
|
||||
r = sd_device_enumerator_new(&e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_device_enumerator_add_match_tag(e, "xaccess");
|
||||
STRV_FOREACH(tag, tags) {
|
||||
r = sd_device_enumerator_add_match_tag(e, *tag);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
FOREACH_DEVICE(e, d) {
|
||||
/* Verify that the tag is still in place. */
|
||||
r = sd_device_has_current_tag(d, "xaccess");
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
bool has_xaccess = false;
|
||||
STRV_FOREACH(tag, tags)
|
||||
if (sd_device_has_current_tag(d, *tag)) {
|
||||
has_xaccess = true;
|
||||
break;
|
||||
}
|
||||
if (!has_xaccess)
|
||||
continue;
|
||||
|
||||
/* In case people mistag devices without nodes, we need to ignore this. */
|
||||
@@ -349,14 +364,12 @@ int session_save(Session *s) {
|
||||
"IS_DISPLAY=%s\n"
|
||||
"STATE=%s\n"
|
||||
"REMOTE=%s\n"
|
||||
"EXTRA_DEVICE_ACCESS=%s\n"
|
||||
"LEADER_FD_SAVED=%s\n",
|
||||
s->user->user_record->uid,
|
||||
one_zero(session_is_active(s)),
|
||||
one_zero(s->user->display == s),
|
||||
session_state_to_string(session_get_state(s)),
|
||||
one_zero(s->remote),
|
||||
one_zero(s->extra_device_access),
|
||||
one_zero(s->leader_fd_saved));
|
||||
|
||||
env_file_fputs_assignment(f, "USER=", s->user->user_record->user_name);
|
||||
@@ -414,6 +427,13 @@ int session_save(Session *s) {
|
||||
session_save_devices(s, f);
|
||||
}
|
||||
|
||||
if (s->extra_device_access) {
|
||||
_cleanup_free_ char *extra_devices = strv_join(s->extra_device_access, " ");
|
||||
if (!extra_devices)
|
||||
return log_oom();
|
||||
fprintf(f, "EXTRA_DEVICE_ACCESS=%s\n", extra_devices);
|
||||
}
|
||||
|
||||
r = flink_tmpfile(f, temp_path, s->state_file, LINK_TMPFILE_REPLACE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to move '%s' into place: %m", s->state_file);
|
||||
@@ -586,9 +606,9 @@ int session_load(Session *s) {
|
||||
}
|
||||
|
||||
if (extra_device_access) {
|
||||
k = parse_boolean(extra_device_access);
|
||||
if (k >= 0)
|
||||
s->extra_device_access = k;
|
||||
s->extra_device_access = strv_split(extra_device_access, /* separators= */ NULL);
|
||||
if (!s->extra_device_access)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
if (vtnr)
|
||||
@@ -915,8 +935,7 @@ int session_start(Session *s, sd_bus_message *properties, sd_bus_error *error) {
|
||||
if (s->seat)
|
||||
(void) seat_save(s->seat);
|
||||
|
||||
if (s->extra_device_access)
|
||||
(void) trigger_xaccess();
|
||||
(void) trigger_xaccess(s->extra_device_access);
|
||||
|
||||
/* Send signals */
|
||||
(void) session_send_signal(s, true);
|
||||
@@ -1008,8 +1027,7 @@ int session_stop(Session *s, bool force) {
|
||||
(void) session_save(s);
|
||||
(void) user_save(s->user);
|
||||
|
||||
if (s->extra_device_access)
|
||||
(void) trigger_xaccess();
|
||||
(void) trigger_xaccess(s->extra_device_access);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ typedef struct Session {
|
||||
char *remote_host;
|
||||
char *service;
|
||||
char *desktop;
|
||||
bool extra_device_access;
|
||||
char **extra_device_access;
|
||||
|
||||
char *scope;
|
||||
char *scope_job;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "logind-seat.h"
|
||||
#include "logind-user.h"
|
||||
#include "logind-varlink.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "user-record.h"
|
||||
#include "user-util.h"
|
||||
@@ -145,11 +146,12 @@ typedef struct CreateSessionParameters {
|
||||
int remote;
|
||||
const char *remote_user;
|
||||
const char *remote_host;
|
||||
bool extra_device_access;
|
||||
char **extra_device_access;
|
||||
} CreateSessionParameters;
|
||||
|
||||
static void create_session_parameters_done(CreateSessionParameters *p) {
|
||||
pidref_done(&p->pid);
|
||||
strv_free(p->extra_device_access);
|
||||
}
|
||||
|
||||
static int vl_method_create_session(sd_varlink *link, sd_json_variant *parameters, sd_varlink_method_flags_t flags, void *userdata) {
|
||||
@@ -170,7 +172,7 @@ static int vl_method_create_session(sd_varlink *link, sd_json_variant *parameter
|
||||
{ "Remote", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, offsetof(CreateSessionParameters, remote), 0 },
|
||||
{ "RemoteUser", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(CreateSessionParameters, remote_user), 0 },
|
||||
{ "RemoteHost", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, offsetof(CreateSessionParameters, remote_host), 0 },
|
||||
{ "ExtraDeviceAccess", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, offsetof(CreateSessionParameters, extra_device_access), 0 },
|
||||
{ "ExtraDeviceAccess", SD_JSON_VARIANT_ARRAY, sd_json_dispatch_strv, offsetof(CreateSessionParameters, extra_device_access), 0 },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -180,7 +182,6 @@ static int vl_method_create_session(sd_varlink *link, sd_json_variant *parameter
|
||||
.class = _SESSION_CLASS_INVALID,
|
||||
.type = _SESSION_TYPE_INVALID,
|
||||
.remote = -1,
|
||||
.extra_device_access = false,
|
||||
};
|
||||
|
||||
r = sd_varlink_dispatch(link, parameters, dispatch_table, &p);
|
||||
|
||||
+19
-5
@@ -814,7 +814,7 @@ typedef struct SessionContext {
|
||||
uint32_t vtnr;
|
||||
const char *tty;
|
||||
const char *display;
|
||||
bool extra_device_access;
|
||||
char **extra_device_access;
|
||||
bool remote;
|
||||
const char *remote_user;
|
||||
const char *remote_host;
|
||||
@@ -827,6 +827,10 @@ typedef struct SessionContext {
|
||||
bool incomplete;
|
||||
} SessionContext;
|
||||
|
||||
static void session_context_done(SessionContext *c) {
|
||||
strv_free(c->extra_device_access);
|
||||
}
|
||||
|
||||
static int create_session_message(
|
||||
sd_bus *bus,
|
||||
pam_handle_t *pamh,
|
||||
@@ -1150,7 +1154,7 @@ static int register_session(
|
||||
SD_JSON_BUILD_PAIR_BOOLEAN("Remote", c->remote),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("RemoteUser", c->remote_user),
|
||||
JSON_BUILD_PAIR_STRING_NON_EMPTY("RemoteHost", c->remote_host),
|
||||
JSON_BUILD_PAIR_CONDITION_BOOLEAN(c->extra_device_access, "ExtraDeviceAccess", c->extra_device_access));
|
||||
JSON_BUILD_PAIR_CONDITION_STRV(!strv_isempty(c->extra_device_access), "ExtraDeviceAccess", c->extra_device_access));
|
||||
if (r < 0)
|
||||
return pam_syslog_errno(pamh, LOG_ERR, r,
|
||||
"Failed to issue io.systemd.Login.CreateSession varlink call: %m");
|
||||
@@ -1317,7 +1321,11 @@ static int register_session(
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = update_environment(pamh, "XDG_SESSION_EXTRA_DEVICE_ACCESS", one_zero(c->extra_device_access));
|
||||
_cleanup_free_ char *extra_devices = strv_join(c->extra_device_access, ":");
|
||||
if (!extra_devices)
|
||||
return pam_log_oom(pamh);
|
||||
|
||||
r = update_environment(pamh, "XDG_SESSION_EXTRA_DEVICE_ACCESS", extra_devices);
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
@@ -1769,7 +1777,7 @@ _public_ PAM_EXTERN int pam_sm_open_session(
|
||||
if (r != PAM_SUCCESS)
|
||||
return r;
|
||||
|
||||
SessionContext c = {};
|
||||
_cleanup_(session_context_done) SessionContext c = {};
|
||||
r = pam_get_item_many(
|
||||
pamh,
|
||||
PAM_SERVICE, &c.service,
|
||||
@@ -1787,7 +1795,13 @@ _public_ PAM_EXTERN int pam_sm_open_session(
|
||||
c.desktop = getenv_harder(pamh, "XDG_SESSION_DESKTOP", desktop_pam);
|
||||
c.area = getenv_harder(pamh, "XDG_AREA", area_pam);
|
||||
c.incomplete = getenv_harder_bool(pamh, "XDG_SESSION_INCOMPLETE", false);
|
||||
c.extra_device_access = getenv_harder_bool(pamh, "XDG_SESSION_EXTRA_DEVICE_ACCESS", false);
|
||||
|
||||
const char *extra_device_access = getenv_harder(pamh, "XDG_SESSION_EXTRA_DEVICE_ACCESS", NULL);
|
||||
if (extra_device_access) {
|
||||
c.extra_device_access = strv_split(extra_device_access, ":");
|
||||
if (!c.extra_device_access)
|
||||
return pam_log_oom(pamh);
|
||||
}
|
||||
|
||||
r = pam_get_data_many(
|
||||
pamh,
|
||||
|
||||
@@ -65,10 +65,9 @@ static SD_VARLINK_DEFINE_METHOD(
|
||||
SD_VARLINK_DEFINE_INPUT(RemoteUser, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("Host name of the remote host"),
|
||||
SD_VARLINK_DEFINE_INPUT(RemoteHost, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("If true this session is granted access to additional hardware devices, "
|
||||
"typically useful for remote, graphical sessions. "
|
||||
"This adds access for all devices tagged with \"xaccess\" in udev."),
|
||||
SD_VARLINK_DEFINE_INPUT(ExtraDeviceAccess, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE),
|
||||
SD_VARLINK_FIELD_COMMENT("List of additional hardware devices that this session is granted access to."
|
||||
"For every $ID in the list, this adds access for all devices tagged with \"xaccess-$ID\" in udev."),
|
||||
SD_VARLINK_DEFINE_INPUT(ExtraDeviceAccess, SD_VARLINK_STRING, SD_VARLINK_NULLABLE|SD_VARLINK_ARRAY),
|
||||
SD_VARLINK_FIELD_COMMENT("The identifier string of the session of the user."),
|
||||
SD_VARLINK_DEFINE_OUTPUT(Id, SD_VARLINK_STRING, 0),
|
||||
SD_VARLINK_FIELD_COMMENT("The runtime path ($XDG_RUNTIME_DIR) of the user."),
|
||||
|
||||
@@ -150,8 +150,10 @@ int sd_session_is_active(const char *session);
|
||||
/* Return 1 if the session is remote. */
|
||||
int sd_session_is_remote(const char *session);
|
||||
|
||||
/* Return 1 if the session is granted extra device access. */
|
||||
int sd_session_has_extra_device_access(const char *session);
|
||||
/* Return extra hardware devices that the session is granted access to.
|
||||
* For every $ID in the list, this adds access for all devices tagged with
|
||||
* "xaccess-$ID" in udev. */
|
||||
int sd_session_get_extra_device_access(const char *session, char ***ret_ids);
|
||||
|
||||
/* Get state from session. Possible states: online, active, closing.
|
||||
* This function is a more generic version of sd_session_is_active(). */
|
||||
|
||||
@@ -63,34 +63,58 @@ static int builtin_uaccess(UdevEvent *event, int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_device_has_tag(dev, "xaccess");
|
||||
if (r < 0)
|
||||
return log_device_error_errno(dev, r, "Failed to query device xaccess tag: %m");
|
||||
bool has_xaccess = false;
|
||||
FOREACH_DEVICE_CURRENT_TAG(dev, tag)
|
||||
if (startswith(tag, "xaccess-")) {
|
||||
has_xaccess = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r > 0) {
|
||||
if (has_xaccess) {
|
||||
r = sd_get_sessions(&sessions);
|
||||
if (r < 0)
|
||||
return log_device_error_errno(dev, r, "Failed to list sessions: %m");
|
||||
|
||||
STRV_FOREACH(s, sessions) {
|
||||
_cleanup_free_ char *state = NULL;
|
||||
if (sd_session_get_state(*s, &state) < 0) {
|
||||
r = sd_session_get_state(*s, &state);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(dev, r, "Failed to query state for session %s, ignoring: %m", *s);
|
||||
continue;
|
||||
}
|
||||
if (streq(state, "closing"))
|
||||
continue;
|
||||
r = sd_session_has_extra_device_access(*s);
|
||||
|
||||
r = sd_session_get_uid(*s, &uid);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(dev, r, "Failed to query uid for session %s, ignoring: %m", *s);
|
||||
continue;
|
||||
}
|
||||
|
||||
_cleanup_strv_free_ char **extra_devices = NULL;
|
||||
r = sd_session_get_extra_device_access(*s, &extra_devices);
|
||||
if (r < 0) {
|
||||
log_device_debug_errno(dev, r, "Failed to query extra device access for session %s, ignoring: %m", *s);
|
||||
continue;
|
||||
}
|
||||
if (r == 0)
|
||||
continue;
|
||||
if (sd_session_get_uid(*s, &uid) < 0) {
|
||||
log_device_debug_errno(dev, r, "Failed to query uid for session %s, ignoring: %m", *s);
|
||||
continue;
|
||||
|
||||
bool match = false;
|
||||
STRV_FOREACH(id, extra_devices) {
|
||||
_cleanup_free_ char *tag = strjoin("xaccess-", *id);
|
||||
if (!tag)
|
||||
return log_oom();
|
||||
|
||||
r = sd_device_has_current_tag(dev, tag);
|
||||
if (r < 0)
|
||||
return log_device_error_errno(dev, r, "Failed to query %s tag: %m", tag);
|
||||
if (r > 0) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match)
|
||||
continue;
|
||||
|
||||
if (set_ensure_put(&uids, NULL, UID_TO_PTR(uid)) < 0)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user