diff options
-rw-r--r-- | modules/pam_lastlog/pam_lastlog.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/modules/pam_lastlog/pam_lastlog.c b/modules/pam_lastlog/pam_lastlog.c index 121e7560..797a61ce 100644 --- a/modules/pam_lastlog/pam_lastlog.c +++ b/modules/pam_lastlog/pam_lastlog.c @@ -57,14 +57,13 @@ struct lastlog { # define PATH_LOGIN_DEFS "/etc/login.defs" #endif -/* XXX - time before ignoring lock. Is 1 sec enough? */ -#define LASTLOG_IGNORE_LOCK_TIME 1 - #define DEFAULT_HOST "" /* "[no.where]" */ #define DEFAULT_TERM "" /* "tt???" */ #define DEFAULT_INACTIVE_DAYS 90 #define MAX_INACTIVE_DAYS 100000 +#define LOCK_RETRIES 3 /* number of file lock retries */ +#define LOCK_RETRY_DELAY 1 /* seconds to wait between lock attempts */ #include <security/pam_modules.h> #include <security/_pam_macros.h> @@ -266,6 +265,7 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t { struct flock last_lock; struct lastlog last_login; + int lock_retries = LOCK_RETRIES; int retval = PAM_SUCCESS; char the_time[256]; char *date = NULL; @@ -278,11 +278,19 @@ last_login_read(pam_handle_t *pamh, int announce, int last_fd, uid_t uid, time_t last_lock.l_start = sizeof(last_login) * (off_t) uid; last_lock.l_len = sizeof(last_login); - if (fcntl(last_fd, F_SETLK, &last_lock) < 0) { + while (fcntl(last_fd, F_SETLK, &last_lock) < 0) { + if (0 == --lock_retries) { + /* read lock failed, proceed anyway to avoid possible DoS */ + D(("locking %s failed", _PATH_LASTLOG)); + pam_syslog(pamh, LOG_INFO, + "file %s is locked/read, proceeding anyway", + _PATH_LASTLOG); + break; + } D(("locking %s failed..(waiting a little)", _PATH_LASTLOG)); - pam_syslog(pamh, LOG_WARNING, - "file %s is locked/read", _PATH_LASTLOG); - sleep(LASTLOG_IGNORE_LOCK_TIME); + pam_syslog(pamh, LOG_INFO, + "file %s is locked/read, retrying", _PATH_LASTLOG); + sleep(LOCK_RETRY_DELAY); } if (pam_modutil_read(last_fd, (char *) &last_login, @@ -380,6 +388,7 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd, int setrlimit_res; struct flock last_lock; struct lastlog last_login; + int lock_retries = LOCK_RETRIES; time_t ll_time; const void *void_remote_host = NULL; const char *remote_host; @@ -426,10 +435,17 @@ last_login_write(pam_handle_t *pamh, int announce, int last_fd, last_lock.l_start = sizeof(last_login) * (off_t) uid; last_lock.l_len = sizeof(last_login); - if (fcntl(last_fd, F_SETLK, &last_lock) < 0) { + while (fcntl(last_fd, F_SETLK, &last_lock) < 0) { + if (0 == --lock_retries) { + D(("locking %s failed", _PATH_LASTLOG)); + pam_syslog(pamh, LOG_ERR, + "file %s is locked/write", _PATH_LASTLOG); + return PAM_SERVICE_ERR; + } D(("locking %s failed..(waiting a little)", _PATH_LASTLOG)); - pam_syslog(pamh, LOG_WARNING, "file %s is locked/write", _PATH_LASTLOG); - sleep(LASTLOG_IGNORE_LOCK_TIME); + pam_syslog(pamh, LOG_INFO, + "file %s is locked/write, retrying", _PATH_LASTLOG); + sleep(LOCK_RETRY_DELAY); } /* |