File pam_modutil_get-overwrite-password-at-free.patch of Package pam
From e2fdc55d9d8d277c9395f96c3bf2938bacc84f62 Mon Sep 17 00:00:00 2001
From: Thorsten Kukuk <kukuk@suse.com>
Date: Thu, 14 Aug 2025 12:01:25 +0200
Subject: [PATCH] pam_modutil_get*: overwrite password at free (#846)
Make sure that the buffer containing encrypted passwords (struct group,
passwd and shadow) get's erased before free, so that they are not
available anymore if the memory get allocated again.
---
libpam/pam_modutil_cleanup.c | 40 +++++++++++++++++++++++++++++++++++
libpam/pam_modutil_getgrgid.c | 2 +-
libpam/pam_modutil_getgrnam.c | 2 +-
libpam/pam_modutil_getpwnam.c | 2 +-
libpam/pam_modutil_getpwuid.c | 2 +-
libpam/pam_modutil_getspnam.c | 2 +-
libpam/pam_modutil_private.h | 9 ++++++++
7 files changed, 54 insertions(+), 5 deletions(-)
diff --git a/libpam/pam_modutil_cleanup.c b/libpam/pam_modutil_cleanup.c
index 2077cbd7..46233736 100644
--- a/libpam/pam_modutil_cleanup.c
+++ b/libpam/pam_modutil_cleanup.c
@@ -5,8 +5,12 @@
*/
#include "pam_modutil_private.h"
+#include "pam_inline.h"
+#include <grp.h>
+#include <pwd.h>
#include <stdlib.h>
+#include <shadow.h>
void
pam_modutil_cleanup (pam_handle_t *pamh UNUSED, void *data,
@@ -15,3 +19,39 @@ pam_modutil_cleanup (pam_handle_t *pamh UNUSED, void *data,
/* junk it */
free(data);
}
+
+void
+pam_modutil_cleanup_group (pam_handle_t *pamh UNUSED, void *data,
+ int error_status UNUSED)
+{
+ struct group *gr = data;
+
+ if (gr && gr->gr_passwd)
+ pam_overwrite_string(gr->gr_passwd);
+
+ free(data);
+}
+
+void
+pam_modutil_cleanup_passwd (pam_handle_t *pamh UNUSED, void *data,
+ int error_status UNUSED)
+{
+ struct passwd *pw = data;
+
+ if (pw && pw->pw_passwd)
+ pam_overwrite_string(pw->pw_passwd);
+
+ free(data);
+}
+
+void
+pam_modutil_cleanup_shadow (pam_handle_t *pamh UNUSED, void *data,
+ int error_status UNUSED)
+{
+ struct spwd *sp = data;
+
+ if (sp && sp->sp_pwdp)
+ pam_overwrite_string(sp->sp_pwdp);
+
+ free(data);
+}
diff --git a/libpam/pam_modutil_getgrgid.c b/libpam/pam_modutil_getgrgid.c
index 6c2bb31b..fa3436c5 100644
--- a/libpam/pam_modutil_getgrgid.c
+++ b/libpam/pam_modutil_getgrgid.c
@@ -62,7 +62,7 @@ pam_modutil_getgrgid(pam_handle_t *pamh, gid_t gid)
status = PAM_NO_MODULE_DATA;
if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
status = pam_set_data(pamh, data_name,
- result, pam_modutil_cleanup);
+ result, pam_modutil_cleanup_group);
}
free(data_name);
if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getgrnam.c b/libpam/pam_modutil_getgrnam.c
index 418b9e47..533a8ce6 100644
--- a/libpam/pam_modutil_getgrnam.c
+++ b/libpam/pam_modutil_getgrnam.c
@@ -62,7 +62,7 @@ pam_modutil_getgrnam(pam_handle_t *pamh, const char *group)
status = PAM_NO_MODULE_DATA;
if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
status = pam_set_data(pamh, data_name,
- result, pam_modutil_cleanup);
+ result, pam_modutil_cleanup_group);
}
free(data_name);
if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getpwnam.c b/libpam/pam_modutil_getpwnam.c
index 5701ba9c..de654aeb 100644
--- a/libpam/pam_modutil_getpwnam.c
+++ b/libpam/pam_modutil_getpwnam.c
@@ -62,7 +62,7 @@ pam_modutil_getpwnam(pam_handle_t *pamh, const char *user)
status = PAM_NO_MODULE_DATA;
if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
status = pam_set_data(pamh, data_name,
- result, pam_modutil_cleanup);
+ result, pam_modutil_cleanup_passwd);
}
free(data_name);
if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getpwuid.c b/libpam/pam_modutil_getpwuid.c
index d3bb7231..6534958c 100644
--- a/libpam/pam_modutil_getpwuid.c
+++ b/libpam/pam_modutil_getpwuid.c
@@ -62,7 +62,7 @@ pam_modutil_getpwuid(pam_handle_t *pamh, uid_t uid)
status = PAM_NO_MODULE_DATA;
if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
status = pam_set_data(pamh, data_name,
- result, pam_modutil_cleanup);
+ result, pam_modutil_cleanup_passwd);
}
free(data_name);
if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_getspnam.c b/libpam/pam_modutil_getspnam.c
index 9aa6ac9a..9733eda0 100644
--- a/libpam/pam_modutil_getspnam.c
+++ b/libpam/pam_modutil_getspnam.c
@@ -62,7 +62,7 @@ pam_modutil_getspnam(pam_handle_t *pamh, const char *user)
status = PAM_NO_MODULE_DATA;
if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
status = pam_set_data(pamh, data_name,
- result, pam_modutil_cleanup);
+ result, pam_modutil_cleanup_shadow);
}
free(data_name);
if (status == PAM_SUCCESS) {
diff --git a/libpam/pam_modutil_private.h b/libpam/pam_modutil_private.h
index 98a30f68..611c7696 100644
--- a/libpam/pam_modutil_private.h
+++ b/libpam/pam_modutil_private.h
@@ -20,5 +20,14 @@
extern void
pam_modutil_cleanup(pam_handle_t *pamh, void *data,
int error_status);
+extern void
+pam_modutil_cleanup_group(pam_handle_t *pamh, void *data,
+ int error_status);
+extern void
+pam_modutil_cleanup_passwd(pam_handle_t *pamh, void *data,
+ int error_status);
+extern void
+pam_modutil_cleanup_shadow(pam_handle_t *pamh, void *data,
+ int error_status);
#endif /* PAMMODUTIL_PRIVATE_H */
--
2.50.1