Merge pull request #12424 from poettering/logind-brightness

logind: add SetBrightness() bus call as minimal API for setting "leds" and "backlight" kernel class device brightness
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2019-06-12 14:28:09 +02:00 committed by GitHub
commit 58cf79c224
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 703 additions and 202 deletions

7
TODO
View file

@ -27,6 +27,13 @@ Features:
* when killing due to service watchdog timeout maybe detect whether target * when killing due to service watchdog timeout maybe detect whether target
process is under ptracing and then log loudly and continue instead. process is under ptracing and then log loudly and continue instead.
* introduce a new group to own TPM devices
* make rfkill uaccess controllable by default, i.e. steal rule from
gnome-bluetooth and friends
* warn if udev rules files are marked executable (docker?)
* tweak journald context caching. In addition to caching per-process attributes * tweak journald context caching. In addition to caching per-process attributes
keyed by PID, cache per-cgroup attributes (i.e. the various xattrs we read) keyed by PID, cache per-cgroup attributes (i.e. the various xattrs we read)
keyed by cgroup path, and guarded by ctime changes. This should provide us keyed by cgroup path, and guarded by ctime changes. This should provide us

View file

@ -56,6 +56,7 @@ BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_common_errors[] = {
SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS), SD_BUS_ERROR_MAP(BUS_ERROR_OPERATION_IN_PROGRESS, EINPROGRESS),
SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP), SD_BUS_ERROR_MAP(BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP),
SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY), SD_BUS_ERROR_MAP(BUS_ERROR_SESSION_BUSY, EBUSY),
SD_BUS_ERROR_MAP(BUS_ERROR_NOT_YOUR_DEVICE, EPERM),
SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY), SD_BUS_ERROR_MAP(BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED, EALREADY),
SD_BUS_ERROR_MAP(BUS_ERROR_NO_NTP_SUPPORT, EOPNOTSUPP), SD_BUS_ERROR_MAP(BUS_ERROR_NO_NTP_SUPPORT, EOPNOTSUPP),

View file

@ -51,6 +51,7 @@
#define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress" #define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress"
#define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported" #define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported"
#define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy" #define BUS_ERROR_SESSION_BUSY "org.freedesktop.login1.SessionBusy"
#define BUS_ERROR_NOT_YOUR_DEVICE "org.freedesktop.login1.NotYourDevice"
#define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled" #define BUS_ERROR_AUTOMATIC_TIME_SYNC_ENABLED "org.freedesktop.timedate1.AutomaticTimeSyncEnabled"
#define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport" #define BUS_ERROR_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport"

View file

@ -14,6 +14,10 @@ SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat"
SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat" SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat"
SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat" SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat"
# Assign keyboard and LCD backlights to the seat
SUBSYSTEM=="leds", TAG+="seat"
SUBSYSTEM=="backlight", TAG+="seat"
# HyperV currently doesn't do DRM, hence we need to synthesize for HyperV's fb device instead # HyperV currently doesn't do DRM, hence we need to synthesize for HyperV's fb device instead
SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", DRIVERS=="hyperv_fb", TAG+="master-of-seat" SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", DRIVERS=="hyperv_fb", TAG+="master-of-seat"

View file

