summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2006-02-11 05:36:43 +0000
committerMike Frysinger <vapier@gentoo.org>2006-02-11 05:36:43 +0000
commitda738bcee47f9e2423bcc66f379e0c5e44c62b78 (patch)
tree9c45712bea37152fda4a2e7311fd937c67027657
parent10e7c9d7d64922a211cf9ea81405e187112a0ad5 (diff)
rholzmann writes in Bug 716:
utent.c has a few problems with mutex locking when used in a binary that was linked with pthreads. The are a few deadlock conditions where functions may be called which lock the utmplock but never release it and where a function that hold the lock calls other functions which try to relock the same lock. For example, notice in the __getutent function the error condition does not unlock the semaphore. The problem is not visible when pthreads isn't used since the lock/unlock functions are NOOP functions.
-rw-r--r--libc/misc/utmp/utent.c25
1 files changed, 12 insertions, 13 deletions
diff --git a/libc/misc/utmp/utent.c b/libc/misc/utmp/utent.c
index b865cc271..945571733 100644
--- a/libc/misc/utmp/utent.c
+++ b/libc/misc/utmp/utent.c
@@ -64,20 +64,22 @@ void setutent(void)
}
if (ret < 0) {
bummer:
- UNLOCK;
static_fd = -1;
close(static_fd);
+unlock_and_ret:
+ UNLOCK;
return;
}
}
lseek(static_fd, 0, SEEK_SET);
- UNLOCK;
- return;
+ goto unlock_and_ret;
}
libc_hidden_def(setutent)
static struct utmp *__getutent(int utmp_fd)
{
+ struct utmp *ret = NULL;
+
if (utmp_fd == -1) {
setutent();
}
@@ -86,13 +88,13 @@ static struct utmp *__getutent(int utmp_fd)
}
LOCK;
- if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) != sizeof(struct utmp))
+ if (read(utmp_fd, (char *) &static_utmp, sizeof(struct utmp)) == sizeof(struct utmp))
{
- return NULL;
+ ret = &static_utmp;
}
UNLOCK;
- return &static_utmp;
+ return ret;
}
void endutent(void)
@@ -163,15 +165,12 @@ struct utmp *pututline (const struct utmp *utmp_entry)
the file pointer where they want it, everything will work out. */
lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
- if (getutid(utmp_entry) != NULL) {
+ if (getutid(utmp_entry) != NULL)
lseek(static_fd, (off_t) - sizeof(struct utmp), SEEK_CUR);
- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
- return NULL;
- } else {
+ else
lseek(static_fd, (off_t) 0, SEEK_END);
- if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
- return NULL;
- }
+ if (write(static_fd, utmp_entry, sizeof(struct utmp)) != sizeof(struct utmp))
+ utmp_entry = NULL;
UNLOCK;
return (struct utmp *)utmp_entry;