From da738bcee47f9e2423bcc66f379e0c5e44c62b78 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Sat, 11 Feb 2006 05:36:43 +0000 Subject: 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. --- libc/misc/utmp/utent.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'libc/misc/utmp/utent.c') 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; -- cgit v1.2.3