• Linus Torvalds's avatar
    Make filldir[64]() verify the directory entry filename is valid · 8a23eb80
    Linus Torvalds authored
    This has been discussed several times, and now filesystem people are
    talking about doing it individually at the filesystem layer, so head
    that off at the pass and just do it in getdents{64}().
    
    This is partially based on a patch by Jann Horn, but checks for NUL
    bytes as well, and somewhat simplified.
    
    There's also commentary about how it might be better if invalid names
    due to filesystem corruption don't cause an immediate failure, but only
    an error at the end of the readdir(), so that people can still see the
    filenames that are ok.
    
    There's also been discussion about just how much POSIX strictly speaking
    requires this since it's about filesystem corruption.  It's really more
    "protect user space from bad behavior" as pointed out by Jann.  But
    since Eric Biederman looked up the POSIX wording, here it is for context:
    
     "From readdir:
    
       The readdir() function shall return a pointer to a structure
       representing the directory entry at the current position in the
       directory stream specified by the argument dirp, and position the
       directory stream at the next entry. It shall return a null pointer
       upon reaching the end of the directory stream. The structure dirent
       defined in the <dirent.h> header describes a directory entry.
    
      From definitions:
    
       3.129 Directory Entry (or Link)
    
       An object that associates a filename with a file. Several directory
       entries can associate names with the same file.
    
      ...
    
       3.169 Filename
    
       A name consisting of 1 to {NAME_MAX} bytes used to name a file. The
       characters composing the name may be selected from the set of all
       character values excluding the slash character and the null byte. The
       filenames dot and dot-dot have special meaning. A filename is
       sometimes referred to as a 'pathname component'."
    
    Note that I didn't bother adding the checks to any legacy interfaces
    that nobody uses.
    
    Also note that if this ends up being noticeable as a performance
    regression, we can fix that to do a much more optimized model that
    checks for both NUL and '/' at the same time one word at a time.
    
    We haven't really tended to optimize 'memchr()', and it only checks for
    one pattern at a time anyway, and we really _should_ check for NUL too
    (but see the comment about "soft errors" in the code about why it
    currently only checks for '/')
    
    See the CONFIG_DCACHE_WORD_ACCESS case of hash_name() for how the name
    lookup code looks for pathname terminating characters in parallel.
    
    Link: https://lore.kernel.org/lkml/20190118161440.220134-2-jannh@google.com/
    Cc: Alexander Viro <viro@zeniv.linux.org.uk>
    Cc: Jann Horn <jannh@google.com>
    Cc: Eric W. Biederman <ebiederm@xmission.com>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    8a23eb80
readdir.c 14.9 KB