@ -846,23 +846,11 @@ static int show_session(int argc, char *argv[], void *userdata) {
(void) pager_open(arg_pager_flags); (void) pager_open(arg_pager_flags);
if (argc <= 1) { if (argc <= 1) {
const char *session, *p = "/org/freedesktop/login1/session/self"; /* If no argument is specified inspect the manager itself */
if (properties) if (properties)
/* If no argument is specified inspect the manager itself */
return show_properties(bus, "/org/freedesktop/login1", &new_line); return show_properties(bus, "/org/freedesktop/login1", &new_line);
/* And in the pretty case, show data of the calling session */ return print_session_status_info(bus, "/org/freedesktop/login1/session/auto", &new_line);
session = getenv("XDG_SESSION_ID");
if (session) {
r = get_session_path(bus, session, &error, &path);
if (r < 0)
return log_error_errno(r, "Failed to get session path: %s", bus_error_message(&error, r));
p = path;
}
return print_session_status_info(bus, p, &new_line);
} }
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
@ -895,8 +883,7 @@ static int show_user(int argc, char *argv[], void *userdata) {
(void) pager_open(arg_pager_flags); (void) pager_open(arg_pager_flags);
if (argc <= 1) { if (argc <= 1) {
/* If not argument is specified inspect the manager /* If no argument is specified inspect the manager itself */
* itself */
if (properties) if (properties)
return show_properties(bus, "/org/freedesktop/login1", &new_line); return show_properties(bus, "/org/freedesktop/login1", &new_line);
@ -953,12 +940,11 @@ static int show_seat(int argc, char *argv[], void *userdata) {
(void) pager_open(arg_pager_flags); (void) pager_open(arg_pager_flags);
if (argc <= 1) { if (argc <= 1) {
/* If not argument is specified inspect the manager /* If no argument is specified inspect the manager itself */
* itself */
if (properties) if (properties)
return show_properties(bus, "/org/freedesktop/login1", &new_line); return show_properties(bus, "/org/freedesktop/login1", &new_line);
return print_seat_status_info(bus, "/org/freedesktop/login1/seat/self", &new_line); return print_seat_status_info(bus, "/org/freedesktop/login1/seat/auto", &new_line);
} }
for (i = 1; i < argc; i++) { for (i = 1; i < argc; i++) {
@ -1005,11 +991,8 @@ static int activate(int argc, char *argv[], void *userdata) {
polkit_agent_open_if_enabled(arg_transport, arg_ask_password); polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
if (argc < 2) { if (argc < 2) {
/* No argument? Let's either use $XDG_SESSION_ID (if specified), or an empty
* session name, in which case logind will try to guess our session. */
short_argv[0] = argv[0]; short_argv[0] = argv[0];
short_argv[1] = getenv("XDG_SESSION_ID") ?: (char*) ""; short_argv[1] = (char*) "";
short_argv[2] = NULL; short_argv[2] = NULL;
argv = short_argv; argv = short_argv;
@ -1030,7 +1013,7 @@ static int activate(int argc, char *argv[], void *userdata) {
&error, NULL, &error, NULL,
"s", argv[i]); "s", argv[i]);
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, -r)); return log_error_errno(r, "Failed to issue method call: %s", bus_error_message(&error, r));
} }
return 0; return 0;

View file

@ -8,6 +8,8 @@
#include "conf-parser.h" #include "conf-parser.h"
#include "format-util.h" #include "format-util.h"
#include "logind-action.h" #include "logind-action.h"
#include "logind-dbus.h"
#include "logind-session-dbus.h"
#include "process-util.h" #include "process-util.h"
#include "sleep-config.h" #include "sleep-config.h"
#include "special.h" #include "special.h"

View file

@ -0,0 +1,256 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#include "bus-util.h"
#include "device-util.h"
#include "hash-funcs.h"
#include "logind-brightness.h"
#include "logind.h"
#include "process-util.h"
#include "stdio-util.h"
/* Brightness and LED devices tend to be very slow to write to (often being I2C and such). Writes to the
* sysfs attributes are synchronous, and hence will freeze our process on access. We can't really have that,
* hence we add some complexity: whenever we need to write to the brightness attribute, we do so in a forked
* off process, which terminates when it is done. Watching that process allows us to watch completion of the
* write operation.
*
* To make this even more complex: clients are likely to send us many write requests in a short time-frame
* (because they implement reactive brightness sliders on screen). Let's coalesce writes to make this
* efficient: whenever we get requests to change brightness while we are still writing to the brightness
* attribute, let's remember the request and restart a new one when the initial operation finished. When we
* get another request while one is ongoing and one is pending we'll replace the pending one with the new
* one.
*
* The bus messages are answered when the first write operation finishes that started either due to the
* request or due to a later request that overrode the requested one.
*
* Yes, this is complex, but I don't see an easier way if we want to be both efficient and still support
* completion notification. */
typedef struct BrightnessWriter {
Manager *manager;
sd_device *device;
char *path;
pid_t child;
uint32_t brightness;
bool again;
Set *current_messages;
Set *pending_messages;
sd_event_source* child_event_source;
} BrightnessWriter;
static void brightness_writer_free(BrightnessWriter *w) {
if (!w)
return;
if (w->manager && w->path)
(void) hashmap_remove_value(w->manager->brightness_writers, w->path, w);
sd_device_unref(w->device);
free(w->path);
set_free(w->current_messages);
set_free(w->pending_messages);
w->child_event_source = sd_event_source_unref(w->child_event_source);
free(w);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(BrightnessWriter*, brightness_writer_free);
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
brightness_writer_hash_ops,
char,
string_hash_func,
string_compare_func,
BrightnessWriter,
brightness_writer_free);
static void brightness_writer_reply(BrightnessWriter *w, int error) {
int r;
assert(w);
for (;;) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
m = set_steal_first(w->current_messages);
if (!m)
break;
if (error == 0)
r = sd_bus_reply_method_return(m, NULL);
else
r = sd_bus_reply_method_errnof(m, error, "Failed to write to brightness device: %m");
if (r < 0)
log_warning_errno(r, "Failed to send method reply, ignoring: %m");
}
}
static int brightness_writer_fork(BrightnessWriter *w);
static int on_brightness_writer_exit(sd_event_source *s, const siginfo_t *si, void *userdata) {
BrightnessWriter *w = userdata;
int r;
assert(s);
assert(si);
assert(w);
assert(si->si_pid == w->child);
w->child = 0;
w->child_event_source = sd_event_source_unref(w->child_event_source);
brightness_writer_reply(w,
si->si_code == CLD_EXITED &&
si->si_status == EXIT_SUCCESS ? 0 : -EPROTO);
if (w->again) {
/* Another request to change the brightness has been queued. Act on it, but make the pending
* messages the current ones. */
w->again = false;
set_free(w->current_messages);
w->current_messages = TAKE_PTR(w->pending_messages);
r = brightness_writer_fork(w);
if (r >= 0)
return 0;
brightness_writer_reply(w, r);
}
brightness_writer_free(w);
return 0;
}
static int brightness_writer_fork(BrightnessWriter *w) {
int r;
assert(w);
assert(w->manager);
assert(w->child == 0);
assert(!w->child_event_source);
r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG, &w->child);
if (r < 0)
return r;
if (r == 0) {
char brs[DECIMAL_STR_MAX(uint32_t)+1];
/* Child */
xsprintf(brs, "%" PRIu32, w->brightness);
r = sd_device_set_sysattr_value(w->device, "brightness", brs);
if (r < 0) {
log_device_error_errno(w->device, r, "Failed to write brightness to device: %m");
_exit(EXIT_FAILURE);
}
_exit(EXIT_SUCCESS);
}
r = sd_event_add_child(w->manager->event, &w->child_event_source, w->child, WEXITED, on_brightness_writer_exit, w);
if (r < 0)
return log_error_errno(r, "Failed to watch brightness writer child " PID_FMT ": %m", w->child);
return 0;
}
static int set_add_message(Set **set, sd_bus_message *message) {
int r;
assert(set);
if (!message)
return 0;
r = sd_bus_message_get_expect_reply(message);
if (r <= 0)
return r;
r = set_ensure_allocated(set, &bus_message_hash_ops);
if (r < 0)
return r;
r = set_put(*set, message);
if (r < 0)
return r;
sd_bus_message_ref(message);
return 1;
}
int manager_write_brightness(
Manager *m,
sd_device *device,
uint32_t brightness,
sd_bus_message *message) {
_cleanup_(brightness_writer_freep) BrightnessWriter *w = NULL;
BrightnessWriter *existing;
const char *path;
int r;
assert(m);
assert(device);
r = sd_device_get_syspath(device, &path);
if (r < 0)
return log_device_error_errno(device, r, "Failed to get sysfs path for brightness device: %m");
existing = hashmap_get(m->brightness_writers, path);
if (existing) {
/* There's already a writer for this device. Let's update it with the new brightness, and add
* our message to the set of message to reply when done. */
r = set_add_message(&existing->pending_messages, message);
if (r < 0)
return log_error_errno(r, "Failed to add message to set: %m");
/* We overide any previously requested brightness here: we coalesce writes, and the newest
* requested brightness is the one we'll put into effect. */
existing->brightness = brightness;
existing->again = true; /* request another iteration of the writer when the current one is
* complete */
return 0;
}
r = hashmap_ensure_allocated(&m->brightness_writers, &brightness_writer_hash_ops);
if (r < 0)
return log_oom();
w = new(BrightnessWriter, 1);
if (!w)
return log_oom();
*w = (BrightnessWriter) {
.device = sd_device_ref(device),
.path = strdup(path),
.brightness = brightness,
};
if (!w->path)
return log_oom();
r = hashmap_put(m->brightness_writers, w->path, w);
if (r < 0)
return log_error_errno(r, "Failed to add brightness writer to hashmap: %m");
w->manager = m;
r = set_add_message(&w->current_messages, message);
if (r < 0)
return log_error_errno(r, "Failed to add message to set: %m");
r = brightness_writer_fork(w);
if (r < 0)
return r;
TAKE_PTR(w);
return 0;
}

View file

@ -0,0 +1,9 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-bus.h"
#include "sd-device.h"
#include "logind.h"
int manager_write_brightness(Manager *m, sd_device *device, uint32_t brightness, sd_bus_message *message);

View file

@ -27,6 +27,10 @@
#include "fileio.h" #include "fileio.h"
#include "format-util.h" #include "format-util.h"
#include "fs-util.h" #include "fs-util.h"
#include "logind-dbus.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-user-dbus.h"
#include "logind.h" #include "logind.h"
#include "missing_capability.h" #include "missing_capability.h"
#include "mkdir.h" #include "mkdir.h"
@ -46,47 +50,78 @@
#include "utmp-wtmp.h" #include "utmp-wtmp.h"
#include "virt.h" #include "virt.h"
static int get_sender_session(Manager *m, sd_bus_message *message, sd_bus_error *error, Session **ret) { static int get_sender_session(
Manager *m,
sd_bus_message *message,
bool consult_display,
sd_bus_error *error,
Session **ret) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
Session *session = NULL;
const char *name; const char *name;
Session *session;
int r; int r;
/* Get client login session. This is not what you are looking for these days, /* Acquire the sender's session. This first checks if the sending process is inside a session itself,
* as apps may instead belong to a user service unit. This includes terminal * and returns that. If not and 'consult_display' is true, this returns the display session of the
* emulators and hence command-line apps. */ * owning user of the caller. */
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
r = sd_bus_query_sender_creds(message,
SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT|
(consult_display ? SD_BUS_CREDS_OWNER_UID : 0), &creds);
if (r < 0) if (r < 0)
return r; return r;
r = sd_bus_creds_get_session(creds, &name); r = sd_bus_creds_get_session(creds, &name);
if (r == -ENXIO) if (r < 0) {
goto err_no_session; if (r != -ENXIO)
if (r < 0) return r;
return r;
if (consult_display) {
uid_t uid;
r = sd_bus_creds_get_owner_uid(creds, &uid);
if (r < 0) {
if (r != -ENXIO)
return r;
} else {
User *user;
user = hashmap_get(m->users, UID_TO_PTR(uid));
if (user)
session = user->display;
}
}
} else
session = hashmap_get(m->sessions, name);
session = hashmap_get(m->sessions, name);
if (!session) if (!session)
goto err_no_session; return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
consult_display ?
"Caller does not belong to any known session and doesn't own any suitable session." :
"Caller does not belong to any known session.");
*ret = session; *ret = session;
return 0; return 0;
err_no_session:
return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
"Caller does not belong to any known session");
} }
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) { int manager_get_session_from_creds(
Manager *m,
sd_bus_message *message,
const char *name,
sd_bus_error *error,
Session **ret) {
Session *session; Session *session;
assert(m); assert(m);
assert(message); assert(message);
assert(ret); assert(ret);
if (isempty(name)) if (SEAT_IS_SELF(name)) /* the caller's own session */
return get_sender_session(m, message, error, ret); return get_sender_session(m, message, false, error, ret);
if (SEAT_IS_AUTO(name)) /* The caller's own session if they have one, otherwise their user's display session */
return get_sender_session(m, message, true, error, ret);
session = hashmap_get(m->sessions, name); session = hashmap_get(m->sessions, name);
if (!session) if (!session)
@ -97,7 +132,6 @@ int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const ch
} }
static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) { static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *error, User **ret) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
uid_t uid; uid_t uid;
User *user; User *user;
@ -109,21 +143,20 @@ static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *er
return r; return r;
r = sd_bus_creds_get_owner_uid(creds, &uid); r = sd_bus_creds_get_owner_uid(creds, &uid);
if (r == -ENXIO) if (r < 0) {
goto err_no_user; if (r != -ENXIO)
if (r < 0) return r;
return r;
user = NULL;
} else
user = hashmap_get(m->users, UID_TO_PTR(uid));
user = hashmap_get(m->users, UID_TO_PTR(uid));
if (!user) if (!user)
goto err_no_user; return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
"Caller does not belong to any logged in or lingering user");
*ret = user; *ret = user;
return 0; return 0;
err_no_user:
return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
"Caller does not belong to any logged in user or lingering user");
} }
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) { int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
@ -145,7 +178,13 @@ int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid,
return 0; return 0;
} }
int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) { int manager_get_seat_from_creds(
Manager *m,
sd_bus_message *message,
const char *name,
sd_bus_error *error,
Seat **ret) {
Seat *seat; Seat *seat;
int r; int r;
@ -153,16 +192,17 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char
assert(message); assert(message);
assert(ret); assert(ret);
if (isempty(name)) { if (SEAT_IS_SELF(name) || SEAT_IS_AUTO(name)) {
Session *session; Session *session;
r = manager_get_session_from_creds(m, message, NULL, error, &session); /* Use these special seat names as session names */
r = manager_get_session_from_creds(m, message, name, error, &session);
if (r < 0) if (r < 0)
return r; return r;
seat = session->seat; seat = session->seat;
if (!seat) if (!seat)
return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat."); return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session '%s' has no seat.", session->id);
} else { } else {
seat = hashmap_get(m->seats, name); seat = hashmap_get(m->seats, name);
if (!seat) if (!seat)
@ -809,11 +849,9 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (asprintf(&id, "%"PRIu32, audit_id) < 0) if (asprintf(&id, "%"PRIu32, audit_id) < 0)
return -ENOMEM; return -ENOMEM;
/* Wut? There's already a session by this name and we /* Wut? There's already a session by this name and we didn't find it above? Weird, then let's
* didn't find it above? Weird, then let's not trust * not trust the audit data and let's better register a new ID */
* the audit data and let's better register a new if (hashmap_contains(m->sessions, id)) {
* ID */
if (hashmap_get(m->sessions, id)) {
log_warning("Existing logind session ID %s used by new audit session, ignoring.", id); log_warning("Existing logind session ID %s used by new audit session, ignoring.", id);
audit_id = AUDIT_SESSION_INVALID; audit_id = AUDIT_SESSION_INVALID;
id = mfree(id); id = mfree(id);
@ -827,9 +865,13 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus
if (asprintf(&id, "c%lu", ++m->session_counter) < 0) if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
return -ENOMEM; return -ENOMEM;
} while (hashmap_get(m->sessions, id)); } while (hashmap_contains(m->sessions, id));
} }
/* The generated names should not clash with 'auto' or 'self' */
assert(!SESSION_IS_SELF(id));
assert(!SESSION_IS_AUTO(id));
/* If we are not watching utmp already, try again */ /* If we are not watching utmp already, try again */
manager_reconnect_utmp(m); manager_reconnect_utmp(m);
@ -990,8 +1032,7 @@ static int method_activate_session_on_seat(sd_bus_message *message, void *userda
assert(message); assert(message);
assert(m); assert(m);
/* Same as ActivateSession() but refuses to work if /* Same as ActivateSession() but refuses to work if the seat doesn't match */
* the seat doesn't match */
r = sd_bus_message_read(message, "ss", &session_name, &seat_name); r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
if (r < 0) if (r < 0)
@ -1367,11 +1408,22 @@ static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_
if (r < 0) if (r < 0)
return r; return r;
if (!path_is_normalized(sysfs))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", sysfs);
if (!path_startswith(sysfs, "/sys")) if (!path_startswith(sysfs, "/sys"))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
if (!seat_name_is_valid(seat)) if (SEAT_IS_SELF(seat) || SEAT_IS_AUTO(seat)) {
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat); Seat *found;
r = manager_get_seat_from_creds(m, message, seat, error, &found);
if (r < 0)
return r;
seat = found->id;
} else if (!seat_name_is_valid(seat)) /* Note that a seat does not have to exist yet for this operation to succeed */
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat name %s is not valid", seat);
r = bus_verify_polkit_async( r = bus_verify_polkit_async(
message, message,

31
src/login/logind-dbus.h Normal file
View file

@ -0,0 +1,31 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-bus.h"
#include "logind.h"
#include "logind-session.h"
#include "logind-user.h"
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret);
int manager_dispatch_delayed(Manager *manager, bool timeout);
int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name, InhibitWhat w, sd_bus_error *error);
int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error);
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error);
int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error);
int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *error);

