From: Lennart Poettering Date: Wed, 29 Nov 2023 10:18:01 +0000 (+0100) Subject: logind: rework logic to decide whether lock + idle + display applies to a session X-Git-Tag: v256-rc1~1186^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b4f01bc1df625842c2db423b460a755c5817c1f9;p=thirdparty%2Fsystemd.git logind: rework logic to decide whether lock + idle + display applies to a session Let's streamline the logic that decides whether the screen lock, idle timeout or display election mechanism applies to a session class. Let's add explicitly SESSION_CLASS_IS_XYZ() macros for each, and then resue them at all suitable places, and refuse any attempts to use the functionality on the wrong clases with a friendly error message. --- diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 26133ee6efc..582cbcbea84 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -413,6 +413,9 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t) { dual_timestamp k; int ih; + if (!SESSION_CLASS_CAN_IDLE(s->class)) + continue; + ih = session_get_idle_hint(s, &k); if (ih < 0) return ih; diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 6da3dd59d5a..d4e656ae85d 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -216,7 +216,9 @@ int bus_session_method_lock(sd_bus_message *message, void *userdata, sd_bus_erro if (r == 0) return 1; /* Will call us back */ - r = session_send_lock(s, strstr(sd_bus_message_get_member(message), "Lock")); + r = session_send_lock(s, /* lock= */ strstr(sd_bus_message_get_member(message), "Lock")); + if (r == -ENOTTY) + return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Session does not support lock screen."); if (r < 0) return r; @@ -248,7 +250,7 @@ static int method_set_idle_hint(sd_bus_message *message, void *userdata, sd_bus_ r = session_set_idle_hint(s, b); if (r == -ENOTTY) - return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical sessions."); + return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Idle hint control is not supported on non-graphical and non-user sessions."); if (r < 0) return r; @@ -278,7 +280,11 @@ static int method_set_locked_hint(sd_bus_message *message, void *userdata, sd_bu if (uid != 0 && uid != s->user->user_record->uid) return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Only owner of session may set locked hint"); - session_set_locked_hint(s, b); + r = session_set_locked_hint(s, b); + if (r == -ENOTTY) + return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Session does not support lock screen."); + if (r < 0) + return r; return sd_bus_reply_method_return(message, NULL); } @@ -765,6 +771,9 @@ int session_send_lock(Session *s, bool lock) { assert(s); + if (!SESSION_CLASS_CAN_LOCK(s->class)) + return -ENOTTY; + p = session_bus_path(s); if (!p) return -ENOMEM; @@ -786,6 +795,9 @@ int session_send_lock_all(Manager *m, bool lock) { HASHMAP_FOREACH(session, m->sessions) { int k; + if (!SESSION_CLASS_CAN_LOCK(session->class)) + continue; + k = session_send_lock(session, lock); if (k < 0) r = k; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index e9d95e1db8f..3226f3db783 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -1155,7 +1155,9 @@ found_atime: int session_set_idle_hint(Session *s, bool b) { assert(s); - if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) + if (!SESSION_CLASS_CAN_IDLE(s->class)) /* Only some session classes know the idle concept at all */ + return -ENOTTY; + if (!SESSION_TYPE_IS_GRAPHICAL(s->type)) /* And only graphical session types can set the field explicitly */ return -ENOTTY; if (s->idle_hint == b) @@ -1181,15 +1183,20 @@ int session_get_locked_hint(Session *s) { return s->locked_hint; } -void session_set_locked_hint(Session *s, bool b) { +int session_set_locked_hint(Session *s, bool b) { assert(s); + if (!SESSION_CLASS_CAN_LOCK(s->class)) + return -ENOTTY; + if (s->locked_hint == b) - return; + return 0; s->locked_hint = b; + (void) session_save(s); + (void) session_send_changed(s, "LockedHint", NULL); - session_send_changed(s, "LockedHint", NULL); + return 1; } void session_set_type(Session *s, SessionType t) { diff --git a/src/login/logind-session.h b/src/login/logind-session.h index 3cc416bf682..9cba60c18f6 100644 --- a/src/login/logind-session.h +++ b/src/login/logind-session.h @@ -45,6 +45,15 @@ typedef enum SessionClass { /* Which session classes can pin our user tracking? */ #define SESSION_CLASS_PIN_USER(class) (!IN_SET((class), SESSION_MANAGER, SESSION_MANAGER_EARLY)) +/* Which session classes decide whether system is idle? (should only cover sessions that have input, and are not idle screens themselves)*/ +#define SESSION_CLASS_CAN_IDLE(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER)) + +/* Which session classes have a lock screen concept? */ +#define SESSION_CLASS_CAN_LOCK(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY)) + +/* Which sessions are candidates to become "display" sessions */ +#define SESSION_CLASS_CAN_DISPLAY(class) (IN_SET((class), SESSION_USER, SESSION_USER_EARLY, SESSION_GREETER)) + typedef enum SessionType { SESSION_UNSPECIFIED, SESSION_TTY, @@ -158,7 +167,7 @@ bool session_is_active(Session *s); int session_get_idle_hint(Session *s, dual_timestamp *t); int session_set_idle_hint(Session *s, bool b); int session_get_locked_hint(Session *s); -void session_set_locked_hint(Session *s, bool b); +int session_set_locked_hint(Session *s, bool b); void session_set_type(Session *s, SessionType t); int session_set_display(Session *s, const char *display); int session_set_tty(Session *s, const char *tty); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 6e41ac6ef60..6de7c47c7a7 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -591,6 +591,9 @@ int user_get_idle_hint(User *u, dual_timestamp *t) { dual_timestamp k; int ih; + if (!SESSION_CLASS_CAN_IDLE(s->class)) + continue; + ih = session_get_idle_hint(s, &k); if (ih < 0) return ih; @@ -783,7 +786,7 @@ 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 IN_SET(s->class, SESSION_USER, SESSION_GREETER) && s->started && !s->stopping; + return SESSION_CLASS_CAN_DISPLAY(s->class) && s->started && !s->stopping; } static int elect_display_compare(Session *s1, Session *s2) {