lkml.org 
[lkml]   [2021]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 580/593] exfat: handle wrong stream entry size in exfat_readdir()
    Date
    From: Namjae Jeon <namjae.jeon@samsung.com>

    commit 1e5654de0f51890f88abd409ebf4867782431e81 upstream.

    The compatibility issue between linux exfat and exfat of some camera
    company was reported from Florian. In their exfat, if the number of files
    exceeds any limit, the DataLength in stream entry of the directory is
    no longer updated. So some files created from camera does not show in
    linux exfat. because linux exfat doesn't allow that cpos becomes larger
    than DataLength of stream entry. This patch check DataLength in stream
    entry only if the type is ALLOC_NO_FAT_CHAIN and add the check ensure
    that dentry offset does not exceed max dentries size(256 MB) to avoid
    the circular FAT chain issue.

    Fixes: ca06197382bd ("exfat: add directory operations")
    Cc: stable@vger.kernel.org # v5.9
    Reported-by: Florian Cramer <flrncrmr@gmail.com>
    Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
    Tested-by: Chris Down <chris@chrisdown.name>
    Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/exfat/dir.c | 8 +++++---
    1 file changed, 5 insertions(+), 3 deletions(-)

    --- a/fs/exfat/dir.c
    +++ b/fs/exfat/dir.c
    @@ -62,7 +62,7 @@ static void exfat_get_uniname_from_ext_e
    static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry)
    {
    int i, dentries_per_clu, dentries_per_clu_bits = 0, num_ext;
    - unsigned int type, clu_offset;
    + unsigned int type, clu_offset, max_dentries;
    sector_t sector;
    struct exfat_chain dir, clu;
    struct exfat_uni_name uni_name;
    @@ -85,6 +85,8 @@ static int exfat_readdir(struct inode *i

    dentries_per_clu = sbi->dentries_per_clu;
    dentries_per_clu_bits = ilog2(dentries_per_clu);
    + max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES,
    + (u64)sbi->num_clusters << dentries_per_clu_bits);

    clu_offset = dentry >> dentries_per_clu_bits;
    exfat_chain_dup(&clu, &dir);
    @@ -108,7 +110,7 @@ static int exfat_readdir(struct inode *i
    }
    }

    - while (clu.dir != EXFAT_EOF_CLUSTER) {
    + while (clu.dir != EXFAT_EOF_CLUSTER && dentry < max_dentries) {
    i = dentry & (dentries_per_clu - 1);

    for ( ; i < dentries_per_clu; i++, dentry++) {
    @@ -244,7 +246,7 @@ static int exfat_iterate(struct file *fi
    if (err)
    goto unlock;
    get_new:
    - if (cpos >= i_size_read(inode))
    + if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode))
    goto end_of_dir;

    err = exfat_readdir(inode, &cpos, &de);

    \
     
     \ /
      Last update: 2021-07-12 09:20    [W:4.090 / U:0.384 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site