View file

@ -4,6 +4,7 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "logind-device.h" #include "logind-device.h"
#include "logind-seat-dbus.h"
#include "util.h" #include "util.h"
Device* device_new(Manager *m, const char *sysfs, bool master) { Device* device_new(Manager *m, const char *sysfs, bool master) {

View file

@ -13,6 +13,7 @@
#include "fd-util.h" #include "fd-util.h"
#include "fileio.h" #include "fileio.h"
#include "format-util.h" #include "format-util.h"
#include "logind-dbus.h"
#include "logind-inhibit.h" #include "logind-inhibit.h"
#include "mkdir.h" #include "mkdir.h"
#include "parse-util.h" #include "parse-util.h"

View file

@ -7,7 +7,10 @@
#include "bus-common-errors.h" #include "bus-common-errors.h"
#include "bus-label.h" #include "bus-label.h"
#include "bus-util.h" #include "bus-util.h"
#include "logind-dbus.h"
#include "logind-seat-dbus.h"
#include "logind-seat.h" #include "logind-seat.h"
#include "logind-session-dbus.h"
#include "logind.h" #include "logind.h"
#include "missing_capability.h" #include "missing_capability.h"
#include "strv.h" #include "strv.h"
@ -255,7 +258,10 @@ const sd_bus_vtable seat_vtable[] = {
}; };
int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
_cleanup_free_ char *e = NULL;
sd_bus_message *message;
Manager *m = userdata; Manager *m = userdata;
const char *p;
Seat *seat; Seat *seat;
int r; int r;
@ -265,32 +271,25 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void
assert(found); assert(found);
assert(m); assert(m);
if (streq(path, "/org/freedesktop/login1/seat/self")) { p = startswith(path, "/org/freedesktop/login1/seat/");
sd_bus_message *message; if (!p)
return 0;
message = sd_bus_get_current_message(bus); e = bus_label_unescape(p);
if (!message) if (!e)
return 0; return -ENOMEM;
r = manager_get_seat_from_creds(m, message, NULL, error, &seat); message = sd_bus_get_current_message(bus);
if (r < 0) if (!message)
return r; return 0;
} else {
_cleanup_free_ char *e = NULL;
const char *p;
p = startswith(path, "/org/freedesktop/login1/seat/"); r = manager_get_seat_from_creds(m, message, e, error, &seat);
if (!p) if (r == -ENXIO) {
return 0; sd_bus_error_free(error);
return 0;
e = bus_label_unescape(p);
if (!e)
return -ENOMEM;
seat = hashmap_get(m->seats, e);
if (!seat)
return 0;
} }
if (r < 0)
return r;
*found = seat; *found = seat;
return 1; return 1;
@ -335,25 +334,47 @@ int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
message = sd_bus_get_current_message(bus); message = sd_bus_get_current_message(bus);
if (message) { if (message) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *name;
Session *session;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
if (r >= 0) { if (r >= 0) {
bool may_auto = false;
const char *name;
r = sd_bus_creds_get_session(creds, &name); r = sd_bus_creds_get_session(creds, &name);
if (r >= 0) { if (r >= 0) {
Session *session;
session = hashmap_get(m->sessions, name); session = hashmap_get(m->sessions, name);
if (session && session->seat) { if (session && session->seat) {
r = strv_extend(&l, "/org/freedesktop/login1/seat/self"); r = strv_extend(&l, "/org/freedesktop/login1/seat/self");
if (r < 0) if (r < 0)
return r; return r;
may_auto = true;
} }
} }
if (!may_auto) {
uid_t uid;
r = sd_bus_creds_get_owner_uid(creds, &uid);
if (r >= 0) {
User *user;
user = hashmap_get(m->users, UID_TO_PTR(uid));
may_auto = user && user->display && user->display->seat;
}
}
if (may_auto) {
r = strv_extend(&l, "/org/freedesktop/login1/seat/auto");
if (r < 0)
return r;
}
} }
} }
*nodes = TAKE_PTR(l); *nodes = TAKE_PTR(l);
return 1; return 1;
} }

