OSDN Git Service

rholzmann writes in Bug 716:
authorMike Frysinger <vapier@gentoo.org>
Sat, 11 Feb 2006 05:36:43 +0000 (05:36 -0000)
committerMike Frysinger <vapier@gentoo.org>
Sat, 11 Feb 2006 05:36:43 +0000 (05:36 -0000)
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

index b865cc2..9455717 100644 (file)
@@ -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;