GNU bug report logs - #43591
[PATCH core-updates] gnu: glibc-final: Catch all cases of a glibc user not requesting 64-bit offsets and then using readdir.

Previous Next

Package: guix-patches;

Reported by: Danny Milosavljevic <dannym <at> scratchpost.org>

Date: Thu, 24 Sep 2020 14:13:02 UTC

Severity: normal

Tags: patch

Full log


Message #29 received at 43591 <at> debbugs.gnu.org (full text, mbox):

From: Danny Milosavljevic <dannym <at> scratchpost.org>
To: Marius Bakke <marius <at> gnu.org>
Cc: 43591 <at> debbugs.gnu.org
Subject: Re: [bug#43591] [PATCH core-updates] gnu: glibc-final: Catch all
 cases of a glibc user not requesting 64-bit offsets and then using readdir.
Date: Fri, 25 Sep 2020 15:36:46 +0200
[Message part 1 (text/plain, inline)]
> >Why is this not an issue with i686 on x86_64 kernels?  
> 
> I'm not sure.  I'll check.

$ cat a00.c
#include <stdio.h>
#if defined( __ILP32__ )
#warning ILP32
#endif
int main() {
        return sizeof(off_t);
}
$ LC_ALL=C guix environment -s i686-linux gcc-toolchain -- gcc -o a00 a00.c
a00.c:3:2: warning: #warning ILP32 [-Wcpp]
    3 | #warning ILP32
      |  ^~~~~~~
$ ./a00
$ echo $?
4

That means they are using the Linux kernel's X86_32 ABI.
It has its own getdents64 system call that returns another value for d_off.

$ LC_ALL=C guix environment -s i686-linux gcc-toolchain -- gcc -o a00 -D_FILE_OFFSET_BITS=64 a00.c
a00.c:3:2: warning: #warning ILP32 [-Wcpp]
    3 | #warning ILP32
      |  ^~~~~~~
$ ./a00
$ echo $?
8

That is why __i686__ is not affected--at the cost of the kernel lying to us
about the file system.

Note that I also tried printing the actual d_off values[1]--on ILP32, even with
_FILE_OFFSET_BITS=64, the VALUES are still 32 bits, and the same values as
without _FILE_OFFSET_BITS.  The d_off SLOT gets bigger on _FILE_OFFSET_BITS=64.

(I also tried printing the actual d_off values[1] on x86_64 without any guix
environment -s, I get entirely different d_off values!!)

I also tried the former on native ARMHF--you get 32 bits d_off values.  And d_off
is always the same size as off_t.

off_t size changes depending on _FILE_OFFSET_BITS.

I do not have access to a real aarch64 machine--so no idea how it is there.
That would be the most interesting case, because those don't have X86_32,
so ILP32 is either not present or implemented differently.

ppc64 would also be interesting...

Test result of [1]:

system _FILE_OFFSET_BITS off_t   d_off-sizeof   d_off-values
-------------------------------------------------------------
x86_64 -                 8 Byte  8 Byte         8 Byte
i686   -                 4 Byte  4 Byte         4 Byte
i686   64                8 Byte  8 Byte         4 Byte
i686   32                4 Byte  4 Byte         4 Byte
i686   7                 4 Byte  4 Byte         4 Byte
armhf  -                 4 Byte  4 Byte         4 Byte
armhf  64                8 Byte  8 Byte         4 Byte
armhf  32                4 Byte  4 Byte         4 Byte
armhf  7                 4 Byte  4 Byte         4 Byte

This is all without qemu--in order to simplify the test case.

So I take it ext4 has some special compilation mode for 32 bits...

Could someone please test [1] on (real!) aarch64 and ppc64 and ppc32
machines?

[1] $ cat a00.c 
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <dirent.h>
#if defined( __ILP32__ )
#warning ILP32
#endif

int main() {
        DIR* d;
        struct dirent* ent;
        d = opendir("/tmp");
        errno = 0;
        assert(sizeof(ent->d_off) == sizeof(off_t));
        while ((ent = readdir(d)) != NULL) {
                printf("%llu\n", (unsigned long long) ent->d_off);
        }
        if (errno)
                perror("readdir");
        return sizeof(off_t);
[Message part 2 (application/pgp-signature, inline)]

This bug report was last modified 4 years and 251 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.