lkml.org 
[lkml]   [2021]   [Sep]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 033/217] udf: Check LVID earlier
    Date
    From: Jan Kara <jack@suse.cz>

    [ Upstream commit 781d2a9a2fc7d0be53a072794dc03ef6de770f3d ]

    We were checking validity of LVID entries only when getting
    implementation use information from LVID in udf_sb_lvidiu(). However if
    the LVID is suitably corrupted, it can cause problems also to code such
    as udf_count_free() which doesn't use udf_sb_lvidiu(). So check validity
    of LVID already when loading it from the disk and just disable LVID
    altogether when it is not valid.

    Reported-by: syzbot+7fbfe5fed73ebb675748@syzkaller.appspotmail.com
    Signed-off-by: Jan Kara <jack@suse.cz>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/udf/super.c | 25 ++++++++++++++++---------
    1 file changed, 16 insertions(+), 9 deletions(-)

    diff --git a/fs/udf/super.c b/fs/udf/super.c
    index 2b8147ecd97f..70b56011b823 100644
    --- a/fs/udf/super.c
    +++ b/fs/udf/super.c
    @@ -113,16 +113,10 @@ struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct super_block *sb)
    return NULL;
    lvid = (struct logicalVolIntegrityDesc *)UDF_SB(sb)->s_lvid_bh->b_data;
    partnum = le32_to_cpu(lvid->numOfPartitions);
    - if ((sb->s_blocksize - sizeof(struct logicalVolIntegrityDescImpUse) -
    - offsetof(struct logicalVolIntegrityDesc, impUse)) /
    - (2 * sizeof(uint32_t)) < partnum) {
    - udf_err(sb, "Logical volume integrity descriptor corrupted "
    - "(numOfPartitions = %u)!\n", partnum);
    - return NULL;
    - }
    /* The offset is to skip freeSpaceTable and sizeTable arrays */
    offset = partnum * 2 * sizeof(uint32_t);
    - return (struct logicalVolIntegrityDescImpUse *)&(lvid->impUse[offset]);
    + return (struct logicalVolIntegrityDescImpUse *)
    + (((uint8_t *)(lvid + 1)) + offset);
    }

    /* UDF filesystem type */
    @@ -1565,6 +1559,7 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_
    struct udf_sb_info *sbi = UDF_SB(sb);
    struct logicalVolIntegrityDesc *lvid;
    int indirections = 0;
    + u32 parts, impuselen;

    while (++indirections <= UDF_MAX_LVID_NESTING) {
    final_bh = NULL;
    @@ -1591,15 +1586,27 @@ static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_

    lvid = (struct logicalVolIntegrityDesc *)final_bh->b_data;
    if (lvid->nextIntegrityExt.extLength == 0)
    - return;
    + goto check;

    loc = leea_to_cpu(lvid->nextIntegrityExt);
    }

    udf_warn(sb, "Too many LVID indirections (max %u), ignoring.\n",
    UDF_MAX_LVID_NESTING);
    +out_err:
    brelse(sbi->s_lvid_bh);
    sbi->s_lvid_bh = NULL;
    + return;
    +check:
    + parts = le32_to_cpu(lvid->numOfPartitions);
    + impuselen = le32_to_cpu(lvid->lengthOfImpUse);
    + if (parts >= sb->s_blocksize || impuselen >= sb->s_blocksize ||
    + sizeof(struct logicalVolIntegrityDesc) + impuselen +
    + 2 * parts * sizeof(u32) > sb->s_blocksize) {
    + udf_warn(sb, "Corrupted LVID (parts=%u, impuselen=%u), "
    + "ignoring.\n", parts, impuselen);
    + goto out_err;
    + }
    }


    --
    2.30.2


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