[Bug libc/23497] readdir64@GLIBC_2.1 cannot parse the kernel directory stream

patrickdepinguin at gmail dot com sourceware-bugzilla@sourceware.org
Thu Dec 20 13:53:00 GMT 2018


https://sourceware.org/bugzilla/show_bug.cgi?id=23497

--- Comment #11 from Thomas De Schampheleire <patrickdepinguin at gmail dot com> ---
What I specifically see is that a readdir does not return entries when
accessing the 9p filesystem inside Qemu, with a CentOS 7 host. With following
simple test program:

#include <dirent.h>
#include <stdio.h>

void readonce(DIR *dirp)
{
    struct dirent *d;
    d = readdir(dirp);
    if (d == NULL) {
        printf("no more entries\n");
        return;
    }

    printf("d_name: %s\n", d->d_name);
    printf("d_ino: %lx\n", d->d_ino);
    printf("d_off: %lx\n", d->d_off);
    printf("d_reclen: %x\n", d->d_reclen);
    printf("d_type: %x\n", d->d_type);
    printf("\n");
}

int main(int argc, char *argv[])
{
    DIR *dirp = opendir(argv[1]);
    for (int i = 0; i < 6 ; i++) {
        readonce(dirp);
    }
}


Output under strace shows multiple calls to getdents64 when accessing the 9p
filesystem:

openat(AT_FDCWD, "/foo", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC)
= 3
fstat64(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
brk(NULL)                               = 0x90ad000
brk(0x90ce000)                          = 0x90ce000
brk(0x90cf000)                          = 0x90cf000
getdents64(3, /* 30 entries */, 32768)  = 944
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(4, 65), ...}) = 0
ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0
write(1, "no more entries\n", 16no more entries
)       = 16
getdents64(3, /* 0 entries */, 32768)   = 0
write(1, "no more entries\n", 16no more entries
)       = 16
getdents64(3, /* 0 entries */, 32768)   = 0
write(1, "no more entries\n", 16no more entries
)       = 16
getdents64(3, /* 0 entries */, 32768)   = 0
write(1, "no more entries\n", 16no more entries
)       = 16
getdents64(3, /* 0 entries */, 32768)   = 0
write(1, "no more entries\n", 16no more entries
)       = 16
getdents64(3, /* 0 entries */, 32768)   = 0
write(1, "no more entries\n", 16no more entries
)       = 16

while there is only one getdents64 call when accessing a local filesystem like
/tmp:

openat(AT_FDCWD, "/tmp", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC)
= 3
fstat64(3, {st_mode=S_IFDIR|S_ISVTX|0777, st_size=160, ...}) = 0
brk(NULL)                               = 0x8939000
brk(0x895a000)                          = 0x895a000
brk(0x895b000)                          = 0x895b000
getdents64(3, /* 8 entries */, 32768)   = 256
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(4, 65), ...}) = 0
ioctl(1, TCGETS, {B9600 opost isig icanon echo ...}) = 0
write(1, "d_name: .\n", 10d_name: .
)             = 10
write(1, "d_ino: 12f8\n", 12d_ino: 12f8
)           = 12
write(1, "d_off: 1\n", 9d_off: 1
)               = 9
write(1, "d_reclen: 10\n", 13d_reclen: 10
)          = 13
write(1, "d_type: 4\n", 10d_type: 4
)             = 10
write(1, "\n", 1
)                       = 1
write(1, "d_name: ..\n", 11d_name: ..
)            = 11
write(1, "d_ino: 12f8\n", 12d_ino: 12f8
)           = 12
write(1, "d_off: 2\n", 9d_off: 2
)               = 9
write(1, "d_reclen: 10\n", 13d_reclen: 10
)          = 13
write(1, "d_type: 4\n", 10d_type: 4
)             = 10
write(1, "\n", 1
)                       = 1
...


Using the same target software and same qemu version on another host machine
(which is a more modern Gentoo system with kernel 4.14.x, rather than the old
CentOS 7 with kernel 3.10), I see no issues on either type of filesystem.

I have yet to try it myself, but do you still think that the fix for this bug
(#23497) is not the solution here? 
The other bug #23960 refers to sigaction changes but I fail to see how they
relate to the reproducer above.
If I should open a new bug, please let me know.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the Glibc-bugs mailing list