diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 337836a0a170..b766b5c9c593 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -821,6 +821,8 @@ static int isofs_fill_super(struct super_block *s, struct fs_context *fc) if (!sb_set_blocksize(s, orig_zonesize)) goto out_freesbi; + sbi->s_session_start = (sector_t)vol_desc_start << + (ISOFS_BLOCK_BITS - s->s_blocksize_bits); sbi->s_nls_iocharset = NULL; #ifdef CONFIG_JOLIET diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index dacb9cdae4fd..79ca0256843a 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h @@ -35,6 +35,8 @@ struct isofs_sb_info { unsigned long s_firstdatazone; unsigned long s_log_zone_size; unsigned long s_max_size; + /* Session start in filesystem block units. */ + sector_t s_session_start; int s_rock_offset; /* offset of SUSP fields within SU area */ s32 s_sbsector; diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 2628f31bd3a5..84e0d764c210 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c @@ -9,6 +9,7 @@ #include #include +#include #include "isofs.h" #include "rock.h" @@ -84,6 +85,10 @@ static void init_rock_state(struct rock_state *rs, struct inode *inode) */ static int rock_continue(struct rock_state *rs) { + struct super_block *sb = rs->inode->i_sb; + struct isofs_sb_info *sbi = ISOFS_SB(sb); + sector_t session_end = sbi->s_session_start + + ((sector_t)sbi->s_nzones << (ISOFS_BLOCK_BITS - sb->s_blocksize_bits)); int ret = 1; int blocksize = 1 << rs->inode->i_blkbits; const int min_de_size = offsetof(struct rock_ridge, u); @@ -101,11 +106,13 @@ static int rock_continue(struct rock_state *rs) goto out; } - if ((unsigned)rs->cont_extent >= ISOFS_SB(rs->inode->i_sb)->s_nzones) { + if (rs->cont_extent && + (rs->cont_extent < sbi->s_session_start || + rs->cont_extent >= session_end)) { printk(KERN_NOTICE "rock: corrupted directory entry. " "extent=%u out of volume (nzones=%lu)\n", (unsigned)rs->cont_extent, - ISOFS_SB(rs->inode->i_sb)->s_nzones); + sbi->s_nzones); ret = -EIO; goto out; }