Based on upstream baae0358f349870544884e405e82e4be7d8add9f | From: Lennart Poettering | Date: Tue, 26 Nov 2013 04:05:00 +0000 | Subject: pam_systemd: do not set XDG_RUNTIME_DIR if the session's original user is not the same as the newly logged in one | It's better not to set any XDG_RUNTIME_DIR at all rather than one of a | different user. So let's do this. --- systemd-208/src/login/logind-dbus.c +++ systemd-208/src/login/logind-dbus.c 2013-11-26 13:37:05.730735774 +0000 @@ -523,6 +523,7 @@ static int bus_manager_create_session(Ma DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_STRING, &session->user->runtime_path, DBUS_TYPE_UNIX_FD, &fifo_fd, + DBUS_TYPE_UINT32, &session->user->uid, DBUS_TYPE_STRING, &cseat, DBUS_TYPE_UINT32, &vtnr, DBUS_TYPE_BOOLEAN, &exists, --- systemd-208/src/login/logind-session-dbus.c +++ systemd-208/src/login/logind-session-dbus.c 2013-11-26 13:36:07.478236401 +0000 @@ -755,6 +755,7 @@ int session_send_create_reply(Session *s DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_STRING, &s->user->runtime_path, DBUS_TYPE_UNIX_FD, &fifo_fd, + DBUS_TYPE_UINT32, &s->user->uid, DBUS_TYPE_STRING, &cseat, DBUS_TYPE_UINT32, &vtnr, DBUS_TYPE_BOOLEAN, &exists, --- systemd-208/src/login/pam-module.c +++ systemd-208/src/login/pam-module.c 2013-11-26 14:32:20.194235777 +0000 @@ -93,24 +93,18 @@ static int get_user_data( assert(ret_username); assert(ret_pw); - r = audit_loginuid_from_pid(0, &uid); - if (r >= 0) - pw = pam_modutil_getpwuid(handle, uid); - else { - r = pam_get_user(handle, &username, NULL); - if (r != PAM_SUCCESS) { - pam_syslog(handle, LOG_ERR, "Failed to get user name."); - return r; - } - - if (isempty(username)) { - pam_syslog(handle, LOG_ERR, "User name not valid."); - return PAM_AUTH_ERR; - } + r = pam_get_user(handle, &username, NULL); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to get user name."); + return r; + } - pw = pam_modutil_getpwnam(handle, username); + if (isempty(username)) { + pam_syslog(handle, LOG_ERR, "User name not valid."); + return PAM_AUTH_ERR; } + pw = pam_modutil_getpwnam(handle, username); if (!pw) { pam_syslog(handle, LOG_ERR, "Failed to get user data."); return PAM_USER_UNKNOWN; @@ -123,16 +117,14 @@ static int get_user_data( } static int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) { - _cleanup_free_ char *p = NULL; - int r; - _cleanup_close_ int fd = -1; union sockaddr_union sa = { .un.sun_family = AF_UNIX, }; + _cleanup_free_ char *p = NULL, *tty = NULL; + _cleanup_close_ int fd = -1; struct ucred ucred; socklen_t l; - _cleanup_free_ char *tty = NULL; - int v; + int v, r; assert(display); assert(vtnr); @@ -194,13 +186,12 @@ _public_ PAM_EXTERN int pam_sm_open_sess dbus_bool_t remote, existing; int r; uint32_t vtnr = 0; + uid_t original_uid; assert(handle); dbus_error_init(&error); - /* pam_syslog(handle, LOG_INFO, "pam-systemd initializing"); */ - /* Make this a NOP on non-logind systems */ if (!logind_running()) return PAM_SUCCESS; @@ -213,6 +204,9 @@ _public_ PAM_EXTERN int pam_sm_open_sess goto finish; } + if (debug) + pam_syslog(handle, LOG_INFO, "pam-systemd initializing"); + r = get_user_data(handle, &username, &pw); if (r != PAM_SUCCESS) goto finish; @@ -374,7 +368,11 @@ _public_ PAM_EXTERN int pam_sm_open_sess if (debug) pam_syslog(handle, LOG_DEBUG, "Asking logind to create session: " "uid=%u pid=%u service=%s type=%s class=%s seat=%s vtnr=%u tty=%s display=%s remote=%s remote_user=%s remote_host=%s", - uid, pid, service, type, class, seat, vtnr, tty, display, yes_no(remote), remote_user, remote_host); + pw->pw_uid, pid, + strempty(service), + type, class, + seat, vtnr, tty, display, + yes_no(remote), remote_user, remote_host); reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error); if (!reply) { @@ -388,6 +386,7 @@ _public_ PAM_EXTERN int pam_sm_open_sess DBUS_TYPE_OBJECT_PATH, &object_path, DBUS_TYPE_STRING, &runtime_path, DBUS_TYPE_UNIX_FD, &session_fd, + DBUS_TYPE_UINT32, &original_uid, DBUS_TYPE_STRING, &seat, DBUS_TYPE_UINT32, &vtnr, DBUS_TYPE_BOOLEAN, &existing, @@ -399,8 +398,8 @@ _public_ PAM_EXTERN int pam_sm_open_sess if (debug) pam_syslog(handle, LOG_DEBUG, "Reply from logind: " - "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u", - id, object_path, runtime_path, session_fd, seat, vtnr); + "id=%s object_path=%s runtime_path=%s session_fd=%d seat=%s vtnr=%u original_uid=%u", + id, object_path, runtime_path, session_fd, seat, vtnr, original_uid); r = pam_misc_setenv(handle, "XDG_SESSION_ID", id, 0); if (r != PAM_SUCCESS) { @@ -408,10 +407,24 @@ _public_ PAM_EXTERN int pam_sm_open_sess goto finish; } - r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); - if (r != PAM_SUCCESS) { - pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); - goto finish; + if (original_uid == pw->pw_uid) { + /* Don't set $XDG_RUNTIME_DIR if the user we now + * authenticated for does not match the original user + * of the session. We do this in order not to result + * in privileged apps clobbering the runtime directory + * unnecessarily. */ + + r = pam_misc_setenv(handle, "XDG_RUNTIME_DIR", runtime_path, 0); + if (r != PAM_SUCCESS) { + pam_syslog(handle, LOG_ERR, "Failed to set runtime dir."); + goto finish; + } + } else if (getenv("XDG_RUNTIME_DIR")) { + r = pam_putenv(handle, "XDG_RUNTIME_DIR"); + if (r != PAM_SUCCESS && r != PAM_BAD_ITEM) { + pam_syslog(handle, LOG_ERR, "Failed to unset runtime dir."); + } + (void) unsetenv("XDG_RUNTIME_DIR"); } if (!isempty(seat)) {