This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fresh bug in utmp functions


With recent glibcs, the xterm on SuSE Linux exits approximately 1 second after
showing the window. It is because of a bug: When the process does not have
write access to the utmp file, pututline() does nothing (obviously!) but
leaves an alarm timer enabled that triggers a SIGALRM signal and thus kills
the process one second later. The xterm on SuSE Linux is not setuid root
(it uses the utempter program to manipulate the utmp file) and therefore
the old code that the xterm child process executes to change the utmp file
kills this same process after it execs into a bash. Here is a fix.

Btw, wouldn't this utempter program be a good addition to glibc, like
pt_chown? It is tiny, and enables manipulation of utmp without need for
setuid root.


2002-09-29  Bruno Haible  <bruno@clisp.org>

	* sysdeps/generic/utmp_file.c (LOCKING_FAILED): New macro.
	(UNLOCK_FILE): Add a label.
	(getutent_r_file, internal_getut_r, getutline_r_file, pututline_file,
	updwtmp_file): Shut off the alarm clock when locking failed.

*** glibc-20020828/sysdeps/generic/utmp_file.c.bak	2002-08-26 15:49:59.000000000 +0200
--- glibc-20020828/sysdeps/generic/utmp_file.c	2002-09-29 02:37:34.000000000 +0200
***************
*** 46,51 ****
--- 46,60 ----
  /* Do-nothing handler for locking timeout.  */
  static void timeout_handler (int signum) {};
  
+ /* LOCK_FILE(fd, type) failure_statement
+      attempts to get a lock on the utmp file referenced by FD.  If it fails,
+      the failure_statement is executed, otherwise it is skipped.
+    LOCKING_FAILED()
+      jumps into the UNLOCK_FILE macro and ensures cleanup of LOCK_FILE.
+    UNLOCK_FILE(fd)
+      unlocks the utmp file referenced by FD and performs the cleanup of
+      LOCK_FILE.
+  */
  #define LOCK_FILE(fd, type) \
  {                                                                       \
    struct flock fl;                                                      \
***************
*** 69,79 ****
--- 78,92 ----
    fl.l_whence = SEEK_SET;                                               \
    if (__fcntl ((fd), F_SETLKW, &fl) < 0)
  
+ #define LOCKING_FAILED() \
+   goto unalarm_return
+ 
  #define UNLOCK_FILE(fd) \
    /* Unlock the file.  */                                               \
    fl.l_type = F_UNLCK;                                                  \
    __fcntl ((fd), F_SETLKW, &fl);                                        \
                                                                          \
+  unalarm_return:							\
    /* Reset the signal handler and alarm.  We must reset the alarm	\
       before resetting the handler so our alarm does not generate a	\
       spurious SIGALRM seen by the user.  However, we cannot just set	\
***************
*** 173,180 ****
  
    LOCK_FILE (file_fd, F_RDLCK)
      {
!       *result = NULL;
!       return -1;
      }
  
    /* Read the next entry.  */
--- 186,193 ----
  
    LOCK_FILE (file_fd, F_RDLCK)
      {
!       nbytes = 0;
!       LOCKING_FAILED ();
      }
  
    /* Read the next entry.  */
***************
*** 184,190 ****
  
    if (nbytes != sizeof (struct utmp))
      {
!       file_offset = -1l;
        *result = NULL;
        return -1;
      }
--- 197,204 ----
  
    if (nbytes != sizeof (struct utmp))
      {
!       if (nbytes != 0)
! 	file_offset = -1l;
        *result = NULL;
        return -1;
      }
***************
*** 232,238 ****
    int result = -1;
  
    LOCK_FILE (file_fd, F_RDLCK)
!     return result;
  
  #if _HAVE_UT_TYPE - 0
    if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
--- 246,252 ----
    int result = -1;
  
    LOCK_FILE (file_fd, F_RDLCK)
!     LOCKING_FAILED ();
  
  #if _HAVE_UT_TYPE - 0
    if (id->ut_type == RUN_LVL || id->ut_type == BOOT_TIME
***************
*** 333,339 ****
    LOCK_FILE (file_fd, F_RDLCK)
      {
        *result = NULL;
!       return -1;
      }
  
    while (1)
--- 347,353 ----
    LOCK_FILE (file_fd, F_RDLCK)
      {
        *result = NULL;
!       LOCKING_FAILED ();
      }
  
    while (1)
***************
*** 396,402 ****
      found = internal_getut_r (data, &buffer);
  
    LOCK_FILE (file_fd, F_WRLCK)
!     return NULL;
  
    if (found < 0)
      {
--- 410,419 ----
      found = internal_getut_r (data, &buffer);
  
    LOCK_FILE (file_fd, F_WRLCK)
!     {
!       pbuf = NULL;
!       LOCKING_FAILED ();
!     }
  
    if (found < 0)
      {
***************
*** 466,475 ****
      return -1;
  
    LOCK_FILE (fd, F_WRLCK)
!     {
!       __close (fd);
!       return result;
!     }
  
    /* Remember original size of log file.  */
    offset = __lseek64 (fd, 0, SEEK_END);
--- 483,489 ----
      return -1;
  
    LOCK_FILE (fd, F_WRLCK)
!     LOCKING_FAILED ();
  
    /* Remember original size of log file.  */
    offset = __lseek64 (fd, 0, SEEK_END);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]