View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-bus.h"
#include "logind-seat.h"
extern const sd_bus_vtable seat_vtable[];
int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
char *seat_bus_path(Seat *s);
int seat_send_signal(Seat *s, bool new_seat);
int seat_send_changed(Seat *s, const char *properties, ...) _sentinel_;
int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);

View file

@ -13,7 +13,9 @@
#include "fileio.h" #include "fileio.h"
#include "format-util.h" #include "format-util.h"
#include "logind-acl.h" #include "logind-acl.h"
#include "logind-seat-dbus.h"
#include "logind-seat.h" #include "logind-seat.h"
#include "logind-session-dbus.h"
#include "mkdir.h" #include "mkdir.h"
#include "parse-util.h" #include "parse-util.h"
#include "stdio-util.h" #include "stdio-util.h"

View file

@ -67,13 +67,10 @@ void seat_add_to_gc_queue(Seat *s);
bool seat_name_is_valid(const char *name); bool seat_name_is_valid(const char *name);
extern const sd_bus_vtable seat_vtable[]; static inline bool SEAT_IS_SELF(const char *name) {
return isempty(name) || streq(name, "self");
}
int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error); static inline bool SEAT_IS_AUTO(const char *name) {
int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error); return streq_ptr(name, "auto");
char *seat_bus_path(Seat *s); }
int seat_send_signal(Seat *s, bool new_seat);
int seat_send_changed(Seat *s, const char *properties, ...) _sentinel_;
int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);

