summaryrefslogtreecommitdiff
path: root/src/login
diff options
context:
space:
mode:
Diffstat (limited to 'src/login')
-rw-r--r--src/login/logind-action.c2
-rw-r--r--src/login/logind-dbus.c27
-rw-r--r--src/login/logind-inhibit.h18
-rw-r--r--src/login/logind-seat.c2
-rw-r--r--src/login/logind-session.c58
-rw-r--r--src/login/logind.c2
-rw-r--r--src/login/pam_systemd.c56
-rw-r--r--src/login/user-runtime-dir.c2
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);