tree-wide: dlopen libpam in pam plugins

Same reasoning as for cryptsetup tokens. It means we can include
the pam plugins in the main systemd package without the package 
manager introducing a dependency on libpam. It also makes things
more consistent and makes writing the upcoming linking test script
a lot simpler.

At the same time, we get rid of the libpam_misc dependency as the
one symbol we were using from it is trivial to reimplement ourselves.
This commit is contained in:
Daan De Meyer
2026-05-18 21:17:38 +00:00
parent 94d745c42c
commit 62053ee289
7 changed files with 132 additions and 110 deletions
+23
View File
@@ -25,10 +25,15 @@ static void *libpam_dl = NULL;
DLSYM_PROTOTYPE(pam_acct_mgmt) = NULL;
DLSYM_PROTOTYPE(pam_close_session) = NULL;
DLSYM_PROTOTYPE(pam_end) = NULL;
DLSYM_PROTOTYPE(pam_get_authtok_noverify) = NULL;
DLSYM_PROTOTYPE(pam_get_authtok_verify) = NULL;
DLSYM_PROTOTYPE(pam_get_data) = NULL;
DLSYM_PROTOTYPE(pam_get_item) = NULL;
DLSYM_PROTOTYPE(pam_get_user) = NULL;
DLSYM_PROTOTYPE(pam_getenv) = NULL;
DLSYM_PROTOTYPE(pam_getenvlist) = NULL;
DLSYM_PROTOTYPE(pam_open_session) = NULL;
DLSYM_PROTOTYPE(pam_prompt) = NULL;
DLSYM_PROTOTYPE(pam_putenv) = NULL;
DLSYM_PROTOTYPE(pam_set_data) = NULL;
DLSYM_PROTOTYPE(pam_set_item) = NULL;
@@ -361,6 +366,19 @@ int pam_prompt_graceful(pam_handle_t *pamh, int style, char **ret_response, cons
return PAM_SUCCESS;
}
int pam_putenv_assign(pam_handle_t *pamh, const char *name, const char *value) {
_cleanup_(erase_and_freep) char *s = NULL;
assert(pamh);
assert(name);
assert(value);
if (asprintf(&s, "%s=%s", name, value) < 0)
return PAM_BUF_ERR;
return sym_pam_putenv(pamh, s);
}
#endif
int dlopen_libpam(int log_level) {
@@ -378,10 +396,15 @@ int dlopen_libpam(int log_level) {
DLSYM_ARG(pam_acct_mgmt),
DLSYM_ARG(pam_close_session),
DLSYM_ARG(pam_end),
DLSYM_ARG(pam_get_authtok_noverify),
DLSYM_ARG(pam_get_authtok_verify),
DLSYM_ARG(pam_get_data),
DLSYM_ARG(pam_get_item),
DLSYM_ARG(pam_get_user),
DLSYM_ARG(pam_getenv),
DLSYM_ARG(pam_getenvlist),
DLSYM_ARG(pam_open_session),
DLSYM_ARG(pam_prompt),
DLSYM_ARG(pam_putenv),
DLSYM_ARG(pam_set_data),
DLSYM_ARG(pam_set_item),
+15 -1
View File
@@ -6,7 +6,7 @@
#if HAVE_PAM
#include <security/pam_appl.h>
#include <security/pam_ext.h>
#include <security/pam_modules.h> /* IWYU pragma: export */
#include <security/pam_modules.h> /* IWYU pragma: export */
#include <syslog.h>
#include "dlfcn-util.h"
@@ -14,10 +14,15 @@
extern DLSYM_PROTOTYPE(pam_acct_mgmt);
extern DLSYM_PROTOTYPE(pam_close_session);
extern DLSYM_PROTOTYPE(pam_end);
extern DLSYM_PROTOTYPE(pam_get_authtok_noverify);
extern DLSYM_PROTOTYPE(pam_get_authtok_verify);
extern DLSYM_PROTOTYPE(pam_get_data);
extern DLSYM_PROTOTYPE(pam_get_item);
extern DLSYM_PROTOTYPE(pam_get_user);
extern DLSYM_PROTOTYPE(pam_getenv);
extern DLSYM_PROTOTYPE(pam_getenvlist);
extern DLSYM_PROTOTYPE(pam_open_session);
extern DLSYM_PROTOTYPE(pam_prompt);
extern DLSYM_PROTOTYPE(pam_putenv);
extern DLSYM_PROTOTYPE(pam_set_data);
extern DLSYM_PROTOTYPE(pam_set_item);
@@ -27,6 +32,11 @@ extern DLSYM_PROTOTYPE(pam_strerror);
extern DLSYM_PROTOTYPE(pam_syslog);
extern DLSYM_PROTOTYPE(pam_vsyslog);
/* sym_pam_prompt() replacement for the pam_info() macro from <security/pam_ext.h>, which expands to a direct
* pam_prompt() call. */
#define sym_pam_info(pamh, fmt, ...) \
sym_pam_prompt((pamh), PAM_TEXT_INFO, NULL, (fmt), ## __VA_ARGS__)
void pam_log_setup(void);
int errno_to_pam_error(int error) _const_;
@@ -90,6 +100,10 @@ int pam_get_data_many_internal(pam_handle_t *pamh, ...) _sentinel_;
int pam_prompt_graceful(pam_handle_t *pamh, int style, char **ret_response, const char *fmt, ...) _printf_(4,5);
/* Equivalent of pam_misc_setenv(pamh, name, value, 0), without the libpam_misc dep — builds "name=value"
* and hands it to sym_pam_putenv(), then erases the buffer before freeing in case it carried a secret. */
int pam_putenv_assign(pam_handle_t *pamh, const char *name, const char *value);
#endif
int dlopen_libpam(int log_level);