View file

@ -8,13 +8,20 @@
#include "bus-label.h" #include "bus-label.h"
#include "bus-util.h" #include "bus-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "logind-brightness.h"
#include "logind-dbus.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-session-device.h" #include "logind-session-device.h"
#include "logind-session.h" #include "logind-session.h"
#include "logind-user-dbus.h"
#include "logind.h" #include "logind.h"
#include "missing_capability.h" #include "missing_capability.h"
#include "path-util.h"
#include "signal-util.h" #include "signal-util.h"
#include "stat-util.h" #include "stat-util.h"
#include "strv.h" #include "strv.h"
#include "user-util.h"
#include "util.h" #include "util.h"
static int property_get_user( static int property_get_user(
@ -479,6 +486,57 @@ static int method_pause_device_complete(sd_bus_message *message, void *userdata,
return sd_bus_reply_method_return(message, NULL); return sd_bus_reply_method_return(message, NULL);
} }
static int method_set_brightness(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
_cleanup_(sd_device_unrefp) sd_device *d = NULL;
const char *subsystem, *name, *seat;
Session *s = userdata;
uint32_t brightness;
uid_t uid;
int r;
assert(message);
assert(s);
r = sd_bus_message_read(message, "ssu", &subsystem, &name, &brightness);
if (r < 0)
return r;
if (!STR_IN_SET(subsystem, "backlight", "leds"))
return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Subsystem type %s not supported, must be one of 'backlight' or 'leds'.", subsystem);
if (!filename_is_valid(name))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Not a valid device name %s, refusing.", name);
if (!s->seat)
return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Your session has no seat, refusing.");
if (s->seat->active != s)
return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Session is not in foreground, refusing.");
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_euid(creds, &uid);
if (r < 0)
return r;
if (uid != 0 && uid != s->user->uid)
return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may change brightness.");
r = sd_device_new_from_subsystem_sysname(&d, subsystem, name);
if (r < 0)
return sd_bus_error_set_errnof(error, r, "Failed to open device %s:%s: %m", subsystem, name);
if (sd_device_get_property_value(d, "ID_SEAT", &seat) >= 0 && !streq_ptr(seat, s->seat->id))
return sd_bus_error_setf(error, BUS_ERROR_NOT_YOUR_DEVICE, "Device %s:%s does not belong to your seat %s, refusing.", subsystem, name, s->seat->id);
r = manager_write_brightness(s->manager, d, brightness, message);
if (r < 0)
return r;
return 1;
}
const sd_bus_vtable session_vtable[] = { const sd_bus_vtable session_vtable[] = {
SD_BUS_VTABLE_START(0), SD_BUS_VTABLE_START(0),
@ -519,6 +577,7 @@ const sd_bus_vtable session_vtable[] = {
SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetBrightness", "ssu", NULL, method_set_brightness, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("PauseDevice", "uus", 0), SD_BUS_SIGNAL("PauseDevice", "uus", 0),
SD_BUS_SIGNAL("ResumeDevice", "uuh", 0), SD_BUS_SIGNAL("ResumeDevice", "uuh", 0),
@ -529,8 +588,11 @@ const sd_bus_vtable session_vtable[] = {
}; };
int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
_cleanup_free_ char *e = NULL;
sd_bus_message *message;
Manager *m = userdata; Manager *m = userdata;
Session *session; Session *session;
const char *p;
int r; int r;
assert(bus); assert(bus);
@ -539,32 +601,25 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo
assert(found); assert(found);
assert(m); assert(m);
if (streq(path, "/org/freedesktop/login1/session/self")) { p = startswith(path, "/org/freedesktop/login1/session/");
sd_bus_message *message; if (!p)
return 0;
message = sd_bus_get_current_message(bus); e = bus_label_unescape(p);
if (!message) if (!e)
return 0; return -ENOMEM;
r = manager_get_session_from_creds(m, message, NULL, error, &session); message = sd_bus_get_current_message(bus);
if (r < 0) if (!message)
return r; return 0;
} else {
_cleanup_free_ char *e = NULL;
const char *p;
p = startswith(path, "/org/freedesktop/login1/session/"); r = manager_get_session_from_creds(m, message, e, error, &session);
if (!p) if (r == -ENXIO) {
return 0; sd_bus_error_free(error);
return 0;
e = bus_label_unescape(p);
if (!e)
return -ENOMEM;
session = hashmap_get(m->sessions, e);
if (!session)
return 0;
} }
if (r < 0)
return r;
*found = session; *found = session;
return 1; return 1;
@ -609,10 +664,12 @@ int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
message = sd_bus_get_current_message(bus); message = sd_bus_get_current_message(bus);
if (message) { if (message) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
const char *name;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
if (r >= 0) { if (r >= 0) {
bool may_auto = false;
const char *name;
r = sd_bus_creds_get_session(creds, &name); r = sd_bus_creds_get_session(creds, &name);
if (r >= 0) { if (r >= 0) {
session = hashmap_get(m->sessions, name); session = hashmap_get(m->sessions, name);
@ -620,13 +677,32 @@ int session_node_enumerator(sd_bus *bus, const char *path, void *userdata, char
r = strv_extend(&l, "/org/freedesktop/login1/session/self"); r = strv_extend(&l, "/org/freedesktop/login1/session/self");
if (r < 0) if (r < 0)
return r; return r;
may_auto = true;
} }
} }
if (!may_auto) {
uid_t uid;
r = sd_bus_creds_get_owner_uid(creds, &uid);
if (r >= 0) {
User *user;
user = hashmap_get(m->users, UID_TO_PTR(uid));
may_auto = user && user->display;
}
}
if (may_auto) {
r = strv_extend(&l, "/org/freedesktop/login1/session/auto");
if (r < 0)
return r;
}
} }
} }
*nodes = TAKE_PTR(l); *nodes = TAKE_PTR(l);
return 1; return 1;
} }

