We got a customer report of a command going through PAM crashing for a given user.
It appears that the pam_lastlog code doesn't check the result of localtime_r(), which leads to crashing in glibc's strftime():
~~~
494 static int
495 last_login_failed(pam_handle_t *pamh, int announce, const char *user, time_t lltime)
496 {
:
502 char the_time[256];
:
535 if (failed) {
536 /* we want the date? */
537 if (announce & LASTLOG_DATE) {
538 struct tm *tm, tm_buf;
539 time_t lf_time;
540
541 lf_time = utuser.ut_tv.tv_sec;
542 tm = localtime_r (&lf_time, &tm_buf);
543 strftime (the_time, sizeof (the_time),
544 /* TRANSLATORS: "strftime options for date of last login" */
545 _(" %a %b %e %H:%M:%S %Z %Y"), tm);
546
547 date = the_time;
548 }
~~~
Here above, assuming "lf_time" is very large, due to a corruption in btmp database, this leads to:
1. having "tm" = NULL
2. calling strftime(..., NULL), which crashes
Hence, checking the result is mandatory.
Version-Release number of selected component (if applicable):
Description of problem:
We got a customer report of a command going through PAM crashing for a given user.
It appears that the pam_lastlog code doesn't check the result of localtime_r(), which leads to crashing in glibc's strftime():
~~~ failed( pam_handle_ t *pamh, int announce, const char *user, time_t lltime) ut_tv.tv_ sec;
494 static int
495 last_login_
496 {
:
502 char the_time[256];
:
535 if (failed) {
536 /* we want the date? */
537 if (announce & LASTLOG_DATE) {
538 struct tm *tm, tm_buf;
539 time_t lf_time;
540
541 lf_time = utuser.
542 tm = localtime_r (&lf_time, &tm_buf);
543 strftime (the_time, sizeof (the_time),
544 /* TRANSLATORS: "strftime options for date of last login" */
545 _(" %a %b %e %H:%M:%S %Z %Y"), tm);
546
547 date = the_time;
548 }
~~~
Here above, assuming "lf_time" is very large, due to a corruption in btmp database, this leads to:
1. having "tm" = NULL
2. calling strftime(..., NULL), which crashes
Hence, checking the result is mandatory.
Version-Release number of selected component (if applicable):
PAM from RHEL7 and later
How reproducible:
Don't know, need to have a corrupted "btmp" entry