Bug 29583 - iconv failures on 32bit platform due to missing large file support
Summary: iconv failures on 32bit platform due to missing large file support
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: build (show other bugs)
Version: 2.38
: P2 normal
Target Milestone: 2.37
Assignee: Florian Weimer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-09-18 16:53 UTC by Helge Deller
Modified: 2022-09-21 12:13 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed: 2022-09-19 00:00:00
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Helge Deller 2022-09-18 16:53:10 UTC
While compiling glibc in a 32-bit environment (hppa architecture, 32-bit userspace, but 64-bit kernel, glibc target is 32-bit as well) I see lots of failures with iconv like this one:

/build/glibc/glibc-2.34/build-tree/hppa-libc/iconv/iconv_prog: failed to start conversion processing

I traced it with strace:
3438821 openat(AT_FDCWD,"/build/glibc/glibc-2.34/build-tree/hppa-libc/iconvdata/gconv-modules",O_RDONLY|O_CLOEXEC) = 3
3438821 statx(3,"",AT_EMPTY_PATH|AT_NO_AUTOMOUNT,STATX_BASIC_STATS,0xf50013c8) = 0
3438821 read(3,0xfa034678,4096) = 3808
3438821 read(3,0xfa034678,4096) = 0
3438821 close(3) = 0
3438821 openat(AT_FDCWD,"/build/glibc/glibc-2.34/build-tree/hppa-libc/iconvdata/gconv-modules.d",O_RDONLY|O_DIRECTORY|O_LARGEFILE|O_NONBLOCK|O_CLOEXEC) = 3
3438821 statx(3,"",AT_EMPTY_PATH|AT_NO_AUTOMOUNT,STATX_BASIC_STATS,0xf5001148) = 0
3438821 getdents64(3,-100439584,32768,99,8,0) = 96
3438821 close(3) = 0

This part comes from gconv_parseconfdir() in  conv/gconv_parseconfdir.h:

  /* Read the gconv-modules configuration file first.  */
  found = read_conf_file (buf, dir, dir_len);

  /* Next, see if there is a gconv-modules.d directory containing
     configuration files and if it is non-empty.  */
  cp--;
  cp[0] = '.';
  cp[1] = 'd';
  cp[2] = '\0';

  DIR *confdir = opendir (buf);
  if (confdir != NULL)
    {
      struct dirent *ent;
      while ((ent = readdir (confdir)) != NULL)

as can be seen, readdir() is called and the syscall returns 96 bytes for getdents64(), but the "ent" variable nevertheless gets NULL and returns without reading the "gconv-modules-extra.conf" file.

Finally it turns out, that this is a problem of missing large file support while scanning the contents of the gconv-modules.d/ directory.
In my build environment the /build/glibc/glibc-2.34/build-tree/hppa-libc/iconvdata/gconv-modules.d/gconv-modules-extra.conf file is located on-disk on a high inode, 
thus the readdir() function returns NULL.

I manually changed the code above to use the 64-bit variants to become:
      struct dirent64 *ent;
      while ((ent = readdir64 (confdir)) != NULL)
which then worked.

So finally, I'd suggest to enable 64-bit file-support for this specific function.
Either by manually using the 64-bit variants, or by compiling with  -D_LARGE_FILE_SOURCE=1  -D_FILE_OFFSET_BITS=64
(whatever is possible and makes sense).
Comment 1 Florian Weimer 2022-09-19 07:27:44 UTC
Patch posted:

[PATCH] gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583)
<https://sourceware.org/pipermail/libc-alpha/2022-September/142060.html>
Comment 2 Florian Weimer 2022-09-20 10:13:50 UTC
Fixed for 2.37 via:

commit f97905f24631097af325d6a231093071c3077a5f
Author: Florian Weimer <fweimer@redhat.com>
Date:   Tue Sep 20 12:12:43 2022 +0200

    gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583)
    
    It's possible that inode numbers are outside the 32-bit range.
    The existing code only handles the in-libc case correctly, and
    still uses the legacy interfaces when building iconv.
    
    Suggested-by: Helge Deller <deller@gmx.de>

Please let us know if we should backport this anywhere.
Comment 3 Helge Deller 2022-09-20 19:13:15 UTC
On 9/20/22 12:13, fweimer at redhat dot com wrote:
> https://sourceware.org/bugzilla/show_bug.cgi?id=29583
>
> Florian Weimer <fweimer at redhat dot com> changed:
>
>             What    |Removed                     |Added
> ----------------------------------------------------------------------------
>           Resolution|---                         |FIXED
>     Target Milestone|---                         |2.37
>               Status|ASSIGNED                    |RESOLVED
>
> --- Comment #2 from Florian Weimer <fweimer at redhat dot com> ---
> Fixed for 2.37 via:
>
> commit f97905f24631097af325d6a231093071c3077a5f
> Author: Florian Weimer <fweimer@redhat.com>
> Date:   Tue Sep 20 12:12:43 2022 +0200
>
>      gconv: Use 64-bit interfaces in gconv_parseconfdir (bug 29583)
>
>      It's possible that inode numbers are outside the 32-bit range.
>      The existing code only handles the in-libc case correctly, and
>      still uses the legacy interfaces when building iconv.
>
>      Suggested-by: Helge Deller <deller@gmx.de>
>
> Please let us know if we should backport this anywhere.

Yes, could you please backport it to 2.34+ ?
I'm running on Debian/unstable and it has 2.34.

Thanks,
Helge
Comment 4 Florian Weimer 2022-09-21 12:13:10 UTC
(In reply to Helge Deller from comment #3)
> Yes, could you please backport it to 2.34+ ?
> I'm running on Debian/unstable and it has 2.34.

Fair enough, backported to 2.34 and later.