View file

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-bus.h"
#include "logind-session.h"
extern const sd_bus_vtable session_vtable[];
int session_node_enumerator(sd_bus *bus, const char *path,void *userdata, char ***nodes, sd_bus_error *error);
int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
char *session_bus_path(Session *s);
int session_send_signal(Session *s, bool new_session);
int session_send_changed(Session *s, const char *properties, ...) _sentinel_;
int session_send_lock(Session *s, bool lock);
int session_send_lock_all(Manager *m, bool lock);
int session_send_create_reply(Session *s, sd_bus_error *error);
int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);

View file

@ -7,14 +7,15 @@
#include <sys/types.h> #include <sys/types.h>
#include "sd-device.h" #include "sd-device.h"
#include "sd-daemon.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "bus-util.h" #include "bus-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "logind-session-dbus.h"
#include "logind-session-device.h" #include "logind-session-device.h"
#include "missing.h" #include "missing.h"
#include "parse-util.h" #include "parse-util.h"
#include "sd-daemon.h"
#include "util.h" #include "util.h"
enum SessionDeviceNotifications { enum SessionDeviceNotifications {

View file

@ -22,7 +22,11 @@
#include "fileio.h" #include "fileio.h"
#include "format-util.h" #include "format-util.h"
#include "io-util.h" #include "io-util.h"
#include "logind-dbus.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-session.h" #include "logind-session.h"
#include "logind-user-dbus.h"
#include "mkdir.h" #include "mkdir.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"

View file

@ -7,6 +7,7 @@ typedef enum KillWho KillWho;
#include "list.h" #include "list.h"
#include "login-util.h" #include "login-util.h"
#include "logind-user.h" #include "logind-user.h"
#include "string-util.h"
typedef enum SessionState { typedef enum SessionState {
SESSION_OPENING, /* Session scope is being created */ SESSION_OPENING, /* Session scope is being created */
@ -145,18 +146,6 @@ int session_kill(Session *s, KillWho who, int signo);
SessionState session_get_state(Session *u); SessionState session_get_state(Session *u);
extern const sd_bus_vtable session_vtable[];
int session_node_enumerator(sd_bus *bus, const char *path,void *userdata, char ***nodes, sd_bus_error *error);
int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
char *session_bus_path(Session *s);
int session_send_signal(Session *s, bool new_session);
int session_send_changed(Session *s, const char *properties, ...) _sentinel_;
int session_send_lock(Session *s, bool lock);
int session_send_lock_all(Manager *m, bool lock);
int session_send_create_reply(Session *s, sd_bus_error *error);
const char* session_state_to_string(SessionState t) _const_; const char* session_state_to_string(SessionState t) _const_;
SessionState session_state_from_string(const char *s) _pure_; SessionState session_state_from_string(const char *s) _pure_;
@ -179,7 +168,10 @@ bool session_is_controller(Session *s, const char *sender);
int session_set_controller(Session *s, const char *sender, bool force, bool prepare); int session_set_controller(Session *s, const char *sender, bool force, bool prepare);
void session_drop_controller(Session *s); void session_drop_controller(Session *s);
int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error); static inline bool SESSION_IS_SELF(const char *name) {
int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error); return isempty(name) || streq(name, "self");
int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error); }
int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
static inline bool SESSION_IS_AUTO(const char *name) {
return streq_ptr(name, "auto");
}

View file

@ -6,6 +6,9 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "bus-util.h" #include "bus-util.h"
#include "format-util.h" #include "format-util.h"
#include "logind-dbus.h"
#include "logind-session-dbus.h"
#include "logind-user-dbus.h"
#include "logind-user.h" #include "logind-user.h"
#include "logind.h" #include "logind.h"
#include "missing_capability.h" #include "missing_capability.h"
@ -245,6 +248,10 @@ int user_object_find(sd_bus *bus, const char *path, const char *interface, void
return 0; return 0;
r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user); r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
if (r == -ENXIO) {
sd_bus_error_free(error);
return 0;
}
if (r < 0) if (r < 0)
return r; return r;
} else { } else {
@ -305,10 +312,11 @@ int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***
message = sd_bus_get_current_message(bus); message = sd_bus_get_current_message(bus);
if (message) { if (message) {
_cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
uid_t uid;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds); r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
if (r >= 0) { if (r >= 0) {
uid_t uid;
r = sd_bus_creds_get_owner_uid(creds, &uid); r = sd_bus_creds_get_owner_uid(creds, &uid);
if (r >= 0) { if (r >= 0) {
user = hashmap_get(m->users, UID_TO_PTR(uid)); user = hashmap_get(m->users, UID_TO_PTR(uid));

View file

@ -0,0 +1,17 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include "sd-bus.h"
#include "logind-user.h"
extern const sd_bus_vtable user_vtable[];
int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
char *user_bus_path(User *s);
int user_send_signal(User *u, bool new_user);
int user_send_changed(User *u, const char *properties, ...) _sentinel_;
int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);

View file

@ -19,7 +19,9 @@
#include "hashmap.h" #include "hashmap.h"
#include "label.h" #include "label.h"
#include "limits-util.h" #include "limits-util.h"
#include "logind-dbus.h"
#include "logind-user.h" #include "logind-user.h"
#include "logind-user-dbus.h"
#include "mkdir.h" #include "mkdir.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
@ -663,12 +665,12 @@ static bool elect_display_filter(Session *s) {
/* Return true if the session is a candidate for the users primary session or display. */ /* Return true if the session is a candidate for the users primary session or display. */
assert(s); assert(s);
return s->class == SESSION_USER && s->started && !s->stopping; return IN_SET(s->class, SESSION_USER, SESSION_GREETER) && s->started && !s->stopping;
} }
static int elect_display_compare(Session *s1, Session *s2) { static int elect_display_compare(Session *s1, Session *s2) {
/* Indexed by SessionType. Lower numbers mean more preferred. */ /* Indexed by SessionType. Lower numbers mean more preferred. */
const int type_ranks[_SESSION_TYPE_MAX] = { static const int type_ranks[_SESSION_TYPE_MAX] = {
[SESSION_UNSPECIFIED] = 0, [SESSION_UNSPECIFIED] = 0,
[SESSION_TTY] = -2, [SESSION_TTY] = -2,
[SESSION_X11] = -3, [SESSION_X11] = -3,

View file

@ -69,18 +69,7 @@ int user_check_linger_file(User *u);
void user_elect_display(User *u); void user_elect_display(User *u);
void user_update_last_session_timer(User *u); void user_update_last_session_timer(User *u);
extern const sd_bus_vtable user_vtable[];
int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
char *user_bus_path(User *s);
int user_send_signal(User *u, bool new_user);
int user_send_changed(User *u, const char *properties, ...) _sentinel_;
const char* user_state_to_string(UserState s) _const_; const char* user_state_to_string(UserState s) _const_;
UserState user_state_from_string(const char *s) _pure_; UserState user_state_from_string(const char *s) _pure_;
int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
CONFIG_PARSER_PROTOTYPE(config_parse_compat_user_tasks_max); CONFIG_PARSER_PROTOTYPE(config_parse_compat_user_tasks_max);

View file

@ -18,6 +18,10 @@
#include "fd-util.h" #include "fd-util.h"
#include "format-util.h" #include "format-util.h"
#include "fs-util.h" #include "fs-util.h"
#include "logind-dbus.h"
#include "logind-seat-dbus.h"
#include "logind-session-dbus.h"
#include "logind-user-dbus.h"
#include "logind.h" #include "logind.h"
#include "main-func.h" #include "main-func.h"
#include "parse-util.h" #include "parse-util.h"
@ -44,10 +48,9 @@ static int manager_new(Manager **ret) {
*m = (Manager) { *m = (Manager) {
.console_active_fd = -1, .console_active_fd = -1,
.reserve_vt_fd = -1, .reserve_vt_fd = -1,
.idle_action_not_before_usec = now(CLOCK_MONOTONIC),
}; };
m->idle_action_not_before_usec = now(CLOCK_MONOTONIC);
m->devices = hashmap_new(&string_hash_ops); m->devices = hashmap_new(&string_hash_ops);
m->seats = hashmap_new(&string_hash_ops); m->seats = hashmap_new(&string_hash_ops);
m->sessions = hashmap_new(&string_hash_ops); m->sessions = hashmap_new(&string_hash_ops);
@ -118,6 +121,7 @@ static Manager* manager_unref(Manager *m) {
hashmap_free(m->users); hashmap_free(m->users);
hashmap_free(m->inhibitors); hashmap_free(m->inhibitors);
hashmap_free(m->buttons); hashmap_free(m->buttons);
hashmap_free(m->brightness_writers);
hashmap_free(m->user_units); hashmap_free(m->user_units);
hashmap_free(m->session_units); hashmap_free(m->session_units);
@ -1215,7 +1219,7 @@ static int run(int argc, char *argv[]) {
(void) mkdir_label("/run/systemd/users", 0755); (void) mkdir_label("/run/systemd/users", 0755);
(void) mkdir_label("/run/systemd/sessions", 0755); (void) mkdir_label("/run/systemd/sessions", 0755);
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, -1) >= 0); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGHUP, SIGTERM, SIGINT, SIGCHLD, -1) >= 0);
r = manager_new(&m); r = manager_new(&m);
if (r < 0) if (r < 0)

View file

@ -31,6 +31,7 @@ struct Manager {
Hashmap *users; Hashmap *users;
Hashmap *inhibitors; Hashmap *inhibitors;
Hashmap *buttons; Hashmap *buttons;
Hashmap *brightness_writers;
LIST_HEAD(Seat, seat_gc_queue); LIST_HEAD(Seat, seat_gc_queue);
LIST_HEAD(Session, session_gc_queue); LIST_HEAD(Session, session_gc_queue);
@ -158,24 +159,6 @@ void manager_reconnect_utmp(Manager *m);
extern const sd_bus_vtable manager_vtable[]; extern const sd_bus_vtable manager_vtable[];
int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error);
int match_name_owner_changed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name, InhibitWhat w, sd_bus_error *error);
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job);
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error);
int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error);
int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *error);
/* gperf lookup function */ /* gperf lookup function */
const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length); const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length);
@ -184,11 +167,5 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until);
CONFIG_PARSER_PROTOTYPE(config_parse_n_autovts); CONFIG_PARSER_PROTOTYPE(config_parse_n_autovts);
CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size); CONFIG_PARSER_PROTOTYPE(config_parse_tmpfs_size);
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret);
int manager_setup_wall_message_timer(Manager *m); int manager_setup_wall_message_timer(Manager *m);
bool logind_wall_tty_filter(const char *tty, void *userdata); bool logind_wall_tty_filter(const char *tty, void *userdata);
int manager_dispatch_delayed(Manager *manager, bool timeout);

