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]

useless file accesses (2)



When gettext is called the first time and needs to convert its message,
strace shows a few unnecessary calls

  lstat("/glibc22", {st_mode=S_IFLNK|0777, st_size=16, ...}) = 0
  readlink("/glibc22", "packages/glibc22", 4095) = 16
  lstat("/packages", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
  lstat("/packages/glibc22", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  lstat("/packages/glibc22/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  lstat("/packages/glibc22/lib/gconv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  open("/packages/glibc22/lib/gconv/gconv-modules", O_RDONLY) = 0

coming from a "realpath" call in iconv/gconv_conf.c. This realpath call is

1. buggy, as demonstrated by the introduction of a long symlink, leading
   to a core dump:

  lstat("/glibc22", {st_mode=S_IFLNK|0777, st_size=16, ...}) = 0
  readlink("/glibc22", "packages/glibc22", 4095) = 16
  lstat("/packages", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
  lstat("/packages/glibc22", {st_mode=S_IFLNK|0777, st_size=128, ...}) = 0
  readlink("/packages/glibc22", "a_very_long_filename_for_glibc22_to_demonstrate_a_buffer_overrun_in_the_result_of_realpath_as_called_by__gconv_read_conf/glibc22", 4095) = 128
  lstat("/packages/a_very_long_filename_for_glibc22_to_demonstrate_a_buffer_overrun_in_the_result_of_realpath_as_called_by__gconv_read_conf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  lstat("/packages/a_very_long_filename_for_glibc22_to_demonstrate_a_buffer_overrun_in_the_result_of_realpath_as_called_by__gconv_read_conf/glibc22", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  lstat("/packages/a_very_long_filename_for_glibc22_to_demonstrate_a_buffer_overrun_in_the_result_of_realpath_as_called_by__gconv_read_conf/glibc22/lib", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  lstat("/packages/a_very_long_filename_for_glibc22_to_demonstrate_a_buffer_overrun_in_the_result_of_realpath_as_called_by__gconv_read_conf/glibc22/lib/gconv", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
  --- SIGSEGV (Speicherzugriffsfehler) ---
  +++ killed by SIGSEGV +++

2. useless, because the realpath result doesn't matter. You won't help the kernel
   a lot by using resolved pathnames, because /usr/lib/gconv is not a symlink
   normally and because few modules will be looked up in this directory.

The intended test was probably a stat && S_ISDIR test, but even this
one is not necessary because the first action of read_conf_file is to open a
file in this directory and return silently if it doesn't exist.


2000-08-06  Bruno Haible  <haible@clisp.cons.org>

	* iconv/gconv_conf.c (__gconv_read_conf): Don't call realpath.

*** glibc-20000729/iconv/gconv_conf.c.bak	Wed Jul 12 18:11:43 2000
--- glibc-20000729/iconv/gconv_conf.c	Sun Aug  6 20:57:44 2000
***************
*** 36,44 ****
  /* This is the default path where we look for module lists.  */
  static const char default_gconv_path[] = GCONV_PATH;
  
! /* The path element in use.   */
  const struct path_elem *__gconv_path_elem;
! /* Maximum length of a single path element.  */
  size_t __gconv_max_path_elem_len;
  
  /* We use the following struct if we couldn't allocate memory.  */
--- 36,45 ----
  /* This is the default path where we look for module lists.  */
  static const char default_gconv_path[] = GCONV_PATH;
  
! /* The path elements, as determined by the __gconv_get_path function.
!    All path elements end in a slash.  */
  const struct path_elem *__gconv_path_elem;
! /* Maximum length of a single path element in __gconv_path_elem.  */
  size_t __gconv_max_path_elem_len;
  
  /* We use the following struct if we couldn't allocate memory.  */
***************
*** 507,527 ****
  
    for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
      {
!       char real_elem[__gconv_max_path_elem_len + sizeof (gconv_conf_filename)];
  
!       if (__realpath (__gconv_path_elem[cnt].name, real_elem) != NULL)
! 	{
! 	  size_t elem_len = strlen (real_elem);
! 	  char *filename;
! 
! 	  filename = alloca (elem_len + 1 + sizeof (gconv_conf_filename));
! 	  __mempcpy (__mempcpy (__mempcpy (filename, real_elem, elem_len),
! 				"/", 1),
! 		     gconv_conf_filename, sizeof (gconv_conf_filename));
! 
! 	  /* Read the next configuration file.  */
! 	  read_conf_file (filename, real_elem, elem_len, &modules, &nmodules);
! 	}
      }
  
    /* Add the internal modules.  */
--- 508,525 ----
  
    for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
      {
!       const char *elem = __gconv_path_elem[cnt].name;
!       size_t elem_len = __gconv_path_elem[cnt].len;
!       char *filename;
! 
!       /* No slash needs to be inserted between elem and gconv_conf_filename;
! 	 elem already ends in a slash.  */
!       filename = alloca (elem_len + sizeof (gconv_conf_filename));
!       __mempcpy (__mempcpy (filename, elem, elem_len),
! 		 gconv_conf_filename, sizeof (gconv_conf_filename));
  
!       /* Read the next configuration file.  */
!       read_conf_file (filename, elem, elem_len, &modules, &nmodules);
      }
  
    /* Add the internal modules.  */

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