lkml.org 
[lkml]   [2005]   [Nov]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [RFC,PATCH] libfs dcache_readdir() and dcache_dir_lseek() bugfix
    From
    Date
    On Fri, 2005-11-04 at 16:11 +0100, jblunck@suse.de wrote:
    > On Fri, Nov 04, Miklos Szeredi wrote:
    >
    > > > As I said: "Old glibc implementations (e.g. glibc-2.2.5) are
    > > > lseeking after every call to getdents() ..."
    > >
    > > Hmm, why would it do that? This seems like it's glibc being stupid.
    > >
    >
    > Well, glibc is that stupid and triggers the bug.

    It is due to the kernel's 32-bit struct dirent being smaller than
    glibc's 32-bit struct dirent (glibc has the extra ->d_type field).
    Because the dirent record length depends on the filename length, the
    exact expansion factor for the results of a call to getdents() may not
    be precomputed.
    glibc uses a heuristic in order to estimate the expansion size, and then
    uses that to allocate an intermediate buffer in which to store the
    results of the getdents syscall.
    If the contents of said intermediate buffer still happen to overflow the
    user-allocated buffer, then glibc calls lseek() in order to rewind the
    file pointer to the next entry it wants to read (and screws any
    filesystem that doesn't support lseek on directories).

    This code appears still to be part of glibc, however it is rarely
    triggered these days because glibc's implementation now defaults to
    using the getdents64 syscall (if it exists) instead of the 32-bit
    version. Since the kernel's struct dirent64 is the same size as the
    glibc struct dirent64 (and larger than the 32-bit struct dirent), there
    is never any chance of buffer overflow.

    The new bug is rather that glibc will return EOVERFLOW, and try to
    rewind your file pointer if your filesystem happens to return 64-bit
    offsets to getdents64().

    > > Unfortunately I can't since I don't have such old glibc.
    >
    > The testcase is similar to what "rm *" with the old glibc would do. It just
    > a testcase to show where the problem is.

    'rm -rf' on a large directory used to be a great way to trigger it.

    Cheers,
    Trond

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-11-04 17:30    [W:0.022 / U:30.192 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site