View file

@ -12,29 +12,35 @@ logind_gperf_c = custom_target(
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
liblogind_core_sources = files(''' liblogind_core_sources = files('''
logind-core.c logind-acl.h
logind-device.c
logind-device.h
logind-button.c
logind-button.h
logind-action.c logind-action.c
logind-action.h logind-action.h
logind-seat.c logind-brightness.c
logind-seat.h logind-brightness.h
logind-session.c logind-button.c
logind-session.h logind-button.h
logind-session-device.c logind-core.c
logind-session-device.h logind-dbus.c
logind-user.c logind-dbus.h
logind-user.h logind-device.c
logind-device.h
logind-inhibit.c logind-inhibit.c
logind-inhibit.h logind-inhibit.h
logind-dbus.c
logind-session-dbus.c
logind-seat-dbus.c logind-seat-dbus.c
logind-seat-dbus.h
logind-seat.c
logind-seat.h
logind-session-dbus.c
logind-session-dbus.h
logind-session-device.c
logind-session-device.h
logind-session.c
logind-session.h
logind-user-dbus.c logind-user-dbus.c
logind-user-dbus.h
logind-user.c
logind-user.h
logind-utmp.c logind-utmp.c
logind-acl.h
'''.split()) '''.split())
liblogind_core_sources += [logind_gperf_c] liblogind_core_sources += [logind_gperf_c]

View file

@ -302,6 +302,10 @@
send_interface="org.freedesktop.login1.Session" send_interface="org.freedesktop.login1.Session"
send_member="PauseDeviceComplete"/> send_member="PauseDeviceComplete"/>
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Session"
send_member="SetBrightness"/>
<allow send_destination="org.freedesktop.login1" <allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.User" send_interface="org.freedesktop.login1.User"
send_member="Terminate"/> send_member="Terminate"/>

View file

@ -1767,3 +1767,13 @@ int bus_reply_pair_array(sd_bus_message *m, char **l) {
return sd_bus_send(NULL, reply, NULL); return sd_bus_send(NULL, reply, NULL);
} }
static void bus_message_unref_wrapper(void *m) {
sd_bus_message_unref(m);
}
const struct hash_ops bus_message_hash_ops = {
.hash = trivial_hash_func,
.compare = trivial_compare_func,
.free_value = bus_message_unref_wrapper,
};

View file

@ -179,3 +179,5 @@ static inline int bus_open_system_watch_bind(sd_bus **ret) {
} }
int bus_reply_pair_array(sd_bus_message *m, char **l); int bus_reply_pair_array(sd_bus_message *m, char **l);
extern const struct hash_ops bus_message_hash_ops;

View file

@ -43,6 +43,7 @@ RestrictRealtime=yes
RestrictSUIDSGID=yes RestrictSUIDSGID=yes
RuntimeDirectory=systemd/sessions systemd/seats systemd/users systemd/inhibit systemd/shutdown RuntimeDirectory=systemd/sessions systemd/seats systemd/users systemd/inhibit systemd/shutdown
RuntimeDirectoryPreserve=yes RuntimeDirectoryPreserve=yes
StateDirectory=systemd/linger
SystemCallArchitectures=native SystemCallArchitectures=native
SystemCallErrorNumber=EPERM SystemCallErrorNumber=EPERM
SystemCallFilter=@system-service SystemCallFilter=@system-service