|
|
8a8cfb |
commit 628598be7e1bfaa04f34df71ef6678f2c5103dfd
|
|
|
8a8cfb |
Author: Florian Weimer <fweimer@redhat.com>
|
|
|
8a8cfb |
Date: Thu Aug 15 16:09:05 2019 +0200
|
|
|
8a8cfb |
|
|
|
8a8cfb |
login: Disarm timer after utmp lock acquisition [BZ #24879]
|
|
|
8a8cfb |
|
|
|
8a8cfb |
If the file processing takes a long time for some reason, SIGALRM can
|
|
|
8a8cfb |
arrive while the file is still being processed. At that point, file
|
|
|
8a8cfb |
access will fail with EINTR. Disarming the timer after lock
|
|
|
8a8cfb |
acquisition avoids that. (If there was a previous alarm, it is the
|
|
|
8a8cfb |
responsibility of the caller to deal with the EINTR error.)
|
|
|
8a8cfb |
|
|
|
8a8cfb |
diff --git a/login/utmp_file.c b/login/utmp_file.c
|
|
|
8a8cfb |
index 8b6fee96b623fa90..a736d3d25e005920 100644
|
|
|
8a8cfb |
--- a/login/utmp_file.c
|
|
|
8a8cfb |
+++ b/login/utmp_file.c
|
|
|
8a8cfb |
@@ -55,32 +55,23 @@ static void timeout_handler (int signum) {};
|
|
|
8a8cfb |
|
|
|
8a8cfb |
/* try_file_lock (LOCKING, FD, TYPE) returns true if the locking
|
|
|
8a8cfb |
operation failed and recovery needs to be performed.
|
|
|
8a8cfb |
- (file_lock_restore (LOCKING) still needs to be called.)
|
|
|
8a8cfb |
|
|
|
8a8cfb |
file_unlock (FD) removes the lock (which must have been
|
|
|
8a8cfb |
- acquired).
|
|
|
8a8cfb |
-
|
|
|
8a8cfb |
- file_lock_restore (LOCKING) is needed to clean up in both
|
|
|
8a8cfb |
- cases. */
|
|
|
8a8cfb |
-
|
|
|
8a8cfb |
-struct file_locking
|
|
|
8a8cfb |
-{
|
|
|
8a8cfb |
- struct sigaction old_action;
|
|
|
8a8cfb |
- unsigned int old_timeout;
|
|
|
8a8cfb |
-};
|
|
|
8a8cfb |
+ successfully acquired). */
|
|
|
8a8cfb |
|
|
|
8a8cfb |
static bool
|
|
|
8a8cfb |
-try_file_lock (struct file_locking *locking, int fd, int type)
|
|
|
8a8cfb |
+try_file_lock (int fd, int type)
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
/* Cancel any existing alarm. */
|
|
|
8a8cfb |
- locking->old_timeout = alarm (0);
|
|
|
8a8cfb |
+ int old_timeout = alarm (0);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
/* Establish signal handler. */
|
|
|
8a8cfb |
+ struct sigaction old_action;
|
|
|
8a8cfb |
struct sigaction action;
|
|
|
8a8cfb |
action.sa_handler = timeout_handler;
|
|
|
8a8cfb |
__sigemptyset (&action.sa_mask);
|
|
|
8a8cfb |
action.sa_flags = 0;
|
|
|
8a8cfb |
- __sigaction (SIGALRM, &action, &locking->old_action);
|
|
|
8a8cfb |
+ __sigaction (SIGALRM, &action, &old_action);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
alarm (TIMEOUT);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
@@ -90,7 +81,23 @@ try_file_lock (struct file_locking *locking, int fd, int type)
|
|
|
8a8cfb |
.l_type = type,
|
|
|
8a8cfb |
fl.l_whence = SEEK_SET,
|
|
|
8a8cfb |
};
|
|
|
8a8cfb |
- return __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
|
|
|
8a8cfb |
+
|
|
|
8a8cfb |
+ bool status = __fcntl64_nocancel (fd, F_SETLKW, &fl) < 0;
|
|
|
8a8cfb |
+ int saved_errno = errno;
|
|
|
8a8cfb |
+
|
|
|
8a8cfb |
+ /* Reset the signal handler and alarm. We must reset the alarm
|
|
|
8a8cfb |
+ before resetting the handler so our alarm does not generate a
|
|
|
8a8cfb |
+ spurious SIGALRM seen by the user. However, we cannot just set
|
|
|
8a8cfb |
+ the user's old alarm before restoring the handler, because then
|
|
|
8a8cfb |
+ it's possible our handler could catch the user alarm's SIGARLM and
|
|
|
8a8cfb |
+ then the user would never see the signal he expected. */
|
|
|
8a8cfb |
+ alarm (0);
|
|
|
8a8cfb |
+ __sigaction (SIGALRM, &old_action, NULL);
|
|
|
8a8cfb |
+ if (old_timeout != 0)
|
|
|
8a8cfb |
+ alarm (old_timeout);
|
|
|
8a8cfb |
+
|
|
|
8a8cfb |
+ __set_errno (saved_errno);
|
|
|
8a8cfb |
+ return status;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
|
|
|
8a8cfb |
static void
|
|
|
8a8cfb |
@@ -103,21 +110,6 @@ file_unlock (int fd)
|
|
|
8a8cfb |
__fcntl64_nocancel (fd, F_SETLKW, &fl);
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
|
|
|
8a8cfb |
-static void
|
|
|
8a8cfb |
-file_lock_restore (struct file_locking *locking)
|
|
|
8a8cfb |
-{
|
|
|
8a8cfb |
- /* Reset the signal handler and alarm. We must reset the alarm
|
|
|
8a8cfb |
- before resetting the handler so our alarm does not generate a
|
|
|
8a8cfb |
- spurious SIGALRM seen by the user. However, we cannot just set
|
|
|
8a8cfb |
- the user's old alarm before restoring the handler, because then
|
|
|
8a8cfb |
- it's possible our handler could catch the user alarm's SIGARLM
|
|
|
8a8cfb |
- and then the user would never see the signal he expected. */
|
|
|
8a8cfb |
- alarm (0);
|
|
|
8a8cfb |
- __sigaction (SIGALRM, &locking->old_action, NULL);
|
|
|
8a8cfb |
- if (locking->old_timeout != 0)
|
|
|
8a8cfb |
- alarm (locking->old_timeout);
|
|
|
8a8cfb |
-}
|
|
|
8a8cfb |
-
|
|
|
8a8cfb |
#ifndef TRANSFORM_UTMP_FILE_NAME
|
|
|
8a8cfb |
# define TRANSFORM_UTMP_FILE_NAME(file_name) (file_name)
|
|
|
8a8cfb |
#endif
|
|
|
8a8cfb |
@@ -166,8 +158,7 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
|
|
8a8cfb |
return -1;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
|
|
|
8a8cfb |
- struct file_locking fl;
|
|
|
8a8cfb |
- if (try_file_lock (&fl, file_fd, F_RDLCK))
|
|
|
8a8cfb |
+ if (try_file_lock (file_fd, F_RDLCK))
|
|
|
8a8cfb |
nbytes = 0;
|
|
|
8a8cfb |
else
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
@@ -175,7 +166,6 @@ __libc_getutent_r (struct utmp *buffer, struct utmp **result)
|
|
|
8a8cfb |
nbytes = __read_nocancel (file_fd, &last_entry, sizeof (struct utmp));
|
|
|
8a8cfb |
file_unlock (file_fd);
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
if (nbytes != sizeof (struct utmp))
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
@@ -201,11 +191,9 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
int result = -1;
|
|
|
8a8cfb |
|
|
|
8a8cfb |
- struct file_locking fl;
|
|
|
8a8cfb |
- if (try_file_lock (&fl, file_fd, F_RDLCK))
|
|
|
8a8cfb |
+ if (try_file_lock (file_fd, F_RDLCK))
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
*lock_failed = true;
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
return -1;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
|
|
|
8a8cfb |
@@ -257,7 +245,6 @@ internal_getut_r (const struct utmp *id, struct utmp *buffer,
|
|
|
8a8cfb |
|
|
|
8a8cfb |
unlock_return:
|
|
|
8a8cfb |
file_unlock (file_fd);
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
return result;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
@@ -303,11 +290,9 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
|
|
8a8cfb |
return -1;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
|
|
|
8a8cfb |
- struct file_locking fl;
|
|
|
8a8cfb |
- if (try_file_lock (&fl, file_fd, F_RDLCK))
|
|
|
8a8cfb |
+ if (try_file_lock (file_fd, F_RDLCK))
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
*result = NULL;
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
return -1;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
|
|
|
8a8cfb |
@@ -337,7 +322,6 @@ __libc_getutline_r (const struct utmp *line, struct utmp *buffer,
|
|
|
8a8cfb |
|
|
|
8a8cfb |
unlock_return:
|
|
|
8a8cfb |
file_unlock (file_fd);
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
return ((*result == NULL) ? -1 : 0);
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
@@ -394,12 +378,8 @@ __libc_pututline (const struct utmp *data)
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
|
|
|
8a8cfb |
- struct file_locking fl;
|
|
|
8a8cfb |
- if (try_file_lock (&fl, file_fd, F_WRLCK))
|
|
|
8a8cfb |
- {
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
- return NULL;
|
|
|
8a8cfb |
- }
|
|
|
8a8cfb |
+ if (try_file_lock (file_fd, F_WRLCK))
|
|
|
8a8cfb |
+ return NULL;
|
|
|
8a8cfb |
|
|
|
8a8cfb |
if (found < 0)
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
@@ -442,7 +422,6 @@ __libc_pututline (const struct utmp *data)
|
|
|
8a8cfb |
|
|
|
8a8cfb |
unlock_return:
|
|
|
8a8cfb |
file_unlock (file_fd);
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
return pbuf;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
@@ -471,10 +450,8 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
|
|
|
8a8cfb |
if (fd < 0)
|
|
|
8a8cfb |
return -1;
|
|
|
8a8cfb |
|
|
|
8a8cfb |
- struct file_locking fl;
|
|
|
8a8cfb |
- if (try_file_lock (&fl, fd, F_WRLCK))
|
|
|
8a8cfb |
+ if (try_file_lock (fd, F_WRLCK))
|
|
|
8a8cfb |
{
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
__close_nocancel_nostatus (fd);
|
|
|
8a8cfb |
return -1;
|
|
|
8a8cfb |
}
|
|
|
8a8cfb |
@@ -504,7 +481,6 @@ __libc_updwtmp (const char *file, const struct utmp *utmp)
|
|
|
8a8cfb |
|
|
|
8a8cfb |
unlock_return:
|
|
|
8a8cfb |
file_unlock (fd);
|
|
|
8a8cfb |
- file_lock_restore (&fl);
|
|
|
8a8cfb |
|
|
|
8a8cfb |
/* Close WTMP file. */
|
|
|
8a8cfb |
__close_nocancel_nostatus (fd);
|