summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2019-06-12 14:28:09 +0200
committerGitHub <noreply@github.com>2019-06-12 14:28:09 +0200
commit58cf79c2244d41f32faaeaf5c5da7a8e13e3303f (patch)
tree0ac8fd0c331105c778da8ff9b7643f10668196a4
parent6ae827906d3ba4f6eda2f6f27ff41d01b965f572 (diff)
parent6ecda0fbefa3a49990fbadc48892459b97bf3002 (diff)
downloadsystemd-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
-rw-r--r--TODO7
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.c1
-rw-r--r--src/libsystemd/sd-bus/bus-common-errors.h1
-rw-r--r--src/login/71-seat.rules.in4
-rw-r--r--src/login/loginctl.c31
-rw-r--r--src/login/logind-action.c2
-rw-r--r--src/login/logind-brightness.c256
-rw-r--r--src/login/logind-brightness.h9
-rw-r--r--src/login/logind-dbus.c140
-rw-r--r--src/login/logind-dbus.h31
-rw-r--r--src/login/logind-device.c1
-rw-r--r--src/login/logind-inhibit.c1
-rw-r--r--src/login/logind-seat-dbus.c73
-rw-r--r--src/login/logind-seat-dbus.h17
-rw-r--r--src/login/logind-seat.c2
-rw-r--r--src/login/logind-seat.h15
-rw-r--r--src/login/logind-session-dbus.c126
-rw-r--r--src/login/logind-session-dbus.h23
-rw-r--r--src/login/logind-session-device.c3
-rw-r--r--src/login/logind-session.c4
-rw-r--r--src/login/logind-session.h24
-rw-r--r--src/login/logind-user-dbus.c10
-rw-r--r--src/login/logind-user-dbus.h17
-rw-r--r--src/login/logind-user.c6
-rw-r--r--src/login/logind-user.h11
-rw-r--r--src/login/logind.c10
-rw-r--r--src/login/logind.h25
-rw-r--r--src/login/meson.build32
-rw-r--r--src/login/org.freedesktop.login1.conf4
-rw-r--r--src/shared/bus-util.c10
-rw-r--r--src/shared/bus-util.h2
-rw-r--r--units/systemd-logind.service.in1
32 files changed, 700 insertions, 199 deletions
diff --git a/TODO b/TODO
index 1b91b7c799..57c07bea7a 100644
--- a/TODO
+++ b/TODO
@@ -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