mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-22 13:33:56 +03:00
Merge pull request #12424 from poettering/logind-brightness
logind: add SetBrightness() bus call as minimal API for setting "leds" and "backlight" kernel class device brightness
This commit is contained in:
commit
58cf79c224
7
TODO
7
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
|
||||
|
@ -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),
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
256
src/login/logind-brightness.c
Normal file
256
src/login/logind-brightness.c
Normal file
@ -0,0 +1,256 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "bus-util.h"
|
||||
#include "device-util.h"
|
||||
#include "hash-funcs.h"
|
||||
#include "logind-brightness.h"
|
||||
#include "logind.h"
|
||||
#include "process-util.h"
|
||||
#include "stdio-util.h"
|
||||
|
||||
/* Brightness and LED devices tend to be very slow to write to (often being I2C and such). Writes to the
|
||||
* sysfs attributes are synchronous, and hence will freeze our process on access. We can't really have that,
|
||||
* hence we add some complexity: whenever we need to write to the brightness attribute, we do so in a forked
|
||||
* off process, which terminates when it is done. Watching that process allows us to watch completion of the
|
||||
* write operation.
|
||||
*
|
||||
* To make this even more complex: clients are likely to send us many write requests in a short time-frame
|
||||
* (because they implement reactive brightness sliders on screen). Let's coalesce writes to make this
|
||||
* efficient: whenever we get requests to change brightness while we are still writing to the brightness
|
||||
* attribute, let's remember the request and restart a new one when the initial operation finished. When we
|
||||
* get another request while one is ongoing and one is pending we'll replace the pending one with the new
|
||||
* one.
|
||||
*
|
||||
* The bus messages are answered when the first write operation finishes that started either due to the
|
||||
* request or due to a later request that overrode the requested one.
|
||||
*
|
||||
* Yes, this is complex, but I don't see an easier way if we want to be both efficient and still support
|
||||
* completion notification. */
|
||||
|
||||
typedef struct BrightnessWriter {
|
||||
Manager *manager;
|
||||
|
||||
sd_device *device;
|
||||
char *path;
|
||||
|
||||
pid_t child;
|
||||
|
||||
uint32_t brightness;
|
||||
bool again;
|
||||
|
||||
Set *current_messages;
|
||||
Set *pending_messages;
|
||||
|
||||
sd_event_source* child_event_source;
|
||||
} BrightnessWriter;
|
||||
|
||||
static void brightness_writer_free(BrightnessWriter *w) {
|
||||
if (!w)
|
||||
return;
|
||||
|
||||
if (w->manager && w->path)
|
||||
(void) hashmap_remove_value(w->manager->brightness_writers, w->path, w);
|
||||
|
||||
sd_device_unref(w->device);
|
||||
free(w->path);
|
||||
|
||||
set_free(w->current_messages);
|
||||
set_free(w->pending_messages);
|
||||
|
||||
w->child_event_source = sd_event_source_unref(w->child_event_source);
|
||||
|
||||
free(w);
|
||||
}
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(BrightnessWriter*, brightness_writer_free);
|
||||
|
||||
DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(
|
||||
brightness_writer_hash_ops,
|
||||
char,
|
||||
string_hash_func,
|
||||
string_compare_func,
|
||||
BrightnessWriter,
|
||||
brightness_writer_free);
|
||||
|
||||
static void brightness_writer_reply(BrightnessWriter *w, int error) {
|
||||
int r;
|
||||
|
||||
assert(w);
|
||||
|
||||
for (;;) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
|
||||
m = set_steal_first(w->current_messages);
|
||||
if (!m)
|
||||
break;
|
||||
|
||||
if (error == 0)
|
||||
r = sd_bus_reply_method_return(m, NULL);
|
||||
else
|
||||
r = sd_bus_reply_method_errnof(m, error, "Failed to write to brightness device: %m");
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to send method reply, ignoring: %m");
|
||||
}
|
||||
}
|
||||
|
||||
static int brightness_writer_fork(BrightnessWriter *w);
|
||||
|
||||
static int on_brightness_writer_exit(sd_event_source *s, const siginfo_t *si, void *userdata) {
|
||||
BrightnessWriter *w = userdata;
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(si);
|
||||
assert(w);
|
||||
|
||||
assert(si->si_pid == w->child);
|
||||
w->child = 0;
|
||||
w->child_event_source = sd_event_source_unref(w->child_event_source);
|
||||
|
||||
brightness_writer_reply(w,
|
||||
si->si_code == CLD_EXITED &&
|
||||
si->si_status == EXIT_SUCCESS ? 0 : -EPROTO);
|
||||
|
||||
if (w->again) {
|
||||
/* Another request to change the brightness has been queued. Act on it, but make the pending
|
||||
* messages the current ones. */
|
||||
w->again = false;
|
||||
set_free(w->current_messages);
|
||||
w->current_messages = TAKE_PTR(w->pending_messages);
|
||||
|
||||
r = brightness_writer_fork(w);
|
||||
if (r >= 0)
|
||||
return 0;
|
||||
|
||||
brightness_writer_reply(w, r);
|
||||
}
|
||||
|
||||
brightness_writer_free(w);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int brightness_writer_fork(BrightnessWriter *w) {
|
||||
int r;
|
||||
|
||||
assert(w);
|
||||
assert(w->manager);
|
||||
assert(w->child == 0);
|
||||
assert(!w->child_event_source);
|
||||
|
||||
r = safe_fork("(sd-bright)", FORK_DEATHSIG|FORK_NULL_STDIO|FORK_CLOSE_ALL_FDS|FORK_LOG, &w->child);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
char brs[DECIMAL_STR_MAX(uint32_t)+1];
|
||||
|
||||
/* Child */
|
||||
xsprintf(brs, "%" PRIu32, w->brightness);
|
||||
|
||||
r = sd_device_set_sysattr_value(w->device, "brightness", brs);
|
||||
if (r < 0) {
|
||||
log_device_error_errno(w->device, r, "Failed to write brightness to device: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
r = sd_event_add_child(w->manager->event, &w->child_event_source, w->child, WEXITED, on_brightness_writer_exit, w);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to watch brightness writer child " PID_FMT ": %m", w->child);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_add_message(Set **set, sd_bus_message *message) {
|
||||
int r;
|
||||
|
||||
assert(set);
|
||||
|
||||
if (!message)
|
||||
return 0;
|
||||
|
||||
r = sd_bus_message_get_expect_reply(message);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
r = set_ensure_allocated(set, &bus_message_hash_ops);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = set_put(*set, message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
sd_bus_message_ref(message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_write_brightness(
|
||||
Manager *m,
|
||||
sd_device *device,
|
||||
uint32_t brightness,
|
||||
sd_bus_message *message) {
|
||||
|
||||
_cleanup_(brightness_writer_freep) BrightnessWriter *w = NULL;
|
||||
BrightnessWriter *existing;
|
||||
const char *path;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(device);
|
||||
|
||||
r = sd_device_get_syspath(device, &path);
|
||||
if (r < 0)
|
||||
return log_device_error_errno(device, r, "Failed to get sysfs path for brightness device: %m");
|
||||
|
||||
existing = hashmap_get(m->brightness_writers, path);
|
||||
if (existing) {
|
||||
/* There's already a writer for this device. Let's update it with the new brightness, and add
|
||||
* our message to the set of message to reply when done. */
|
||||
|
||||
r = set_add_message(&existing->pending_messages, message);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add message to set: %m");
|
||||
|
||||
/* We overide any previously requested brightness here: we coalesce writes, and the newest
|
||||
* requested brightness is the one we'll put into effect. */
|
||||
existing->brightness = brightness;
|
||||
existing->again = true; /* request another iteration of the writer when the current one is
|
||||
* complete */
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = hashmap_ensure_allocated(&m->brightness_writers, &brightness_writer_hash_ops);
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
|
||||
w = new(BrightnessWriter, 1);
|
||||
if (!w)
|
||||
return log_oom();
|
||||
|
||||
*w = (BrightnessWriter) {
|
||||
.device = sd_device_ref(device),
|
||||
.path = strdup(path),
|
||||
.brightness = brightness,
|
||||
};
|
||||
|
||||
if (!w->path)
|
||||
return log_oom();
|
||||
|
||||
r = hashmap_put(m->brightness_writers, w->path, w);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add brightness writer to hashmap: %m");
|
||||
w->manager = m;
|
||||
|
||||
r = set_add_message(&w->current_messages, message);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add message to set: %m");
|
||||
|
||||
r = brightness_writer_fork(w);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
TAKE_PTR(w);
|
||||
return 0;
|
||||
}
|
9
src/login/logind-brightness.h
Normal file
9
src/login/logind-brightness.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "sd-bus.h"
|
||||
#include "sd-device.h"
|
||||
|
||||
#include "logind.h"
|
||||
|
||||
int manager_write_brightness(Manager *m, sd_device *device, uint32_t brightness, sd_bus_message *message);
|
@ -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,
|
||||
|
31
src/login/logind-dbus.h
Normal file
31
src/login/logind-dbus.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "logind.h"
|
||||
#include "logind-session.h"
|
||||
#include "logind-user.h"
|
||||
|
||||
int manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret);
|
||||
int manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret);
|
||||
int manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret);
|
||||
|
||||
int manager_dispatch_delayed(Manager *manager, bool timeout);
|
||||
|
||||
int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name, InhibitWhat w, sd_bus_error *error);
|
||||
|
||||
int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
|
||||
int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_;
|
||||
|
||||
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, char **wants, char **after, const char *requires_mounts_for, sd_bus_message *more_properties, sd_bus_error *error, char **job);
|
||||
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error);
|
||||
int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error);
|
||||
int manager_unit_is_active(Manager *manager, const char *unit, sd_bus_error *error);
|
||||
int manager_job_is_active(Manager *manager, const char *path, sd_bus_error *error);
|
@ -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) {
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
p = startswith(path, "/org/freedesktop/login1/seat/");
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
message = sd_bus_get_current_message(bus);
|
||||
if (!message)
|
||||
return 0;
|
||||
e = bus_label_unescape(p);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
message = sd_bus_get_current_message(bus);
|
||||
if (!message)
|
||||
return 0;
|
||||
|
||||
p = startswith(path, "/org/freedesktop/login1/seat/");
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
e = bus_label_unescape(p);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
17
src/login/logind-seat-dbus.h
Normal file
17
src/login/logind-seat-dbus.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "logind-seat.h"
|
||||
|
||||
extern const sd_bus_vtable seat_vtable[];
|
||||
|
||||
int seat_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
|
||||
int seat_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
|
||||
char *seat_bus_path(Seat *s);
|
||||
|
||||
int seat_send_signal(Seat *s, bool new_seat);
|
||||
int seat_send_changed(Seat *s, const char *properties, ...) _sentinel_;
|
||||
|
||||
int bus_seat_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
@ -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"
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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;
|
||||
p = startswith(path, "/org/freedesktop/login1/session/");
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
message = sd_bus_get_current_message(bus);
|
||||
if (!message)
|
||||
return 0;
|
||||
e = bus_label_unescape(p);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
message = sd_bus_get_current_message(bus);
|
||||
if (!message)
|
||||
return 0;
|
||||
|
||||
p = startswith(path, "/org/freedesktop/login1/session/");
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
e = bus_label_unescape(p);
|
||||
if (!e)
|
||||
return -ENOMEM;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
23
src/login/logind-session-dbus.h
Normal file
23
src/login/logind-session-dbus.h
Normal file
@ -0,0 +1,23 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "logind-session.h"
|
||||
|
||||
extern const sd_bus_vtable session_vtable[];
|
||||
int session_node_enumerator(sd_bus *bus, const char *path,void *userdata, char ***nodes, sd_bus_error *error);
|
||||
int session_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
|
||||
char *session_bus_path(Session *s);
|
||||
|
||||
int session_send_signal(Session *s, bool new_session);
|
||||
int session_send_changed(Session *s, const char *properties, ...) _sentinel_;
|
||||
int session_send_lock(Session *s, bool lock);
|
||||
int session_send_lock_all(Manager *m, bool lock);
|
||||
|
||||
int session_send_create_reply(Session *s, sd_bus_error *error);
|
||||
|
||||
int bus_session_method_activate(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_session_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_session_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
@ -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 {
|
||||
|
@ -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"
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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));
|
||||
|
17
src/login/logind-user-dbus.h
Normal file
17
src/login/logind-user-dbus.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "logind-user.h"
|
||||
|
||||
extern const sd_bus_vtable user_vtable[];
|
||||
int user_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error);
|
||||
int user_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error);
|
||||
char *user_bus_path(User *s);
|
||||
|
||||
int user_send_signal(User *u, bool new_user);
|
||||
int user_send_changed(User *u, const char *properties, ...) _sentinel_;
|
||||
|
||||
int bus_user_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int bus_user_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -12,29 +12,35 @@ logind_gperf_c = custom_target(
|
||||
command : [gperf, '@INPUT@', '--output-file', '@OUTPUT@'])
|
||||
|
||||
liblogind_core_sources = files('''
|
||||
logind-core.c
|
||||
logind-device.c
|
||||
logind-device.h
|
||||
logind-button.c
|
||||
logind-button.h
|
||||
logind-acl.h
|
||||
logind-action.c
|
||||
logind-action.h
|
||||
logind-seat.c
|
||||
logind-seat.h
|
||||
logind-session.c
|
||||
logind-session.h
|
||||
logind-session-device.c
|
||||
logind-session-device.h
|
||||
logind-user.c
|
||||
logind-user.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-inhibit.c
|
||||
logind-inhibit.h
|
||||
logind-dbus.c
|
||||
logind-session-dbus.c
|
||||
logind-seat-dbus.c
|
||||
logind-seat-dbus.h
|
||||
logind-seat.c
|
||||
logind-seat.h
|
||||
logind-session-dbus.c
|
||||
logind-session-dbus.h
|
||||
logind-session-device.c
|
||||
logind-session-device.h
|
||||
logind-session.c
|
||||
logind-session.h
|
||||
logind-user-dbus.c
|
||||
logind-user-dbus.h
|
||||
logind-user.c
|
||||
logind-user.h
|
||||
logind-utmp.c
|
||||
logind-acl.h
|
||||
'''.split())
|
||||
|
||||
liblogind_core_sources += [logind_gperf_c]
|
||||
|
@ -302,6 +302,10 @@
|
||||
send_interface="org.freedesktop.login1.Session"
|
||||
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"/>
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user