From 98393f852f2f66a74f7370aa63c07b26d610343c Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Tue, 6 Mar 2018 20:13:05 +0100 Subject: New upstream version 238 --- src/login/70-uaccess.rules | 2 +- src/login/inhibit.c | 1 + src/login/logind-acl.c | 2 +- src/login/logind-button.c | 6 +- src/login/logind-core.c | 34 +++ src/login/logind-dbus.c | 24 +- src/login/logind-gperf.gperf | 1 + src/login/logind-seat.c | 8 +- src/login/logind-seat.h | 2 +- src/login/logind-session-device.c | 135 ++++++----- src/login/logind-session-device.h | 6 +- src/login/logind-session.c | 14 +- src/login/logind-session.h | 2 +- src/login/logind-user.c | 14 +- src/login/logind-user.h | 2 +- src/login/logind.c | 39 ++-- src/login/logind.conf.in | 1 + src/login/logind.h | 3 + src/login/meson.build | 11 +- src/login/org.freedesktop.login1.policy | 360 +++++++++++++++++++++++++++++ src/login/org.freedesktop.login1.policy.in | 360 ----------------------------- 21 files changed, 541 insertions(+), 486 deletions(-) create mode 100644 src/login/org.freedesktop.login1.policy delete mode 100644 src/login/org.freedesktop.login1.policy.in (limited to 'src/login') diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules index f2c838f353..3515d292ac 100644 --- a/src/login/70-uaccess.rules +++ b/src/login/70-uaccess.rules @@ -27,7 +27,7 @@ SUBSYSTEM=="block", ENV{ID_CDROM}=="1", TAG+="uaccess" SUBSYSTEM=="scsi_generic", SUBSYSTEMS=="scsi", ATTRS{type}=="4|5", TAG+="uaccess" # Sound devices -SUBSYSTEM=="sound", TAG+="uaccess" \ +SUBSYSTEM=="sound", TAG+="uaccess", \ OPTIONS+="static_node=snd/timer", OPTIONS+="static_node=snd/seq" # ffado is an userspace driver for firewire sound cards diff --git a/src/login/inhibit.c b/src/login/inhibit.c index 22657f9eda..6b5d9c29b9 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -272,6 +272,7 @@ int main(int argc, char *argv[]) { if (r == 0) { /* Child */ execvp(argv[optind], argv + optind); + log_open(); log_error_errno(errno, "Failed to execute %s: %m", argv[optind]); _exit(EXIT_FAILURE); } diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c index d785f67ca3..3f355e7ea8 100644 --- a/src/login/logind-acl.c +++ b/src/login/logind-acl.c @@ -192,7 +192,7 @@ int devnode_acl_all(struct udev *udev, assert(udev); - nodes = set_new(&string_hash_ops); + nodes = set_new(&path_hash_ops); if (!nodes) return -ENOMEM; diff --git a/src/login/logind-button.c b/src/login/logind-button.c index 94945f0bcb..2da6e69952 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -110,9 +110,13 @@ static void button_lid_switch_handle_action(Manager *manager, bool is_edge) { assert(manager); - /* If we are docked, handle the lid switch differently */ + /* If we are docked or on external power, handle the lid switch + * differently */ if (manager_is_docked_or_external_displays(manager)) handle_action = manager->handle_lid_switch_docked; + else if (manager->handle_lid_switch_ep != _HANDLE_ACTION_INVALID && + manager_is_on_external_power()) + handle_action = manager->handle_lid_switch_ep; else handle_action = manager->handle_lid_switch; diff --git a/src/login/logind-core.c b/src/login/logind-core.c index e338682f41..41b4d4d8d7 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -602,3 +602,37 @@ bool manager_is_docked_or_external_displays(Manager *m) { return false; } + +bool manager_is_on_external_power(void) { + int r; + + /* For now we only check for AC power, but 'external power' can apply + * to anything that isn't an internal battery */ + r = on_ac_power(); + if (r < 0) + log_warning_errno(r, "Failed to read AC power status: %m"); + else if (r > 0) + return true; + + return false; +} + +bool manager_all_buttons_ignored(Manager *m) { + assert(m); + + if (m->handle_power_key != HANDLE_IGNORE) + return false; + if (m->handle_suspend_key != HANDLE_IGNORE) + return false; + if (m->handle_hibernate_key != HANDLE_IGNORE) + return false; + if (m->handle_lid_switch != HANDLE_IGNORE) + return false; + if (m->handle_lid_switch_ep != _HANDLE_ACTION_INVALID && + m->handle_lid_switch_ep != HANDLE_IGNORE) + return false; + if (m->handle_lid_switch_docked != HANDLE_IGNORE) + return false; + + return true; +} diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index ae36ececb5..07cb257151 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -41,6 +41,7 @@ #include "mkdir.h" #include "path-util.h" #include "process-util.h" +#include "cgroup-util.h" #include "selinux-util.h" #include "sleep-config.h" #include "special.h" @@ -658,6 +659,7 @@ static int method_list_inhibitors(sd_bus_message *message, void *userdata, sd_bu static int method_create_session(sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop; uint32_t audit_id = 0; + _cleanup_free_ char *unit = NULL; _cleanup_free_ char *id = NULL; Session *session = NULL; Manager *m = userdata; @@ -787,8 +789,15 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus return r; } - r = manager_get_session_by_pid(m, leader, NULL); - if (r > 0) + /* + * Check if we are already in a logind session. Or if we are in user@.service + * which is a special PAM session that avoids creating a logind session. + */ + r = cg_pid_get_unit(leader, &unit); + if (r < 0) + return r; + if (hashmap_get(m->session_units, unit) || + hashmap_get(m->user_units, unit)) return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session"); /* @@ -1930,15 +1939,11 @@ static int nologin_timeout_handler( void *userdata) { Manager *m = userdata; - int r; log_info("Creating /run/nologin, blocking further logins..."); - r = write_string_file_atomic_label("/run/nologin", "System is going down."); - if (r < 0) - log_error_errno(r, "Failed to create /run/nologin: %m"); - else - m->unlink_nologin = true; + m->unlink_nologin = + create_shutdown_run_nologin_or_warn() >= 0; return 0; } @@ -2010,7 +2015,7 @@ static void reset_scheduled_shutdown(Manager *m) { m->shutdown_dry_run = false; if (m->unlink_nologin) { - (void) unlink("/run/nologin"); + (void) unlink_or_warn("/run/nologin"); m->unlink_nologin = false; } @@ -2653,6 +2658,7 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("HandleLidSwitchExternalPower", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_ep), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST), diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf index ee62db63a5..f6f57526f6 100644 --- a/src/login/logind-gperf.gperf +++ b/src/login/logind-gperf.gperf @@ -27,6 +27,7 @@ Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manag Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key) Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key) Login.HandleLidSwitch, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch) +Login.HandleLidSwitchExternalPower,config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_ep) Login.HandleLidSwitchDocked, config_parse_handle_action, 0, offsetof(Manager, handle_lid_switch_docked) Login.PowerKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, power_key_ignore_inhibited) Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, suspend_key_ignore_inhibited) diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index b99e7abf91..46e7c06ddc 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -639,16 +639,16 @@ int seat_get_idle_hint(Seat *s, dual_timestamp *t) { return idle_hint; } -bool seat_check_gc(Seat *s, bool drop_not_started) { +bool seat_may_gc(Seat *s, bool drop_not_started) { assert(s); if (drop_not_started && !s->started) - return false; + return true; if (seat_is_seat0(s)) - return true; + return false; - return seat_has_master_device(s); + return !seat_has_master_device(s); } void seat_add_to_gc_queue(Seat *s) { diff --git a/src/login/logind-seat.h b/src/login/logind-seat.h index 5427ac21c8..4982ea3381 100644 --- a/src/login/logind-seat.h +++ b/src/login/logind-seat.h @@ -79,7 +79,7 @@ int seat_start(Seat *s); int seat_stop(Seat *s, bool force); int seat_stop_sessions(Seat *s, bool force); -bool seat_check_gc(Seat *s, bool drop_not_started); +bool seat_may_gc(Seat *s, bool drop_not_started); void seat_add_to_gc_queue(Seat *s); bool seat_name_is_valid(const char *name); diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c index 067e67a93d..73eee72515 100644 --- a/src/login/logind-session-device.c +++ b/src/login/logind-session-device.c @@ -74,20 +74,25 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati return r; switch (type) { + case SESSION_DEVICE_RESUME: r = sd_bus_message_append(m, "uuh", major, minor, sd->fd); if (r < 0) return r; break; + case SESSION_DEVICE_TRY_PAUSE: t = "pause"; break; + case SESSION_DEVICE_PAUSE: t = "force"; break; + case SESSION_DEVICE_RELEASE: t = "gone"; break; + default: return -EINVAL; } @@ -101,43 +106,33 @@ static int session_device_notify(SessionDevice *sd, enum SessionDeviceNotificati return sd_bus_send(sd->session->manager->bus, m, NULL); } -static int sd_eviocrevoke(int fd) { - static bool warned; - int r; +static void sd_eviocrevoke(int fd) { + static bool warned = false; assert(fd >= 0); - r = ioctl(fd, EVIOCREVOKE, NULL); - if (r < 0) { - r = -errno; - if (r == -EINVAL && !warned) { + if (ioctl(fd, EVIOCREVOKE, NULL) < 0) { + + if (errno == EINVAL && !warned) { + log_warning_errno(errno, "Kernel does not support evdev-revocation: %m"); warned = true; - log_warning("kernel does not support evdev-revocation"); } } - - return 0; } static int sd_drmsetmaster(int fd) { - int r; - assert(fd >= 0); - r = ioctl(fd, DRM_IOCTL_SET_MASTER, 0); - if (r < 0) + if (ioctl(fd, DRM_IOCTL_SET_MASTER, 0) < 0) return -errno; return 0; } static int sd_drmdropmaster(int fd) { - int r; - assert(fd >= 0); - r = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0); - if (r < 0) + if (ioctl(fd, DRM_IOCTL_DROP_MASTER, 0) < 0) return -errno; return 0; @@ -146,7 +141,9 @@ static int sd_drmdropmaster(int fd) { static int session_device_open(SessionDevice *sd, bool active) { int fd, r; + assert(sd); assert(sd->type != DEVICE_TYPE_UNKNOWN); + assert(sd->node); /* open device and try to get an udev_device from it */ fd = open(sd->node, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); @@ -154,28 +151,27 @@ static int session_device_open(SessionDevice *sd, bool active) { return -errno; switch (sd->type) { + case DEVICE_TYPE_DRM: if (active) { - /* Weird legacy DRM semantics might return an error - * even though we're master. No way to detect that so - * fail at all times and let caller retry in inactive - * state. */ + /* Weird legacy DRM semantics might return an error even though we're master. No way to detect + * that so fail at all times and let caller retry in inactive state. */ r = sd_drmsetmaster(fd); if (r < 0) { close_nointr(fd); return r; } - } else { - /* DRM-Master is granted to the first user who opens a - * device automatically (ughh, racy!). Hence, we just - * drop DRM-Master in case we were the first. */ - sd_drmdropmaster(fd); - } + } else + /* DRM-Master is granted to the first user who opens a device automatically (ughh, + * racy!). Hence, we just drop DRM-Master in case we were the first. */ + (void) sd_drmdropmaster(fd); break; + case DEVICE_TYPE_EVDEV: if (!active) sd_eviocrevoke(fd); break; + case DEVICE_TYPE_UNKNOWN: default: /* fallback for devices wihout synchronizations */ @@ -195,29 +191,38 @@ static int session_device_start(SessionDevice *sd) { return 0; switch (sd->type) { + case DEVICE_TYPE_DRM: - /* Device is kept open. Simply call drmSetMaster() and hope - * there is no-one else. In case it fails, we keep the device - * paused. Maybe at some point we have a drmStealMaster(). */ - r = sd_drmsetmaster(sd->fd); - if (r < 0) - return r; + + if (sd->fd < 0) { + /* Open device if it isn't open yet */ + sd->fd = session_device_open(sd, true); + if (sd->fd < 0) + return sd->fd; + } else { + /* Device is kept open. Simply call drmSetMaster() and hope there is no-one else. In case it fails, we + * keep the device paused. Maybe at some point we have a drmStealMaster(). */ + r = sd_drmsetmaster(sd->fd); + if (r < 0) + return r; + } break; + case DEVICE_TYPE_EVDEV: - /* Evdev devices are revoked while inactive. Reopen it and we - * are fine. */ + /* Evdev devices are revoked while inactive. Reopen it and we are fine. */ r = session_device_open(sd, true); if (r < 0) return r; - /* For evdev devices, the file descriptor might be left - * uninitialized. This might happen while resuming into a - * session and logind has been restarted right before. */ + + /* For evdev devices, the file descriptor might be left uninitialized. This might happen while resuming + * into a session and logind has been restarted right before. */ safe_close(sd->fd); sd->fd = r; break; + case DEVICE_TYPE_UNKNOWN: default: - /* fallback for devices wihout synchronizations */ + /* fallback for devices without synchronizations */ break; } @@ -232,6 +237,7 @@ static void session_device_stop(SessionDevice *sd) { return; switch (sd->type) { + case DEVICE_TYPE_DRM: /* On DRM devices we simply drop DRM-Master but keep it open. * This allows the user to keep resources allocated. The @@ -239,6 +245,7 @@ static void session_device_stop(SessionDevice *sd) { * circumventing this. */ sd_drmdropmaster(sd->fd); break; + case DEVICE_TYPE_EVDEV: /* Revoke access on evdev file-descriptors during deactivation. * This will basically prevent any operations on the fd and @@ -246,6 +253,7 @@ static void session_device_stop(SessionDevice *sd) { * protection this way. */ sd_eviocrevoke(sd->fd); break; + case DEVICE_TYPE_UNKNOWN: default: /* fallback for devices without synchronization */ @@ -371,10 +379,8 @@ int session_device_new(Session *s, dev_t dev, bool open_device, SessionDevice ** goto error; r = hashmap_put(s->devices, &sd->dev, sd); - if (r < 0) { - r = -ENOMEM; + if (r < 0) goto error; - } if (open_device) { /* Open the device for the first time. We need a valid fd to pass back @@ -423,7 +429,7 @@ void session_device_free(SessionDevice *sd) { session_device_stop(sd); session_device_notify(sd, SESSION_DEVICE_RELEASE); - close_nointr(sd->fd); + safe_close(sd->fd); LIST_REMOVE(sd_by_device, sd->device->session_devices, sd); @@ -458,13 +464,15 @@ void session_device_resume_all(Session *s) { assert(s); HASHMAP_FOREACH(sd, s->devices, i) { - if (!sd->active) { - if (session_device_start(sd) < 0) - continue; - if (session_device_save(sd) < 0) - continue; - session_device_notify(sd, SESSION_DEVICE_RESUME); - } + if (sd->active) + continue; + + if (session_device_start(sd) < 0) + continue; + if (session_device_save(sd) < 0) + continue; + + session_device_notify(sd, SESSION_DEVICE_RESUME); } } @@ -475,25 +483,27 @@ void session_device_pause_all(Session *s) { assert(s); HASHMAP_FOREACH(sd, s->devices, i) { - if (sd->active) { - session_device_stop(sd); - session_device_notify(sd, SESSION_DEVICE_PAUSE); - } + if (!sd->active) + continue; + + session_device_stop(sd); + session_device_notify(sd, SESSION_DEVICE_PAUSE); } } unsigned int session_device_try_pause_all(Session *s) { + unsigned num_pending = 0; SessionDevice *sd; Iterator i; - unsigned int num_pending = 0; assert(s); HASHMAP_FOREACH(sd, s->devices, i) { - if (sd->active) { - session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE); - ++num_pending; - } + if (!sd->active) + continue; + + session_device_notify(sd, SESSION_DEVICE_TRY_PAUSE); + num_pending++; } return num_pending; @@ -516,7 +526,7 @@ int session_device_save(SessionDevice *sd) { return 0; m = strjoina("FDSTORE=1\n" - "FDNAME=session", sd->session->id); + "FDNAME=session-", sd->session->id); r = sd_pid_notify_with_fds(0, false, m, &sd->fd, 1); if (r < 0) @@ -527,11 +537,12 @@ int session_device_save(SessionDevice *sd) { } void session_device_attach_fd(SessionDevice *sd, int fd, bool active) { - assert(fd > 0); + assert(fd >= 0); assert(sd); assert(sd->fd < 0); assert(!sd->active); sd->fd = fd; + sd->pushed_fd = true; sd->active = active; } diff --git a/src/login/logind-session-device.h b/src/login/logind-session-device.h index a1cf17af92..a9ead7bdca 100644 --- a/src/login/logind-session-device.h +++ b/src/login/logind-session-device.h @@ -39,9 +39,9 @@ struct SessionDevice { dev_t dev; char *node; int fd; - bool active; - DeviceType type; - bool pushed_fd; + DeviceType type:3; + bool active:1; + bool pushed_fd:1; LIST_FIELDS(struct SessionDevice, sd_by_device); }; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 92eb2943fe..1859150b5e 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -1000,27 +1000,27 @@ static void session_remove_fifo(Session *s) { } } -bool session_check_gc(Session *s, bool drop_not_started) { +bool session_may_gc(Session *s, bool drop_not_started) { assert(s); if (drop_not_started && !s->started) - return false; + return true; if (!s->user) - return false; + return true; if (s->fifo_fd >= 0) { if (pipe_eof(s->fifo_fd) <= 0) - return true; + return false; } if (s->scope_job && manager_job_is_active(s->manager, s->scope_job)) - return true; + return false; if (s->scope && manager_unit_is_active(s->manager, s->scope)) - return true; + return false; - return false; + return true; } void session_add_to_gc_queue(Session *s) { diff --git a/src/login/logind-session.h b/src/login/logind-session.h index 8491832402..16a278c792 100644 --- a/src/login/logind-session.h +++ b/src/login/logind-session.h @@ -131,7 +131,7 @@ struct Session { Session *session_new(Manager *m, const char *id); void session_free(Session *s); void session_set_user(Session *s, User *u); -bool session_check_gc(Session *s, bool drop_not_started); +bool session_may_gc(Session *s, bool drop_not_started); void session_add_to_gc_queue(Session *s); int session_activate(Session *s); bool session_is_active(Session *s); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 32b2045696..f85564f221 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -680,25 +680,25 @@ int user_check_linger_file(User *u) { return access(p, F_OK) >= 0; } -bool user_check_gc(User *u, bool drop_not_started) { +bool user_may_gc(User *u, bool drop_not_started) { assert(u); if (drop_not_started && !u->started) - return false; + return true; if (u->sessions) - return true; + return false; if (user_check_linger_file(u) > 0) - return true; + return false; if (u->slice_job && manager_job_is_active(u->manager, u->slice_job)) - return true; + return false; if (u->service_job && manager_job_is_active(u->manager, u->service_job)) - return true; + return false; - return false; + return true; } void user_add_to_gc_queue(User *u) { diff --git a/src/login/logind-user.h b/src/login/logind-user.h index ad1686ffc5..c3452dcd08 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -66,7 +66,7 @@ User *user_free(User *u); DEFINE_TRIVIAL_CLEANUP_FUNC(User *, user_free); -bool user_check_gc(User *u, bool drop_not_started); +bool user_may_gc(User *u, bool drop_not_started); void user_add_to_gc_queue(User *u); int user_start(User *u); int user_stop(User *u, bool force); diff --git a/src/login/logind.c b/src/login/logind.c index d15d4cec5b..5220861c1d 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -35,6 +35,7 @@ #include "dirent-util.h" #include "fd-util.h" #include "format-util.h" +#include "fs-util.h" #include "logind.h" #include "process-util.h" #include "selinux-util.h" @@ -53,6 +54,7 @@ static void manager_reset_config(Manager *m) { m->handle_suspend_key = HANDLE_SUSPEND; m->handle_hibernate_key = HANDLE_HIBERNATE; m->handle_lid_switch = HANDLE_SUSPEND; + m->handle_lid_switch_ep = _HANDLE_ACTION_INVALID; m->handle_lid_switch_docked = HANDLE_IGNORE; m->power_key_ignore_inhibited = false; m->suspend_key_ignore_inhibited = false; @@ -182,7 +184,7 @@ static void manager_free(Manager *m) { udev_unref(m->udev); if (m->unlink_nologin) - (void) unlink("/run/nologin"); + (void) unlink_or_warn("/run/nologin"); bus_verify_polkit_async_registry_free(m->polkit_registry); @@ -253,11 +255,7 @@ static int manager_enumerate_buttons(Manager *m) { /* Loads buttons from udev */ - if (m->handle_power_key == HANDLE_IGNORE && - m->handle_suspend_key == HANDLE_IGNORE && - m->handle_hibernate_key == HANDLE_IGNORE && - m->handle_lid_switch == HANDLE_IGNORE && - m->handle_lid_switch_docked == HANDLE_IGNORE) + if (manager_all_buttons_ignored(m)) return 0; e = udev_enumerate_new(m->udev); @@ -325,7 +323,9 @@ static int manager_enumerate_seats(Manager *m) { s = hashmap_get(m->seats, de->d_name); if (!s) { - unlinkat(dirfd(d), de->d_name, 0); + if (unlinkat(dirfd(d), de->d_name, 0) < 0) + log_warning("Failed to remove /run/systemd/seats/%s: %m", + de->d_name); continue; } @@ -453,9 +453,15 @@ static int manager_attach_fds(Manager *m) { continue; } + if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) { + log_debug("Device fd doesn't actually point to device node: %m"); + close_nointr(fd); + continue; + } + sd = hashmap_get(s->devices, &st.st_rdev); if (!sd) { - /* Weird we got an fd for a session device which wasn't + /* Weird, we got an fd for a session device which wasn't * recorded in the session state file... */ log_warning("Got fd for missing session device [%u:%u] in session %s", major(st.st_rdev), minor(st.st_rdev), s->id); @@ -905,12 +911,7 @@ static int manager_connect_udev(Manager *m) { return r; /* Don't watch keys if nobody cares */ - if (m->handle_power_key != HANDLE_IGNORE || - m->handle_suspend_key != HANDLE_IGNORE || - m->handle_hibernate_key != HANDLE_IGNORE || - m->handle_lid_switch != HANDLE_IGNORE || - m->handle_lid_switch_docked != HANDLE_IGNORE) { - + if (!manager_all_buttons_ignored(m)) { m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev"); if (!m->udev_button_monitor) return -ENOMEM; @@ -966,7 +967,7 @@ static void manager_gc(Manager *m, bool drop_not_started) { LIST_REMOVE(gc_queue, m->seat_gc_queue, seat); seat->in_gc_queue = false; - if (!seat_check_gc(seat, drop_not_started)) { + if (seat_may_gc(seat, drop_not_started)) { seat_stop(seat, false); seat_free(seat); } @@ -977,14 +978,14 @@ static void manager_gc(Manager *m, bool drop_not_started) { session->in_gc_queue = false; /* First, if we are not closing yet, initiate stopping */ - if (!session_check_gc(session, drop_not_started) && + if (session_may_gc(session, drop_not_started) && session_get_state(session) != SESSION_CLOSING) session_stop(session, false); /* Normally, this should make the session referenced * again, if it doesn't then let's get rid of it * immediately */ - if (!session_check_gc(session, drop_not_started)) { + if (session_may_gc(session, drop_not_started)) { session_finalize(session); session_free(session); } @@ -995,11 +996,11 @@ static void manager_gc(Manager *m, bool drop_not_started) { user->in_gc_queue = false; /* First step: queue stop jobs */ - if (!user_check_gc(user, drop_not_started)) + if (user_may_gc(user, drop_not_started)) user_stop(user, false); /* Second step: finalize user */ - if (!user_check_gc(user, drop_not_started)) { + if (user_may_gc(user, drop_not_started)) { user_finalize(user); user_free(user); } diff --git a/src/login/logind.conf.in b/src/login/logind.conf.in index 6f720b7708..40a77dc7be 100644 --- a/src/login/logind.conf.in +++ b/src/login/logind.conf.in @@ -22,6 +22,7 @@ #HandleSuspendKey=suspend #HandleHibernateKey=hibernate #HandleLidSwitch=suspend +#HandleLidSwitchExternalPower=suspend #HandleLidSwitchDocked=ignore #PowerKeyIgnoreInhibited=no #SuspendKeyIgnoreInhibited=no diff --git a/src/login/logind.h b/src/login/logind.h index 8262367135..918bc1f919 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -118,6 +118,7 @@ struct Manager { HandleAction handle_suspend_key; HandleAction handle_hibernate_key; HandleAction handle_lid_switch; + HandleAction handle_lid_switch_ep; HandleAction handle_lid_switch_docked; bool power_key_ignore_inhibited; @@ -160,6 +161,8 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user); int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session); bool manager_is_docked_or_external_displays(Manager *m); +bool manager_is_on_external_power(void); +bool manager_all_buttons_ignored(Manager *m); extern const sd_bus_vtable manager_vtable[]; diff --git a/src/login/meson.build b/src/login/meson.build index e8e4f7bd7d..5b75382e5f 100644 --- a/src/login/meson.build +++ b/src/login/meson.build @@ -87,15 +87,8 @@ if conf.get('ENABLE_LOGIND') == 1 install_dir : dbuspolicydir) install_data('org.freedesktop.login1.service', install_dir : dbussystemservicedir) - - i18n.merge_file( - 'org.freedesktop.login1.policy', - input : 'org.freedesktop.login1.policy.in', - output : 'org.freedesktop.login1.policy', - po_dir : po_dir, - data_dirs : po_dir, - install : install_polkit, - install_dir : polkitpolicydir) + install_data('org.freedesktop.login1.policy', + install_dir : polkitpolicydir) install_data('70-power-switch.rules', install_dir : udevrulesdir) diff --git a/src/login/org.freedesktop.login1.policy b/src/login/org.freedesktop.login1.policy new file mode 100644 index 0000000000..f1d1f956d3 --- /dev/null +++ b/src/login/org.freedesktop.login1.policy @@ -0,0 +1,360 @@ + + + + + + + + The systemd Project + http://www.freedesktop.org/wiki/Software/systemd + + + Allow applications to inhibit system shutdown + Authentication is required for an application to inhibit system shutdown. + + no + yes + yes + + org.freedesktop.login1.inhibit-delay-shutdown org.freedesktop.login1.inhibit-block-sleep org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle + + + + Allow applications to delay system shutdown + Authentication is required for an application to delay system shutdown. + + yes + yes + yes + + org.freedesktop.login1.inhibit-delay-sleep + + + + Allow applications to inhibit system sleep + Authentication is required for an application to inhibit system sleep. + + no + yes + yes + + org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle + + + + Allow applications to delay system sleep + Authentication is required for an application to delay system sleep. + + yes + yes + yes + + + + + Allow applications to inhibit automatic system suspend + Authentication is required for an application to inhibit automatic system suspend. + + yes + yes + yes + + + + + Allow applications to inhibit system handling of the power key + Authentication is required for an application to inhibit system handling of the power key. + + no + yes + yes + + org.freedesktop.login1.inhibit-handle-suspend-key org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch + + + + Allow applications to inhibit system handling of the suspend key + Authentication is required for an application to inhibit system handling of the suspend key. + + no + yes + yes + + org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch + + + + Allow applications to inhibit system handling of the hibernate key + Authentication is required for an application to inhibit system handling of the hibernate key. + + no + yes + yes + + + + + Allow applications to inhibit system handling of the lid switch + Authentication is required for an application to inhibit system handling of the lid switch. + + no + yes + yes + + + + + Allow non-logged-in user to run programs + Explicit request is required to run programs as a non-logged-in user. + + yes + yes + yes + + + + + Allow non-logged-in users to run programs + Authentication is required to run programs as a non-logged-in user. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Allow attaching devices to seats + Authentication is required for attaching a device to a seat. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.flush-devices + + + + Flush device to seat attachments + Authentication is required for resetting how devices are attached to seats. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Power off the system + Authentication is required for powering off the system. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.set-wall-message + + + + Power off the system while other users are logged in + Authentication is required for powering off the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.power-off + + + + Power off the system while an application asked to inhibit it + Authentication is required for powering off the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.power-off + + + + Reboot the system + Authentication is required for rebooting the system. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.set-wall-message + + + + Reboot the system while other users are logged in + Authentication is required for rebooting the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.reboot + + + + Reboot the system while an application asked to inhibit it + Authentication is required for rebooting the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.reboot + + + + Halt the system + Authentication is required for halting the system. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.set-wall-message + + + + Halt the system while other users are logged in + Authentication is required for halting the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.halt + + + + Halt the system while an application asked to inhibit it + Authentication is required for halting the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.halt + + + + Suspend the system + Authentication is required for suspending the system. + + auth_admin_keep + auth_admin_keep + yes + + + + + Suspend the system while other users are logged in + Authentication is required for suspending the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.suspend + + + + Suspend the system while an application asked to inhibit it + Authentication is required for suspending the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.suspend + + + + Hibernate the system + Authentication is required for hibernating the system. + + auth_admin_keep + auth_admin_keep + yes + + + + + Hibernate the system while other users are logged in + Authentication is required for hibernating the system while other users are logged in. + + auth_admin_keep + auth_admin_keep + yes + + org.freedesktop.login1.hibernate + + + + Hibernate the system while an application asked to inhibit it + Authentication is required for hibernating the system while an application asked to inhibit it. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + org.freedesktop.login1.hibernate + + + + Manage active sessions, users and seats + Authentication is required for managing active sessions, users and seats. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Lock or unlock active sessions + Authentication is required to lock or unlock active sessions. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Allow indication to the firmware to boot to setup interface + Authentication is required to indicate to the firmware to boot to setup interface. + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + + Set a wall message + Authentication is required to set a wall message + + auth_admin_keep + auth_admin_keep + auth_admin_keep + + + + diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in deleted file mode 100644 index 47162022d2..0000000000 --- a/src/login/org.freedesktop.login1.policy.in +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - The systemd Project - http://www.freedesktop.org/wiki/Software/systemd - - - Allow applications to inhibit system shutdown - Authentication is required for an application to inhibit system shutdown. - - no - yes - yes - - org.freedesktop.login1.inhibit-delay-shutdown org.freedesktop.login1.inhibit-block-sleep org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle - - - - Allow applications to delay system shutdown - Authentication is required for an application to delay system shutdown. - - yes - yes - yes - - org.freedesktop.login1.inhibit-delay-sleep - - - - Allow applications to inhibit system sleep - Authentication is required for an application to inhibit system sleep. - - no - yes - yes - - org.freedesktop.login1.inhibit-delay-sleep org.freedesktop.login1.inhibit-block-idle - - - - Allow applications to delay system sleep - Authentication is required for an application to delay system sleep. - - yes - yes - yes - - - - - Allow applications to inhibit automatic system suspend - Authentication is required for an application to inhibit automatic system suspend. - - yes - yes - yes - - - - - Allow applications to inhibit system handling of the power key - Authentication is required for an application to inhibit system handling of the power key. - - no - yes - yes - - org.freedesktop.login1.inhibit-handle-suspend-key org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch - - - - Allow applications to inhibit system handling of the suspend key - Authentication is required for an application to inhibit system handling of the suspend key. - - no - yes - yes - - org.freedesktop.login1.inhibit-handle-hibernate-key org.freedesktop.login1.inhibit-handle-lid-switch - - - - Allow applications to inhibit system handling of the hibernate key - Authentication is required for an application to inhibit system handling of the hibernate key. - - no - yes - yes - - - - - Allow applications to inhibit system handling of the lid switch - Authentication is required for an application to inhibit system handling of the lid switch. - - no - yes - yes - - - - - Allow non-logged-in user to run programs - Explicit request is required to run programs as a non-logged-in user. - - yes - yes - yes - - - - - Allow non-logged-in users to run programs - Authentication is required to run programs as a non-logged-in user. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - - - - Allow attaching devices to seats - Authentication is required for attaching a device to a seat. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.flush-devices - - - - Flush device to seat attachments - Authentication is required for resetting how devices are attached to seats. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - - - - Power off the system - Authentication is required for powering off the system. - - auth_admin_keep - auth_admin_keep - yes - - org.freedesktop.login1.set-wall-message - - - - Power off the system while other users are logged in - Authentication is required for powering off the system while other users are logged in. - - auth_admin_keep - auth_admin_keep - yes - - org.freedesktop.login1.power-off - - - - Power off the system while an application asked to inhibit it - Authentication is required for powering off the system while an application asked to inhibit it. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.power-off - - - - Reboot the system - Authentication is required for rebooting the system. - - auth_admin_keep - auth_admin_keep - yes - - org.freedesktop.login1.set-wall-message - - - - Reboot the system while other users are logged in - Authentication is required for rebooting the system while other users are logged in. - - auth_admin_keep - auth_admin_keep - yes - - org.freedesktop.login1.reboot - - - - Reboot the system while an application asked to inhibit it - Authentication is required for rebooting the system while an application asked to inhibit it. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.reboot - - - - Halt the system - Authentication is required for halting the system. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.set-wall-message - - - - Halt the system while other users are logged in - Authentication is required for halting the system while other users are logged in. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.halt - - - - Halt the system while an application asked to inhibit it - Authentication is required for halting the system while an application asked to inhibit it. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.halt - - - - Suspend the system - Authentication is required for suspending the system. - - auth_admin_keep - auth_admin_keep - yes - - - - - Suspend the system while other users are logged in - Authentication is required for suspending the system while other users are logged in. - - auth_admin_keep - auth_admin_keep - yes - - org.freedesktop.login1.suspend - - - - Suspend the system while an application asked to inhibit it - Authentication is required for suspending the system while an application asked to inhibit it. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.suspend - - - - Hibernate the system - Authentication is required for hibernating the system. - - auth_admin_keep - auth_admin_keep - yes - - - - - Hibernate the system while other users are logged in - Authentication is required for hibernating the system while other users are logged in. - - auth_admin_keep - auth_admin_keep - yes - - org.freedesktop.login1.hibernate - - - - Hibernate the system while an application asked to inhibit it - Authentication is required for hibernating the system while an application asked to inhibit it. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - org.freedesktop.login1.hibernate - - - - Manage active sessions, users and seats - Authentication is required for managing active sessions, users and seats. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - - - - Lock or unlock active sessions - Authentication is required to lock or unlock active sessions. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - - - - Allow indication to the firmware to boot to setup interface - Authentication is required to indicate to the firmware to boot to setup interface. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - - - - Set a wall message - Authentication is required to set a wall message - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - - - -- cgit v1.2.1