This is the mail archive of the
libc-alpha@sources.redhat.com
mailing list for the glibc project.
useless file accesses (2)
- To: libc-alpha at sourceware dot cygnus dot com
- Subject: useless file accesses (2)
- From: Bruno Haible <haible at ilog dot fr>
- Date: Mon, 7 Aug 2000 14:13:59 +0200 (CEST)
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. */