This file contains fixes from the "release/2.28/master" branch: https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/release/2.28/master Currently we have these commits (sans tests and ChangeLog updates): 7f11842e7483da7aa9fa3031be122021978ef600 726e1554ce4db5e35af41cb0110c54c5e1232054 4b25485f03158959cff45379eecc1d73c7dcdd11 d05b05d1570ba3ae354a2f5a3cfeefb373b09979 bfcfa22589f2b4277a65e60c6b736b6bbfbd87d0 2f498f3d140ab5152bd784df2be7af7d9c5e63ed diff --git a/htl/Versions b/htl/Versions index 6a63a1b8a1..c5a616da10 100644 --- a/htl/Versions +++ b/htl/Versions @@ -150,6 +150,8 @@ libpthread { __cthread_keycreate; __cthread_getspecific; __cthread_setspecific; + __pthread_getspecific; + __pthread_setspecific; __pthread_getattr_np; __pthread_attr_getstack; } diff --git a/sysdeps/htl/pt-getspecific.c b/sysdeps/htl/pt-getspecific.c index a0227a67f6..64ddf9551a 100644 --- a/sysdeps/htl/pt-getspecific.c +++ b/sysdeps/htl/pt-getspecific.c @@ -36,3 +36,4 @@ __pthread_getspecific (pthread_key_t key) return self->thread_specifics[key]; } strong_alias (__pthread_getspecific, pthread_getspecific); +hidden_def (__pthread_getspecific) diff --git a/sysdeps/htl/pt-setspecific.c b/sysdeps/htl/pt-setspecific.c index a46a12f157..02aff417ef 100644 --- a/sysdeps/htl/pt-setspecific.c +++ b/sysdeps/htl/pt-setspecific.c @@ -48,3 +48,4 @@ __pthread_setspecific (pthread_key_t key, const void *value) return 0; } strong_alias (__pthread_setspecific, pthread_setspecific); +hidden_def (__pthread_setspecific) diff --git a/sysdeps/htl/pthreadP.h b/sysdeps/htl/pthreadP.h index 132ac1718e..71c2fcd9c6 100644 --- a/sysdeps/htl/pthreadP.h +++ b/sysdeps/htl/pthreadP.h @@ -68,6 +68,8 @@ struct __pthread_cancelation_handler **___pthread_get_cleanup_stack (void) attri #if IS_IN (libpthread) hidden_proto (__pthread_key_create) +hidden_proto (__pthread_getspecific) +hidden_proto (__pthread_setspecific) hidden_proto (_pthread_mutex_init) #endif diff --git a/sysdeps/unix/sysv/linux/getdents64.c b/sysdeps/unix/sysv/linux/getdents64.c index 3bde0cf4f0..bc140b5a7f 100644 --- a/sysdeps/unix/sysv/linux/getdents64.c +++ b/sysdeps/unix/sysv/linux/getdents64.c @@ -33,41 +33,80 @@ strong_alias (__getdents64, __getdents) # include # if SHLIB_COMPAT(libc, GLIBC_2_1, GLIBC_2_2) -# include +# include +# include -/* kernel definition of as of 3.2. */ -struct compat_linux_dirent +static ssize_t +handle_overflow (int fd, __off64_t offset, ssize_t count) { - /* Both d_ino and d_off are compat_ulong_t which are defined in all - architectures as 'u32'. */ - uint32_t d_ino; - uint32_t d_off; - unsigned short d_reclen; - char d_name[1]; -}; + /* If this is the first entry in the buffer, we can report the + error. */ + if (count == 0) + { + __set_errno (EOVERFLOW); + return -1; + } + + /* Otherwise, seek to the overflowing entry, so that the next call + will report the error, and return the data read so far.. */ + if (__lseek64 (fd, offset, SEEK_SET) != 0) + return -1; + return count; +} ssize_t __old_getdents64 (int fd, char *buf, size_t nbytes) { - ssize_t retval = INLINE_SYSCALL_CALL (getdents, fd, buf, nbytes); + /* We do not move the individual directory entries. This is only + possible if the target type (struct __old_dirent64) is smaller + than the source type. */ + _Static_assert (offsetof (struct __old_dirent64, d_name) + <= offsetof (struct dirent64, d_name), + "__old_dirent64 is larger than dirent64"); + _Static_assert (__alignof__ (struct __old_dirent64) + <= __alignof__ (struct dirent64), + "alignment of __old_dirent64 is larger than dirent64"); - /* The kernel added the d_type value after the name. Change this now. */ - if (retval != -1) + ssize_t retval = INLINE_SYSCALL_CALL (getdents64, fd, buf, nbytes); + if (retval > 0) { - union - { - struct compat_linux_dirent k; - struct dirent u; - } *kbuf = (void *) buf; - - while ((char *) kbuf < buf + retval) + char *p = buf; + char *end = buf + retval; + while (p < end) { - char d_type = *((char *) kbuf + kbuf->k.d_reclen - 1); - memmove (kbuf->u.d_name, kbuf->k.d_name, - strlen (kbuf->k.d_name) + 1); - kbuf->u.d_type = d_type; + struct dirent64 *source = (struct dirent64 *) p; + + /* Copy out the fixed-size data. */ + __ino_t ino = source->d_ino; + __off64_t offset = source->d_off; + unsigned int reclen = source->d_reclen; + unsigned char type = source->d_type; + + /* Check for ino_t overflow. */ + if (__glibc_unlikely (ino != source->d_ino)) + return handle_overflow (fd, offset, p - buf); + + /* Convert to the target layout. Use a separate struct and + memcpy to side-step aliasing issues. */ + struct __old_dirent64 result; + result.d_ino = ino; + result.d_off = offset; + result.d_reclen = reclen; + result.d_type = type; + + /* Write the fixed-sized part of the result to the + buffer. */ + size_t result_name_offset = offsetof (struct __old_dirent64, d_name); + memcpy (p, &result, result_name_offset); + + /* Adjust the position of the name if necessary. Copy + everything until the end of the record, including the + terminating NUL byte. */ + if (result_name_offset != offsetof (struct dirent64, d_name)) + memmove (p + result_name_offset, source->d_name, + reclen - offsetof (struct dirent64, d_name)); - kbuf = (void *) ((char *) kbuf + kbuf->k.d_reclen); + p += reclen; } } return retval; diff --git a/misc/error.c b/misc/error.c index b4e8b6c938..03378e2f2a 100644 --- a/misc/error.c +++ b/misc/error.c @@ -319,6 +319,7 @@ error (int status, int errnum, const char *message, ...) va_start (args, message); error_tail (status, errnum, message, args); + va_end (args); #ifdef _LIBC _IO_funlockfile (stderr); @@ -390,6 +391,7 @@ error_at_line (int status, int errnum, const char *file_name, va_start (args, message); error_tail (status, errnum, message, args); + va_end (args); #ifdef _LIBC _IO_funlockfile (stderr); diff --git a/nscd/nscd_conf.c b/nscd/nscd_conf.c index 265a02434d..7293b795b6 100644 --- a/nscd/nscd_conf.c +++ b/nscd/nscd_conf.c @@ -190,7 +190,10 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) if (!arg1) error (0, 0, _("Must specify user name for server-user option")); else - server_user = xstrdup (arg1); + { + free ((char *) server_user); + server_user = xstrdup (arg1); + } } else if (strcmp (entry, "stat-user") == 0) { @@ -198,6 +201,7 @@ nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb]) error (0, 0, _("Must specify user name for stat-user option")); else { + free ((char *) stat_user); stat_user = xstrdup (arg1); struct passwd *pw = getpwnam (stat_user); diff --git a/nss/nss_files/files-alias.c b/nss/nss_files/files-alias.c index cfd34b66b9..35b0bfc5d2 100644 --- a/nss/nss_files/files-alias.c +++ b/nss/nss_files/files-alias.c @@ -221,6 +221,13 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, { while (! feof_unlocked (listfile)) { + if (room_left < 2) + { + free (old_line); + fclose (listfile); + goto no_more_room; + } + first_unused[room_left - 1] = '\xff'; line = fgets_unlocked (first_unused, room_left, listfile); @@ -229,6 +236,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, if (first_unused[room_left - 1] != '\xff') { free (old_line); + fclose (listfile); goto no_more_room; } @@ -256,6 +264,7 @@ get_next_alias (FILE *stream, const char *match, struct aliasent *result, + __alignof__ (char *))) { free (old_line); + fclose (listfile); goto no_more_room; } room_left -= ((first_unused - cp)