From a6a6197e9d8363e133d1d8deb9e2aa84c28f5029 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 21 Feb 2024 13:21:31 +0900 Subject: [PATCH] pam_systemd_home: always close already opened bus connection in open_session() Fixes #31375. --- src/home/pam_systemd_home.c | 6 ++++++ src/shared/pam-util.c | 26 ++++++++++++++++++++++++++ src/shared/pam-util.h | 1 + 3 files changed, 33 insertions(+) diff --git a/src/home/pam_systemd_home.c b/src/home/pam_systemd_home.c index 4904516724d..077f9208cb5 100644 --- a/src/home/pam_systemd_home.c +++ b/src/home/pam_systemd_home.c @@ -826,6 +826,12 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (r != PAM_SUCCESS) return r; + /* Explicitly get saved PamBusData here. Otherwise, this function may succeed without setting 'd' + * even if there is an opened sd-bus connection, and it will be leaked. See issue #31375. */ + r = pam_get_bus_data(handle, "pam-systemd-home", &d); + if (r != PAM_SUCCESS) + return r; + r = acquire_home(handle, flags, debug, &d); if (r == PAM_USER_UNKNOWN) /* Not managed by us? Don't complain. */ return PAM_SUCCESS; diff --git a/src/shared/pam-util.c b/src/shared/pam-util.c index c93ab9afebe..e3d92038aa8 100644 --- a/src/shared/pam-util.c +++ b/src/shared/pam-util.c @@ -209,6 +209,32 @@ int pam_release_bus_connection(pam_handle_t *handle, const char *module_name) { return PAM_SUCCESS; } +int pam_get_bus_data( + pam_handle_t *handle, + const char *module_name, + PamBusData **ret) { + + PamBusData *d = NULL; + _cleanup_free_ char *cache_id = NULL; + int r; + + assert(handle); + assert(module_name); + assert(ret); + + cache_id = pam_make_bus_cache_id(module_name); + if (!cache_id) + return pam_log_oom(handle); + + /* We cache the bus connection so that we can share it between the session and the authentication hooks */ + r = pam_get_data(handle, cache_id, (const void**) &d); + if (!IN_SET(r, PAM_SUCCESS, PAM_NO_MODULE_DATA)) + return pam_syslog_pam_error(handle, LOG_ERR, r, "Failed to get bus connection: @PAMERR@"); + + *ret = d; + return PAM_SUCCESS; +} + void pam_cleanup_free(pam_handle_t *handle, void *data, int error_status) { /* A generic destructor for pam_set_data() that just frees the specified data */ free(data); diff --git a/src/shared/pam-util.h b/src/shared/pam-util.h index 3439d4246e1..51bffc329e5 100644 --- a/src/shared/pam-util.h +++ b/src/shared/pam-util.h @@ -37,6 +37,7 @@ void pam_bus_data_disconnectp(PamBusData **d); * helps avoid a clash in the internal data structures of sd-bus. It will be used as key for cache items. */ int pam_acquire_bus_connection(pam_handle_t *handle, const char *module_name, sd_bus **ret_bus, PamBusData **ret_bus_data); int pam_release_bus_connection(pam_handle_t *handle, const char *module_name); +int pam_get_bus_data(pam_handle_t *handle, const char *module_name, PamBusData **ret); void pam_cleanup_free(pam_handle_t *handle, void *data, int error_status); -- 2.47.3