summaryrefslogtreecommitdiffstats
path: root/fs/udf/inode.c
diff options
context:
space:
mode:
authorSteven J. Magnani <steve.magnani@digidescorp.com>2019-08-14 08:50:02 -0400
committerJan Kara <jack@suse.cz>2019-08-26 05:17:55 -0400
commitab9a3a737284b3d9e1d2ba43a0ef31b3ef2e2417 (patch)
treeda1ecd5168487841b078727bfcb357edc1172e15 /fs/udf/inode.c
parent56db1991690f076c2a7e3b2a226629cd10901690 (diff)
udf: reduce leakage of blocks related to named streams
Windows is capable of creating UDF files having named streams. One example is the "Zone.Identifier" stream attached automatically to files downloaded from a network. See: https://msdn.microsoft.com/en-us/library/dn392609.aspx Modification of a file having one or more named streams in Linux causes the stream directory to become detached from the file, essentially leaking all blocks pertaining to the file's streams. Fix by saving off information about an inode's streams when reading it, for later use when its on-disk data is updated. Link: https://lore.kernel.org/r/20190814125002.10869-1-steve@digidescorp.com Signed-off-by: Steven J. Magnani <steve@digidescorp.com> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/udf/inode.c')
-rw-r--r--fs/udf/inode.c24
1 files changed, 23 insertions, 1 deletions
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 9bb18311a22f..54eee39f2698 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1485,6 +1485,8 @@ reread:
1485 iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); 1485 iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
1486 iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); 1486 iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs);
1487 iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint); 1487 iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint);
1488 iinfo->i_streamdir = 0;
1489 iinfo->i_lenStreams = 0;
1488 } else { 1490 } else {
1489 inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << 1491 inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
1490 (inode->i_sb->s_blocksize_bits - 9); 1492 (inode->i_sb->s_blocksize_bits - 9);
@@ -1498,6 +1500,16 @@ reread:
1498 iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); 1500 iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
1499 iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); 1501 iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs);
1500 iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); 1502 iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint);
1503
1504 /* Named streams */
1505 iinfo->i_streamdir = (efe->streamDirectoryICB.extLength != 0);
1506 iinfo->i_locStreamdir =
1507 lelb_to_cpu(efe->streamDirectoryICB.extLocation);
1508 iinfo->i_lenStreams = le64_to_cpu(efe->objectSize);
1509 if (iinfo->i_lenStreams >= inode->i_size)
1510 iinfo->i_lenStreams -= inode->i_size;
1511 else
1512 iinfo->i_lenStreams = 0;
1501 } 1513 }
1502 inode->i_generation = iinfo->i_unique; 1514 inode->i_generation = iinfo->i_unique;
1503 1515
@@ -1760,9 +1772,19 @@ static int udf_update_inode(struct inode *inode, int do_sync)
1760 iinfo->i_ext.i_data, 1772 iinfo->i_ext.i_data,
1761 inode->i_sb->s_blocksize - 1773 inode->i_sb->s_blocksize -
1762 sizeof(struct extendedFileEntry)); 1774 sizeof(struct extendedFileEntry));
1763 efe->objectSize = cpu_to_le64(inode->i_size); 1775 efe->objectSize =
1776 cpu_to_le64(inode->i_size + iinfo->i_lenStreams);
1764 efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); 1777 efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
1765 1778
1779 if (iinfo->i_streamdir) {
1780 struct long_ad *icb_lad = &efe->streamDirectoryICB;
1781
1782 icb_lad->extLocation =
1783 cpu_to_lelb(iinfo->i_locStreamdir);
1784 icb_lad->extLength =
1785 cpu_to_le32(inode->i_sb->s_blocksize);
1786 }
1787
1766 udf_adjust_time(iinfo, inode->i_atime); 1788 udf_adjust_time(iinfo, inode->i_atime);
1767 udf_adjust_time(iinfo, inode->i_mtime); 1789 udf_adjust_time(iinfo, inode->i_mtime);
1768 udf_adjust_time(iinfo, inode->i_ctime); 1790 udf_adjust_time(iinfo, inode->i_ctime);