This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug libc/6634] New: pututline_file() corrupts utmp file when internal_getut_r() returns -1 due to LOCK_FILE timeout.
- From: "rsa at us dot ibm dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sources dot redhat dot com
- Date: 11 Jun 2008 21:19:32 -0000
- Subject: [Bug libc/6634] New: pututline_file() corrupts utmp file when internal_getut_r() returns -1 due to LOCK_FILE timeout.
- Reply-to: sourceware-bugzilla at sourceware dot org
The 'pututline' utmp entry insertion function can corrupt
the utmp file with duplicate entries when the system is busy.
Root cause:
If the utmp entry already exists and the timeout for the lock (re:LOCK_FILE) in
internal_getur_r() expires internal_getur_r() returns -1 to pututline_file().
The pututline_file() function incorrectly interprets the -1 return value as
"entry not found" rather than "lock timed out" AND then incorrectly appends a
duplicate entry to the utmp file.
This can happen whenever there are simultaneous pututline executions and the
system is under a high enough load to cause the lock to time out.
The program logic needs to be repaired to assure that a lock timeout will never
cause a duplicate entry to be added.
Perhaps a backoff algorithm could be used to retry the lock or the lock timeout
could be increased as well to accommodate systems under greater stress.
The problem was identified on an x86 machine.
The macro (FILE_LOCK) expanded version of internal_getur_r follows:
internal_getut_r (const struct utmp *id, struct utmp *buffer)
{
int result = -1;
{
struct flock fl;
struct sigaction action, old_action;
unsigned int old_timeout;
old_timeout = alarm (0);
action.__sigaction_handler.sa_handler = timeout_handler;
(__builtin_memset (&action.sa_mask, '\0', sizeof (sigset_t)), 0);
action.sa_flags = 0;
__sigaction (14, &action, &old_action);
alarm (1);
memset (&fl, '\0', sizeof (struct flock));
fl.l_type = (0);
fl.l_whence = 0;
if (__fcntl_nocancel ((file_fd), 7, &fl) < 0)
goto unalarm_return;
if (id->ut_type == 1 || id->ut_type == 2
|| id->ut_type == 4 || id->ut_type == 3)
{
while (1)
{
if (__read_nocancel (file_fd, buffer, sizeof (struct utmp))
!= sizeof (struct utmp))
{
(__libc_errno = (3));
file_offset = -1l;
goto unlock_return;
}
file_offset += sizeof (struct utmp);
if (id->ut_type == buffer->ut_type)
break;
}
}
else
{
while (1)
{
if (__read_nocancel (file_fd, buffer, sizeof (struct utmp))
!= sizeof (struct utmp))
{
(__libc_errno = (3));
file_offset = -1l;
goto unlock_return;
}
file_offset += sizeof (struct utmp);
if (__utmp_equal (buffer, id))
break;
}
}
result = 0;
unlock_return:
fl.l_type = 2;
__fcntl_nocancel ((file_fd), 7, &fl);
unalarm_return:alarm (0);
__sigaction (14, &old_action, ((void *) 0));
if (old_timeout != 0)
alarm (old_timeout);
}
while (0);
return result;
}
--
Summary: pututline_file() corrupts utmp file when
internal_getut_r() returns -1 due to LOCK_FILE timeout.
Product: glibc
Version: unspecified
Status: NEW
Severity: normal
Priority: P2
Component: libc
AssignedTo: drepper at redhat dot com
ReportedBy: rsa at us dot ibm dot com
CC: glibc-bugs at sources dot redhat dot com,suzuki at in
dot ibm dot com
http://sourceware.org/bugzilla/show_bug.cgi?id=6634
------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.