2008-12-13 Klaus Dittrich <kladit@arcor.de> * login/utmp_file.c (pututline_file): Replace call to dup2 with libc internal symbol __dup2 to avoid access through the PLT. 2008-11-29 Ulrich Drepper <drepper@redhat.com> * login/utmp_file.c (file_writable): New variable. (setutent_file): Don't try to open file for writing. (pututline_file): Before writing, make descriptor writable if necessary. --- libc/login/utmp_file.c 14 Aug 2008 04:22:59 -0000 1.22 +++ libc/login/utmp_file.c 23 Dec 2008 16:49:43 -0000 1.24 @@ -34,6 +34,7 @@ /* Descriptor for the file and position. */ static int file_fd = -1; +static bool file_writable; static off64_t file_offset; /* Cache for the last read entry. */ @@ -136,21 +137,16 @@ setutent_file (void) if (file_fd < 0) { const char *file_name; - int result; file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); - file_fd = open_not_cancel_2 (file_name, O_RDWR | O_LARGEFILE); + file_writable = false; + file_fd = open_not_cancel_2 (file_name, O_RDONLY | O_LARGEFILE); if (file_fd == -1) - { - /* Hhm, read-write access did not work. Try read-only. */ - file_fd = open_not_cancel_2 (file_name, O_RDONLY | O_LARGEFILE); - if (file_fd == -1) - return 0; - } + return 0; /* We have to make sure the file is `closed on exec'. */ - result = fcntl_not_cancel (file_fd, F_GETFD, 0); + int result = fcntl_not_cancel (file_fd, F_GETFD, 0); if (result >= 0) result = fcntl_not_cancel (file_fd, F_SETFD, result | FD_CLOEXEC); if (result == -1) @@ -373,6 +369,36 @@ pututline_file (const struct utmp *data) assert (file_fd >= 0); + if (! file_writable) + { + /* We must make the file descriptor writable before going on. */ + const char *file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); + + int new_fd = open_not_cancel_2 (file_name, O_RDWR | O_LARGEFILE); + if (new_fd == -1) + return NULL; + + /* We have to make sure the file is `closed on exec'. */ + int result = fcntl_not_cancel (file_fd, F_GETFD, 0); + if (result >= 0) + result = fcntl_not_cancel (file_fd, F_SETFD, result | FD_CLOEXEC); + + if (result == -1) + { + close_not_cancel_no_status (file_fd); + return NULL; + } + + if (__lseek64 (new_fd, __lseek64 (file_fd, 0, SEEK_CUR), SEEK_SET) == -1 + || __dup2 (new_fd, file_fd) < 0) + { + close_not_cancel_no_status (new_fd); + return NULL; + } + close_not_cancel_no_status (new_fd); + file_writable = true; + } + /* Find the correct place to insert the data. */ if (file_offset > 0 && (