diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2019-06-12 14:28:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-12 14:28:09 +0200 |
commit | 58cf79c2244d41f32faaeaf5c5da7a8e13e3303f (patch) | |
tree | 0ac8fd0c331105c778da8ff9b7643f10668196a4 | |
parent | 6ae827906d3ba4f6eda2f6f27ff41d01b965f572 (diff) | |
parent | 6ecda0fbefa3a49990fbadc48892459b97bf3002 (diff) | |
download | systemd-58cf79c2244d41f32faaeaf5c5da7a8e13e3303f.tar.gz systemd-58cf79c2244d41f32faaeaf5c5da7a8e13e3303f.tar.bz2 systemd-58cf79c2244d41f32faaeaf5c5da7a8e13e3303f.zip |
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
32 files changed, 700 insertions, 199 deletions
@@ -27,6 +27,13 @@ Features: * when killing due to service watchdog timeout maybe detect whether target 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 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 diff --git a/src/libsystemd/sd-bus/bus-common-errors.c b/src/libsystemd/sd-bus/bus-common-errors.c index ef53d0a450..edd30bf84d 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.c +++ b/src/libsystemd/sd-bus/bus-common-errors.c @@ -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_SLEEP_VERB_NOT_SUPPORTED, EOPNOTSUPP), 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_NO_NTP_SUPPORT, EOPNOTSUPP), diff --git a/src/libsystemd/sd-bus/bus-common-errors.h b/src/libsystemd/sd-bus/bus-common-errors.h index 2544bdebc1..296579116c 100644 --- a/src/libsystemd/sd-bus/bus-common-errors.h +++ b/src/libsystemd/sd-bus/bus-common-errors.h @@ -51,6 +51,7 @@ #define BUS_ERROR_OPERATION_IN_PROGRESS "org.freedesktop.login1.OperationInProgress" #define BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED "org.freedesktop.login1.SleepVerbNotSupported" #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_NO_NTP_SUPPORT "org.freedesktop.timedate1.NoNTPSupport" diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in index b67966cdf6..6010f048ae 100644 --- a/src/login/71-seat.rules.in +++ b/src/login/71-seat.rules.in @@ -14,6 +14,10 @@ SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat" SUBSYSTEM=="input", KERNEL=="input*", 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 SUBSYSTEM=="graphics", KERNEL=="fb[0-9]", DRIVERS=="hyperv_fb", TAG+="master-of-seat" diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 687a534f7b..2ad9887066 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -846,23 +846,11 @@ static int show_session(int argc, char *argv[], void *userdata) { (void) pager_open(arg_pager_flags); if (argc <= 1) { - const char *session, *p = "/org/freedesktop/login1/session/self"; - + /* If no argument is specified inspect the manager itself */ if (properties) - /* If no argument is specified inspect the manager itself */ return show_properties(bus, "/org/freedesktop/login1", &new_line); - /* And in the pretty case, show data of the calling session */ - 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); + return print_session_status_info(bus, "/org/freedesktop/login1/session/auto", &new_line); } 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); if (argc <= 1) { - /* If not argument is specified inspect the manager - * itself */ + /* If no argument is specified inspect the manager itself */ if (properties) 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); if (argc <= 1) { - /* If not argument is specified inspect the manager - * itself */ + /* If no argument is specified inspect the manager itself */ if (properties) 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++) { @@ -1005,11 +991,8 @@ static int activate(int argc, char *argv[], void *userdata) { polkit_agent_open_if_enabled(arg_transport, arg_ask_password); 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[1] = getenv("XDG_SESSION_ID") ?: (char*) ""; + short_argv[1] = (char*) ""; short_argv[2] = NULL; argv = short_argv; @@ -1030,7 +1013,7 @@ static int activate(int argc, char *argv[], void *userdata) { &error, NULL, "s", argv[i]); 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; diff --git a/src/login/logind-action.c b/src/login/logind-action.c index 6c9366761d..4f97e0d9bb 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -8,6 +8,8 @@ #include "conf-parser.h" #include "format-util.h" #include "logind-action.h" +#include "logind-dbus.h" +#include "logind-session-dbus.h" #include "process-util.h" #include "sleep-config.h" #include "special.h" diff --git a/src/login/logind-brightness.c b/src/login/logind-brightness.c new file mode 100644 index 0000000000..8dfa97d7ae --- /dev/null +++ b/src/login/logind-brightness.c @@ -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; +} diff --git a/src/login/logind-brightness.h b/src/login/logind-brightness.h new file mode 100644 index 0000000000..b22ee37ba7 --- /dev/null +++ b/src/login/logind-brightness.h @@ -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); diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index be767186ff..0e8925ab94 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -27,6 +27,10 @@ #include "fileio.h" #include "format-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 "missing_capability.h" #include "mkdir.h" @@ -46,47 +50,78 @@ #include "utmp-wtmp.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; + Session *session = NULL; const char *name; - Session *session; int r; - /* Get client login session. This is not what you are looking for these days, - * as apps may instead belong to a user service unit. This includes terminal - * emulators and hence command-line apps. */ - r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds); + /* Acquire the sender's session. This first checks if the sending process is inside a session itself, + * and returns that. If not and 'consult_display' is true, this returns the display session of the + * owning user of the caller. */ + + 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) return r; r = sd_bus_creds_get_session(creds, &name); - if (r == -ENXIO) - goto err_no_session; - if (r < 0) - return r; + if (r < 0) { + if (r != -ENXIO) + 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) - 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; 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; assert(m); assert(message); assert(ret); - if (isempty(name)) - return get_sender_session(m, message, error, ret); + if (SEAT_IS_SELF(name)) /* the caller's own session */ + 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); 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) { - _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; uid_t uid; User *user; @@ -109,21 +143,20 @@ static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *er return r; r = sd_bus_creds_get_owner_uid(creds, &uid); - if (r == -ENXIO) - goto err_no_user; - if (r < 0) - return r; + if (r < 0) { + if (r != -ENXIO) + 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) - 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; 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) { @@ -145,7 +178,13 @@ int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, 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; int r; @@ -153,16 +192,17 @@ int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char assert(message); assert(ret); - if (isempty(name)) { + if (SEAT_IS_SELF(name) || SEAT_IS_AUTO(name)) { 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) return r; seat = session->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 { seat = hashmap_get(m->seats, name); 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) return -ENOMEM; - /* Wut? There's already a session by this name and we - * didn't find it above? Weird, then let's not trust - * the audit data and let's better register a new - * ID */ - if (hashmap_get(m->sessions, id)) { + /* Wut? There's already a session by this name and we didn't find it above? Weird, then let's + * not trust the audit data and let's better register a new ID */ + if (hashmap_contains(m->sessions, id)) { log_warning("Existing logind session ID %s used by new audit session, ignoring.", id); audit_id = AUDIT_SESSION_INVALID; 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) 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 */ manager_reconnect_utmp(m); @@ -990,8 +1032,7 @@ static int method_activate_session_on_seat(sd_bus_message *message, void *userda assert(message); assert(m); - /* Same as ActivateSession() but refuses to work if - * the seat doesn't match */ + /* Same as ActivateSession() but refuses to work if the seat doesn't match */ r = sd_bus_message_read(message, "ss", &session_name, &seat_name); if (r < 0) @@ -1367,11 +1408,22 @@ static int method_attach_device(sd_bus_message *message, void *userdata, sd_bus_ if (r < 0) 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")) return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs); - if (!seat_name_is_valid(seat)) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat); + if (SEAT_IS_SELF(seat) || SEAT_IS_AUTO(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( message, diff --git a/src/login/logind-dbus.h b/src/login/logind-dbus.h new file mode 100644 index 0000000000..6c73a9654f --- /dev/null +++ b/src/login/logind-dbus.h @@ -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); diff --git a/src/login/logind-device.c b/src/login/logind-device.c index e724365b13..20108544aa 100644 --- a/src/login/logind-device.c +++ b/src/login/logind-device.c @@ -4,6 +4,7 @@ #include "alloc-util.h" #include "logind-device.h" +#include "logind-seat-dbus.h" #include "util.h" Device* device_new(Manager *m, const char *sysfs, bool master) { diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index d427dcaa01..d963706dce 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -13,6 +13,7 @@ #include "fd-util.h" #include "fileio.h" #include "format-util.h" +#include "logind-dbus.h" #include "logind-inhibit.h" #include "mkdir.h" #include "parse-util.h" diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 6ee5a1c95d..c33a0e0ad4 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -7,7 +7,10 @@ #include "bus-common-errors.h" #include "bus-label.h" #include "bus-util.h" +#include "logind-dbus.h" +#include "logind-seat-dbus.h" #include "logind-seat.h" +#include "logind-session-dbus.h" #include "logind.h" #include "missing_capability.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) { + _cleanup_free_ char *e = NULL; + sd_bus_message *message; Manager *m = userdata; + const char *p; Seat *seat; int r; @@ -265,32 +271,25 @@ int seat_object_find(sd_bus *bus, const char *path, const char *interface, void assert(found); assert(m); - if (streq(path, "/org/freedesktop/login1/seat/self")) { - sd_bus_message *message; - - message = sd_bus_get_current_message(bus); - if (!message) - return 0; - - r = manager_get_seat_from_creds(m, message, NULL, error, &seat); - if (r < 0) - return r; - } else { - _cleanup_free_ char *e = NULL; - const char *p; + p = startswith(path, "/org/freedesktop/login1/seat/"); + if (!p) + return 0; - p = startswith(path, "/org/freedesktop/login1/seat/"); - if (!p) - return 0; + e = bus_label_unescape(p); + if (!e) + return -ENOMEM; - e = bus_label_unescape(p); - if (!e) - return -ENOMEM; + message = sd_bus_get_current_message(bus); + if (!message) + return 0; - seat = hashmap_get(m->seats, e); - if (!seat) - return 0; + r = manager_get_seat_from_creds(m, message, e, error, &seat); + if (r == -ENXIO) { + sd_bus_error_free(error); + return 0; } + if (r < 0) + return r; *found = seat; 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); if (message) { _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) { + bool may_auto = false; + const char *name; + r = sd_bus_creds_get_session(creds, &name); if (r >= 0) { + Session *session; + session = hashmap_get(m->sessions, name); if (session && session->seat) { r = strv_extend(&l, "/org/freedesktop/login1/seat/self"); if (r < 0) 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); - return 1; } diff --git a/src/login/logind-seat-dbus.h b/src/login/logind-seat-dbus.h new file mode 100644 index 0000000000..2590f64922 --- /dev/null +++ b/src/login/logind-seat-dbus.h @@ -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); diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index f5ffb68238..dc578adf63 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -13,7 +13,9 @@ #include "fileio.h" #include "format-util.h" #include "logind-acl.h" +#include "logind-seat-dbus.h" #include "logind-seat.h" +#include "logind-session-dbus.h" #include "mkdir.h" #include "parse-util.h" #include "stdio-util.h" diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h index 6236f1360b..64cdf2f25a 100644 --- a/src/login/logind-seat.h +++ b/src/login/logind-seat.h @@ -67,13 +67,10 @@ void seat_add_to_gc_queue(Seat *s); 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); -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); +static inline bool SEAT_IS_AUTO(const char *name) { + return streq_ptr(name, "auto"); +} diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index df5bfba982..c297f62cdf 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -8,13 +8,20 @@ #include "bus-label.h" #include "bus-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.h" +#include "logind-user-dbus.h" #include "logind.h" #include "missing_capability.h" +#include "path-util.h" #include "signal-util.h" #include "stat-util.h" #include "strv.h" +#include "user-util.h" #include "util.h" 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); } +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[] = { 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("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("SetBrightness", "ssu", NULL, method_set_brightness, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("PauseDevice", "uus", 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) { + _cleanup_free_ char *e = NULL; + sd_bus_message *message; Manager *m = userdata; Session *session; + const char *p; int r; assert(bus); @@ -539,32 +601,25 @@ int session_object_find(sd_bus *bus, const char *path, const char *interface, vo assert(found); assert(m); - if (streq(path, "/org/freedesktop/login1/session/self")) { - sd_bus_message *message; - - message = sd_bus_get_current_message(bus); - if (!message) - return 0; - - r = manager_get_session_from_creds(m, message, NULL, error, &session); - if (r < 0) - return r; - } else { - _cleanup_free_ char *e = NULL; - const char *p; + p = startswith(path, "/org/freedesktop/login1/session/"); + if (!p) + return 0; - p = startswith(path, "/org/freedesktop/login1/session/"); - if (!p) - return 0; + e = bus_label_unescape(p); + if (!e) + return -ENOMEM; - e = bus_label_unescape(p); - if (!e) - return -ENOMEM; + message = sd_bus_get_current_message(bus); + if (!message) + return 0; - session = hashmap_get(m->sessions, e); - if (!session) - return 0; + r = manager_get_session_from_creds(m, message, e, error, &session); + if (r == -ENXIO) { + sd_bus_error_free(error); + return 0; } + if (r < 0) + return r; *found = session; 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); if (message) { _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) { + bool may_auto = false; + const char *name; + r = sd_bus_creds_get_session(creds, &name); if (r >= 0) { 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"); if (r < 0) 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); - return 1; } diff --git a/src/login/logind-session-dbus.h b/src/login/logind-session-dbus.h new file mode 100644 index 0000000000..9d2315cc60 --- /dev/null +++ b/src/login/logind-session-dbus.h @@ -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); diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c index 3e2ff6d5b8..3057e72394 100644 --- a/src/login/logind-session-device.c +++ b/src/login/logind-session-device.c @@ -7,14 +7,15 @@ #include <sys/types.h> #include "sd-device.h" +#include "sd-daemon.h" #include "alloc-util.h" #include "bus-util.h" #include "fd-util.h" +#include "logind-session-dbus.h" #include "logind-session-device.h" #include "missing.h" #include "parse-util.h" -#include "sd-daemon.h" #include "util.h" enum SessionDeviceNotifications { diff --git a/src/login/logind-session.c b/src/login/logind-session.c index f1efeb0e01..17700c6921 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -22,7 +22,11 @@ #include "fileio.h" #include "format-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-user-dbus.h" #include "mkdir.h" #include "parse-util.h" #include "path-util.h" diff --git a/src/login/logind-session.h b/src/login/logind-session.h index f3c17a8d91..50fe29e797 100644 --- a/src/login/logind-session.h +++ b/src/login/logind-session.h @@ -7,6 +7,7 @@ typedef enum KillWho KillWho; #include "list.h" #include "login-util.h" #include "logind-user.h" +#include "string-util.h" typedef enum SessionState { 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); -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_; 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); void session_drop_controller(Session *s); -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); +static inline bool SESSION_IS_SELF(const char *name) { + return isempty(name) || streq(name, "self"); +} + +static inline bool SESSION_IS_AUTO(const char *name) { + return streq_ptr(name, "auto"); +} diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index fcaeba13f6..beb97362e7 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -6,6 +6,9 @@ #include "alloc-util.h" #include "bus-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.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; 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) return r; } 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); if (message) { _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); if (r >= 0) { + uid_t uid; + r = sd_bus_creds_get_owner_uid(creds, &uid); if (r >= 0) { user = hashmap_get(m->users, UID_TO_PTR(uid)); diff --git a/src/login/logind-user-dbus.h b/src/login/logind-user-dbus.h new file mode 100644 index 0000000000..acfcb981cf --- /dev/null +++ b/src/login/logind-user-dbus.h @@ -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); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index c5d442865c..b17fb2e322 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -19,7 +19,9 @@ #include "hashmap.h" #include "label.h" #include "limits-util.h" +#include "logind-dbus.h" #include "logind-user.h" +#include "logind-user-dbus.h" #include "mkdir.h" #include "parse-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 user’s ‘primary session’ or ‘display’. */ 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) { /* 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_TTY] = -2, [SESSION_X11] = -3, diff --git a/src/login/logind-user.h b/src/login/logind-user.h index c41973e27d..4bd65d8373 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -69,18 +69,7 @@ int user_check_linger_file(User *u); void user_elect_display(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_; 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); diff --git a/src/login/logind.c b/src/login/logind.c index 4c0e8ce6b1..d60223db68 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -18,6 +18,10 @@ #include "fd-util.h" #include "format-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 "main-func.h" #include "parse-util.h" @@ -44,10 +48,9 @@ static int manager_new(Manager **ret) { *m = (Manager) { .console_active_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->seats = 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->inhibitors); hashmap_free(m->buttons); + hashmap_free(m->brightness_writers); hashmap_free(m->user_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/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); if (r < 0) diff --git a/src/login/logind.h b/src/login/logind.h index 7b6f73c6ec..f260f2dc96 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -31,6 +31,7 @@ struct Manager { Hashmap *users; Hashmap *inhibitors; Hashmap *buttons; + Hashmap *brightness_writers; LIST_HEAD(Seat, seat_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[]; -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 */ 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_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); bool logind_wall_tty_filter(const char *tty, void *userdata); - -int manager_dispatch_delayed(Manager *manager, bool timeout); diff --git a/src/login/meson.build b/src/login/meson.build index 1cc75fd1cf..832274af78 100644 --- a/src/login/meson.build +++ b/src/login/meson.build @@ -12,29 +12,35 @@ logind_gperf_c = custom_target( command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@']) liblogind_core_sources = files(''' + logind-acl.h + logind-action.c + logind-action.h + logind-brightness.c + logind-brightness.h + logind-button.c + logind-button.h logind-core.c + logind-dbus.c + logind-dbus.h logind-device.c logind-device.h - logind-button.c - logind-button.h - logind-action.c - logind-action.h + logind-inhibit.c + logind-inhibit.h + logind-seat-dbus.c + logind-seat-dbus.h logind-seat.c logind-seat.h - logind-session.c - logind-session.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.h logind-user.c logind-user.h - logind-inhibit.c - logind-inhibit.h - logind-dbus.c - logind-session-dbus.c - logind-seat-dbus.c - logind-user-dbus.c logind-utmp.c - logind-acl.h '''.split()) liblogind_core_sources += [logind_gperf_c] diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf index f3c13ad89a..124a25810e 100644 --- a/src/login/org.freedesktop.login1.conf +++ b/src/login/org.freedesktop.login1.conf @@ -303,6 +303,10 @@ send_member="PauseDeviceComplete"/> <allow send_destination="org.freedesktop.login1" + send_interface="org.freedesktop.login1.Session" + send_member="SetBrightness"/> + + <allow send_destination="org.freedesktop.login1" send_interface="org.freedesktop.login1.User" send_member="Terminate"/> diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index c2440271fe..81acff4602 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1767,3 +1767,13 @@ int bus_reply_pair_array(sd_bus_message *m, char **l) { 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, +}; diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h index 59bfdb2398..3216b0c37a 100644 --- a/src/shared/bus-util.h +++ b/src/shared/bus-util.h @@ -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); + +extern const struct hash_ops bus_message_hash_ops; diff --git a/units/systemd-logind.service.in b/units/systemd-logind.service.in index 3eef95c661..8a7262776f 100644 --- a/units/systemd-logind.service.in +++ b/units/systemd-logind.service.in @@ -43,6 +43,7 @@ RestrictRealtime=yes RestrictSUIDSGID=yes RuntimeDirectory=systemd/sessions systemd/seats systemd/users systemd/inhibit systemd/shutdown RuntimeDirectoryPreserve=yes +StateDirectory=systemd/linger SystemCallArchitectures=native SystemCallErrorNumber=EPERM SystemCallFilter=@system-service |