diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index b766b5c9c593..184350d2e6ad 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -1176,7 +1176,6 @@ static int isofs_read_level3_size(struct inode *inode) unsigned long block, offset, block_saved, offset_saved; int i = 0; int more_entries = 0; - struct iso_directory_record *tmpde = NULL; struct iso_inode_info *ei = ISOFS_I(inode); inode->i_size = 0; @@ -1200,9 +1199,12 @@ static int isofs_read_level3_size(struct inode *inode) goto out_noread; } de = (struct iso_directory_record *) (bh->b_data + offset); - de_len = *(unsigned char *) de; - if (de_len == 0) { + /* + * If we are at the end of a block (or at its zero-padded + * tail), move on to the next block. + */ + if (offset >= bufsize || de->length[0] == 0) { brelse(bh); bh = NULL; ++block; @@ -1210,32 +1212,18 @@ static int isofs_read_level3_size(struct inode *inode) continue; } + if (!isofs_dir_record_valid(de, offset, bufsize)) { + printk(KERN_NOTICE "iso9660: Corrupted directory entry in block %lu of inode %llu\n", + block, inode->i_ino); + brelse(bh); + return -EIO; + } + + de_len = de->length[0]; block_saved = block; offset_saved = offset; offset += de_len; - /* Make sure we have a full directory entry */ - if (offset >= bufsize) { - int slop = bufsize - offset + de_len; - if (!tmpde) { - tmpde = kmalloc(256, GFP_KERNEL); - if (!tmpde) - goto out_nomem; - } - memcpy(tmpde, de, slop); - offset &= bufsize - 1; - block++; - brelse(bh); - bh = NULL; - if (offset) { - bh = sb_bread(inode->i_sb, block); - if (!bh) - goto out_noread; - memcpy((void *)tmpde+slop, bh->b_data, offset); - } - de = tmpde; - } - inode->i_size += isonum_733(de->size); if (i == 1) { ei->i_next_section_block = block_saved; @@ -1249,17 +1237,11 @@ static int isofs_read_level3_size(struct inode *inode) goto out_toomany; } while (more_entries); out: - kfree(tmpde); brelse(bh); return 0; -out_nomem: - brelse(bh); - return -ENOMEM; - out_noread: printk(KERN_INFO "ISOFS: unable to read i-node block %lu\n", block); - kfree(tmpde); return -EIO; out_toomany: