diff options
author | Matt Cowell <matt.cowell@nokia.com> | 2019-08-29 16:36:35 -0500 |
---|---|---|
committer | Tomáš Mráz <t8m@users.noreply.github.com> | 2019-09-02 11:28:31 +0200 |
commit | 9de67eee2cf8c3024f7bee7393ea762ac7bd09ab (patch) | |
tree | 442ba3e354bdb3bf070fc74908dd4262d48e0845 /modules/pam_pwhistory/opasswd.c | |
parent | 1b087edc7f05237bf5eccc405704cd82b848e761 (diff) | |
download | pam-9de67eee2cf8c3024f7bee7393ea762ac7bd09ab.tar.gz pam-9de67eee2cf8c3024f7bee7393ea762ac7bd09ab.tar.bz2 pam-9de67eee2cf8c3024f7bee7393ea762ac7bd09ab.zip |
pwhistory: fix read of uninitialized data and memory leak when modifying opasswd
The glibc implementation of getline/getdelim does not guarantee a NUL
terminator in lineptr if getline returns failure (-1). This occurs when
the opasswd file exists but is empty. Since strdup is called
immediately afterwards, this causes strdup to read uninitialized memory
and possibly buffer overrun / crash.
This also fixes a memory leak which always occurs when reading the last
line of the opasswd file. Since the strdup is called before checking
the return code from getline, getdelim, or fgets+strlen, it will
duplicate and never free either:
- The last successfully read line (for getline or getdelim)
- Uninitialized data (if the file is empty)
- A 0 byte string (for fgets+strlen)
Fix by always checking the return code of getline, getdelim, or
fgets+strlen before calling strdup.
Diffstat (limited to 'modules/pam_pwhistory/opasswd.c')
-rw-r--r-- | modules/pam_pwhistory/opasswd.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/modules/pam_pwhistory/opasswd.c b/modules/pam_pwhistory/opasswd.c index e6cf3469..813f579c 100644 --- a/modules/pam_pwhistory/opasswd.c +++ b/modules/pam_pwhistory/opasswd.c @@ -326,6 +326,9 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid, n = strlen (buf); #endif /* HAVE_GETLINE / HAVE_GETDELIM */ + if (n < 1) + break; + cp = buf; save = strdup (buf); /* Copy to write the original data back. */ if (save == NULL) @@ -336,9 +339,6 @@ save_old_pass (pam_handle_t *pamh, const char *user, uid_t uid, goto error_opasswd; } - if (n < 1) - break; - tmp = strchr (cp, '#'); /* remove comments */ if (tmp) *tmp = '\0'; |