diff options
author | Mike Frysinger <vapier@gentoo.org> | 2006-02-11 05:36:43 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2006-02-11 05:36:43 +0000 |
commit | da738bcee47f9e2423bcc66f379e0c5e44c62b78 (patch) | |
tree | 9c45712bea37152fda4a2e7311fd937c67027657 /libc/misc/utmp/utent.c | |
parent | 10e7c9d7d64922a211cf9ea81405e187112a0ad5 (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.
Diffstat (limited to 'libc/misc/utmp/utent.c')
-rw-r--r-- | libc/misc/utmp/utent.c | 25 |
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; |