diff options
Diffstat (limited to 'fs/udf/inode.c')
| -rw-r--r-- | fs/udf/inode.c | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index c9b4df5810d5..a445d599098d 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
| @@ -750,7 +750,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, | |||
| 750 | /* Are we beyond EOF? */ | 750 | /* Are we beyond EOF? */ |
| 751 | if (etype == -1) { | 751 | if (etype == -1) { |
| 752 | int ret; | 752 | int ret; |
| 753 | isBeyondEOF = 1; | 753 | isBeyondEOF = true; |
| 754 | if (count) { | 754 | if (count) { |
| 755 | if (c) | 755 | if (c) |
| 756 | laarr[0] = laarr[1]; | 756 | laarr[0] = laarr[1]; |
| @@ -792,7 +792,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, | |||
| 792 | endnum = c + 1; | 792 | endnum = c + 1; |
| 793 | lastblock = 1; | 793 | lastblock = 1; |
| 794 | } else { | 794 | } else { |
| 795 | isBeyondEOF = 0; | 795 | isBeyondEOF = false; |
| 796 | endnum = startnum = ((count > 2) ? 2 : count); | 796 | endnum = startnum = ((count > 2) ? 2 : count); |
| 797 | 797 | ||
| 798 | /* if the current extent is in position 0, | 798 | /* if the current extent is in position 0, |
| @@ -1288,6 +1288,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) | |||
| 1288 | struct kernel_lb_addr *iloc = &iinfo->i_location; | 1288 | struct kernel_lb_addr *iloc = &iinfo->i_location; |
| 1289 | unsigned int link_count; | 1289 | unsigned int link_count; |
| 1290 | unsigned int indirections = 0; | 1290 | unsigned int indirections = 0; |
| 1291 | int bs = inode->i_sb->s_blocksize; | ||
| 1291 | int ret = -EIO; | 1292 | int ret = -EIO; |
| 1292 | 1293 | ||
| 1293 | reread: | 1294 | reread: |
| @@ -1374,38 +1375,35 @@ reread: | |||
| 1374 | if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) { | 1375 | if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_EFE)) { |
| 1375 | iinfo->i_efe = 1; | 1376 | iinfo->i_efe = 1; |
| 1376 | iinfo->i_use = 0; | 1377 | iinfo->i_use = 0; |
| 1377 | ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize - | 1378 | ret = udf_alloc_i_data(inode, bs - |
| 1378 | sizeof(struct extendedFileEntry)); | 1379 | sizeof(struct extendedFileEntry)); |
| 1379 | if (ret) | 1380 | if (ret) |
| 1380 | goto out; | 1381 | goto out; |
| 1381 | memcpy(iinfo->i_ext.i_data, | 1382 | memcpy(iinfo->i_ext.i_data, |
| 1382 | bh->b_data + sizeof(struct extendedFileEntry), | 1383 | bh->b_data + sizeof(struct extendedFileEntry), |
| 1383 | inode->i_sb->s_blocksize - | 1384 | bs - sizeof(struct extendedFileEntry)); |
| 1384 | sizeof(struct extendedFileEntry)); | ||
| 1385 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { | 1385 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { |
| 1386 | iinfo->i_efe = 0; | 1386 | iinfo->i_efe = 0; |
| 1387 | iinfo->i_use = 0; | 1387 | iinfo->i_use = 0; |
| 1388 | ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize - | 1388 | ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry)); |
| 1389 | sizeof(struct fileEntry)); | ||
| 1390 | if (ret) | 1389 | if (ret) |
| 1391 | goto out; | 1390 | goto out; |
| 1392 | memcpy(iinfo->i_ext.i_data, | 1391 | memcpy(iinfo->i_ext.i_data, |
| 1393 | bh->b_data + sizeof(struct fileEntry), | 1392 | bh->b_data + sizeof(struct fileEntry), |
| 1394 | inode->i_sb->s_blocksize - sizeof(struct fileEntry)); | 1393 | bs - sizeof(struct fileEntry)); |
| 1395 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { | 1394 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { |
| 1396 | iinfo->i_efe = 0; | 1395 | iinfo->i_efe = 0; |
| 1397 | iinfo->i_use = 1; | 1396 | iinfo->i_use = 1; |
| 1398 | iinfo->i_lenAlloc = le32_to_cpu( | 1397 | iinfo->i_lenAlloc = le32_to_cpu( |
| 1399 | ((struct unallocSpaceEntry *)bh->b_data)-> | 1398 | ((struct unallocSpaceEntry *)bh->b_data)-> |
| 1400 | lengthAllocDescs); | 1399 | lengthAllocDescs); |
| 1401 | ret = udf_alloc_i_data(inode, inode->i_sb->s_blocksize - | 1400 | ret = udf_alloc_i_data(inode, bs - |
| 1402 | sizeof(struct unallocSpaceEntry)); | 1401 | sizeof(struct unallocSpaceEntry)); |
| 1403 | if (ret) | 1402 | if (ret) |
| 1404 | goto out; | 1403 | goto out; |
| 1405 | memcpy(iinfo->i_ext.i_data, | 1404 | memcpy(iinfo->i_ext.i_data, |
| 1406 | bh->b_data + sizeof(struct unallocSpaceEntry), | 1405 | bh->b_data + sizeof(struct unallocSpaceEntry), |
| 1407 | inode->i_sb->s_blocksize - | 1406 | bs - sizeof(struct unallocSpaceEntry)); |
| 1408 | sizeof(struct unallocSpaceEntry)); | ||
| 1409 | return 0; | 1407 | return 0; |
| 1410 | } | 1408 | } |
| 1411 | 1409 | ||
| @@ -1489,6 +1487,28 @@ reread: | |||
| 1489 | } | 1487 | } |
| 1490 | inode->i_generation = iinfo->i_unique; | 1488 | inode->i_generation = iinfo->i_unique; |
| 1491 | 1489 | ||
| 1490 | /* | ||
| 1491 | * Sanity check length of allocation descriptors and extended attrs to | ||
| 1492 | * avoid integer overflows | ||
| 1493 | */ | ||
| 1494 | if (iinfo->i_lenEAttr > bs || iinfo->i_lenAlloc > bs) | ||
| 1495 | goto out; | ||
| 1496 | /* Now do exact checks */ | ||
| 1497 | if (udf_file_entry_alloc_offset(inode) + iinfo->i_lenAlloc > bs) | ||
| 1498 | goto out; | ||
| 1499 | /* Sanity checks for files in ICB so that we don't get confused later */ | ||
| 1500 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | ||
| 1501 | /* | ||
| 1502 | * For file in ICB data is stored in allocation descriptor | ||
| 1503 | * so sizes should match | ||
| 1504 | */ | ||
| 1505 | if (iinfo->i_lenAlloc != inode->i_size) | ||
| 1506 | goto out; | ||
| 1507 | /* File in ICB has to fit in there... */ | ||
| 1508 | if (inode->i_size > bs - udf_file_entry_alloc_offset(inode)) | ||
| 1509 | goto out; | ||
| 1510 | } | ||
| 1511 | |||
| 1492 | switch (fe->icbTag.fileType) { | 1512 | switch (fe->icbTag.fileType) { |
| 1493 | case ICBTAG_FILE_TYPE_DIRECTORY: | 1513 | case ICBTAG_FILE_TYPE_DIRECTORY: |
| 1494 | inode->i_op = &udf_dir_inode_operations; | 1514 | inode->i_op = &udf_dir_inode_operations; |
