diff options
Diffstat (limited to 'src/login')
-rw-r--r-- | src/login/logind-action.c | 2 | ||||
-rw-r--r-- | src/login/logind-dbus.c | 27 | ||||
-rw-r--r-- | src/login/logind-inhibit.h | 18 | ||||
-rw-r--r-- | src/login/logind-seat.c | 2 | ||||
-rw-r--r-- | src/login/logind-session.c | 58 | ||||
-rw-r--r-- | src/login/logind.c | 2 | ||||
-rw-r--r-- | src/login/pam_systemd.c | 56 | ||||
-rw-r--r-- | src/login/user-runtime-dir.c | 2 |
8 files changed, 86 insertions, 81 deletions
diff --git a/src/login/logind-action.c b/src/login/logind-action.c index e4e6c90191..6c9366761d 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -121,7 +121,7 @@ int manager_handle_action( return -EOPNOTSUPP; } - if (m->action_what) { + if (m->action_what > 0) { log_debug("Action already in progress, ignoring."); return -EALREADY; } diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index bd9f5ac4d6..8ab498fdc2 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1474,23 +1474,15 @@ int manager_set_lid_switch_ignore(Manager *m, usec_t until) { } static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { - - static const char * const signal_name[_INHIBIT_WHAT_MAX] = { - [INHIBIT_SHUTDOWN] = "PrepareForShutdown", - [INHIBIT_SLEEP] = "PrepareForSleep" - }; - int active = _active; assert(m); - assert(w >= 0); - assert(w < _INHIBIT_WHAT_MAX); - assert(signal_name[w]); + assert(IN_SET(w, INHIBIT_SHUTDOWN, INHIBIT_SLEEP)); return sd_bus_emit_signal(m->bus, "/org/freedesktop/login1", "org.freedesktop.login1.Manager", - signal_name[w], + w == INHIBIT_SHUTDOWN ? "PrepareForShutdown" : "PrepareForSleep", "b", active); } @@ -1502,7 +1494,6 @@ static int execute_shutdown_or_sleep( sd_bus_error *error) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; - char *c = NULL; const char *p; int r; @@ -1530,15 +1521,11 @@ static int execute_shutdown_or_sleep( if (r < 0) goto error; - c = strdup(p); - if (!c) { - r = -ENOMEM; + r = free_and_strdup(&m->action_job, p); + if (r < 0) goto error; - } m->action_unit = unit_name; - free(m->action_job); - m->action_job = c; m->action_what = w; /* Make sure the lid switch is ignored for a while */ @@ -1656,7 +1643,7 @@ int bus_manager_shutdown_or_sleep_now_or_later( assert(m); assert(unit_name); assert(w > 0); - assert(w <= _INHIBIT_WHAT_MAX); + assert(w < _INHIBIT_WHAT_MAX); assert(!m->action_job); r = unit_load_state(m->bus, unit_name, &load_state); @@ -1773,7 +1760,7 @@ static int method_do_shutdown_or_sleep( return r; /* Don't allow multiple jobs being executed at the same time */ - if (m->action_what) + if (m->action_what > 0) return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress"); if (sleep_verb) { @@ -2012,7 +1999,7 @@ static int manager_scheduled_shutdown_handler( assert_not_reached("unexpected shutdown type"); /* Don't allow multiple jobs being executed at the same time */ - if (m->action_what) { + if (m->action_what > 0) { r = -EALREADY; log_error("Scheduled shutdown to %s failed: shutdown or sleep operation already in progress", target); goto error; diff --git a/src/login/logind-inhibit.h b/src/login/logind-inhibit.h index d358a48559..650587106d 100644 --- a/src/login/logind-inhibit.h +++ b/src/login/logind-inhibit.h @@ -4,15 +4,15 @@ typedef struct Inhibitor Inhibitor; typedef enum InhibitWhat { - INHIBIT_SHUTDOWN = 1, - INHIBIT_SLEEP = 2, - INHIBIT_IDLE = 4, - INHIBIT_HANDLE_POWER_KEY = 8, - INHIBIT_HANDLE_SUSPEND_KEY = 16, - INHIBIT_HANDLE_HIBERNATE_KEY = 32, - INHIBIT_HANDLE_LID_SWITCH = 64, - _INHIBIT_WHAT_MAX = 128, - _INHIBIT_WHAT_INVALID = -1 + INHIBIT_SHUTDOWN = 1 << 0, + INHIBIT_SLEEP = 1 << 1, + INHIBIT_IDLE = 1 << 2, + INHIBIT_HANDLE_POWER_KEY = 1 << 3, + INHIBIT_HANDLE_SUSPEND_KEY = 1 << 4, + INHIBIT_HANDLE_HIBERNATE_KEY = 1 << 5, + INHIBIT_HANDLE_LID_SWITCH = 1 << 6, + _INHIBIT_WHAT_MAX = 1 << 7, + _INHIBIT_WHAT_INVALID = -1 } InhibitWhat; typedef enum InhibitMode { diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index c758ffd5fa..a6d88f8e7b 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -376,7 +376,7 @@ int seat_read_active_vt(Seat *s) { k = read(s->manager->console_active_fd, t, sizeof(t)-1); if (k <= 0) { - log_error("Failed to read current console: %s", k < 0 ? strerror(-errno) : "EOF"); + log_error("Failed to read current console: %s", k < 0 ? strerror(errno) : "EOF"); return k < 0 ? -errno : -EIO; } diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 4b4dd4c060..90a9108566 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -1227,54 +1227,26 @@ error: } static void session_restore_vt(Session *s) { - pid_t pid; - int r; - - if (s->vtnr < 1) - return; + int r, vt, old_fd; - if (s->vtfd < 0) - return; - - /* The virtual terminal can potentially be entering in hung-up state at any time - * depending on when the controlling process exits. - * - * If the controlling process exits while we're restoring the virtual terminal, - * the VT will enter in hung-up state and we'll fail at restoring it. To prevent - * this case, we kick off the current controlling process (if any) in a child - * process so logind doesn't play around with tty ownership. - * - * If the controlling process already exited, getting a fresh handle to the - * virtual terminal reset the hung-up state. */ - r = safe_fork("(logind)", FORK_REOPEN_LOG|FORK_CLOSE_ALL_FDS|FORK_RESET_SIGNALS|FORK_WAIT|FORK_LOG, &pid); - if (r == 0) { - char path[sizeof("/dev/tty") + DECIMAL_STR_MAX(s->vtnr)]; - int vt; - - /* We must be a session leader in order to become the controlling process. */ - pid = setsid(); - if (pid < 0) { - log_error_errno(errno, "Failed to become session leader: %m"); - _exit(EXIT_FAILURE); - } + /* We need to get a fresh handle to the virtual terminal, + * since the old file-descriptor is potentially in a hung-up + * state after the controlling process exited; we do a + * little dance to avoid having the terminal be available + * for reuse before we've cleaned it up. + */ + old_fd = TAKE_FD(s->vtfd); - sprintf(path, "/dev/tty%u", s->vtnr); - vt = acquire_terminal(path, ACQUIRE_TERMINAL_FORCE, USEC_INFINITY); - if (vt < 0) { - log_error_errno(vt, "Cannot acquire VT %s of session %s: %m", path, s->id); - _exit(EXIT_FAILURE); - } + vt = session_open_vt(s); + safe_close(old_fd); - r = vt_restore(vt); - if (r < 0) - log_warning_errno(r, "Failed to restore VT, ignoring: %m"); + if (vt < 0) + return; - /* Give up and release the controlling terminal. */ - safe_close(vt); - _exit(EXIT_SUCCESS); - } + r = vt_restore(vt); + if (r < 0) + log_warning_errno(r, "Failed to restore VT, ignoring: %m"); - /* Close the fd in any cases. */ s->vtfd = safe_close(s->vtfd); } diff --git a/src/login/logind.c b/src/login/logind.c index 8d85de9b43..95ec0a57c6 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -146,7 +146,7 @@ static Manager* manager_unref(Manager *m) { bus_verify_polkit_async_registry_free(m->polkit_registry); - sd_bus_unref(m->bus); + sd_bus_flush_close_unref(m->bus); sd_event_unref(m->event); safe_close(m->reserve_vt_fd); diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index c7d9dcf4e2..997b74eb88 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -28,6 +28,7 @@ #include "path-util.h" #include "process-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "strv.h" #include "terminal-util.h" #include "util.h" @@ -190,6 +191,45 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_ return 0; } +static int export_legacy_dbus_address( + pam_handle_t *handle, + uid_t uid, + const char *runtime) { + + const char *s; + _cleanup_free_ char *t = NULL; + int r = PAM_BUF_ERR; + + /* We need to export $DBUS_SESSION_BUS_ADDRESS because various applications will not connect + * correctly to the bus without it. This setting matches what dbus.socket does for the user + * session using 'systemctl --user set-environment'. We want to have the same configuration + * in processes started from the PAM session. + * + * The setting of the address is guarded by the access() check because it is also possible to compile + * dbus without --enable-user-session, in which case this socket is not used, and + * $DBUS_SESSION_BUS_ADDRESS should not be set. An alternative approach would to not do the access() + * check here, and let applications try on their own, by using "unix:path=%s/bus;autolaunch:". But we + * expect the socket to be present by the time we do this check, so we can just as well check once + * here. */ + + s = strjoina(runtime, "/bus"); + if (access(s, F_OK) < 0) + return PAM_SUCCESS; + + if (asprintf(&t, DEFAULT_USER_BUS_ADDRESS_FMT, runtime) < 0) + goto error; + + r = pam_misc_setenv(handle, "DBUS_SESSION_BUS_ADDRESS", t, 0); + if (r != PAM_SUCCESS) + goto error; + + return PAM_SUCCESS; + +error: + pam_syslog(handle, LOG_ERR, "Failed to set bus variable."); + return r; +} + static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, const char *limit) { uint64_t val; int r; @@ -392,11 +432,9 @@ _public_ PAM_EXTERN int pam_sm_open_session( pam_get_item(handle, PAM_SERVICE, (const void**) &service); if (streq_ptr(service, "systemd-user")) { - _cleanup_free_ char *rt = NULL; - - if (asprintf(&rt, "/run/user/"UID_FMT, pw->pw_uid) < 0) - return PAM_BUF_ERR; + char rt[STRLEN("/run/user/") + DECIMAL_STR_MAX(uid_t)]; + xsprintf(rt, "/run/user/"UID_FMT, pw->pw_uid); if (validate_runtime_directory(handle, rt, pw->pw_uid)) { r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", rt, 0); if (r != PAM_SUCCESS) { @@ -405,6 +443,10 @@ _public_ PAM_EXTERN int pam_sm_open_session( } } + r = export_legacy_dbus_address(handle, pw->pw_uid, rt); + if (r != PAM_SUCCESS) + return r; + return PAM_SUCCESS; } @@ -569,7 +611,7 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (r < 0) { if (sd_bus_error_has_name(&error, BUS_ERROR_SESSION_BUSY)) { if (debug) - pam_syslog(handle, LOG_DEBUG, "Cannot create session: %s", bus_error_message(&error, r)); + pam_syslog(handle, LOG_DEBUG, "Not creating session: %s", bus_error_message(&error, r)); return PAM_SUCCESS; } else { pam_syslog(handle, LOG_ERR, "Failed to create session: %s", bus_error_message(&error, r)); @@ -613,6 +655,10 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (r != PAM_SUCCESS) return r; } + + r = export_legacy_dbus_address(handle, pw->pw_uid, runtime_path); + if (r != PAM_SUCCESS) + return r; } /* Most likely we got the session/type/class from environment variables, but might have gotten the data diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c index 5e58e4baad..eb66e18de1 100644 --- a/src/login/user-runtime-dir.c +++ b/src/login/user-runtime-dir.c @@ -22,7 +22,7 @@ static int acquire_runtime_dir_size(uint64_t *ret) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL; + _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; int r; r = sd_bus_default_system(&bus); |