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>
This commit is contained in:

committed by
Jan Kara

parent
56db199169
commit
ab9a3a7372
@@ -1485,6 +1485,8 @@ reread:
|
||||
iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
|
||||
iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs);
|
||||
iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint);
|
||||
iinfo->i_streamdir = 0;
|
||||
iinfo->i_lenStreams = 0;
|
||||
} else {
|
||||
inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
|
||||
(inode->i_sb->s_blocksize_bits - 9);
|
||||
@@ -1498,6 +1500,16 @@ reread:
|
||||
iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
|
||||
iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs);
|
||||
iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint);
|
||||
|
||||
/* Named streams */
|
||||
iinfo->i_streamdir = (efe->streamDirectoryICB.extLength != 0);
|
||||
iinfo->i_locStreamdir =
|
||||
lelb_to_cpu(efe->streamDirectoryICB.extLocation);
|
||||
iinfo->i_lenStreams = le64_to_cpu(efe->objectSize);
|
||||
if (iinfo->i_lenStreams >= inode->i_size)
|
||||
iinfo->i_lenStreams -= inode->i_size;
|
||||
else
|
||||
iinfo->i_lenStreams = 0;
|
||||
}
|
||||
inode->i_generation = iinfo->i_unique;
|
||||
|
||||
@@ -1760,9 +1772,19 @@ static int udf_update_inode(struct inode *inode, int do_sync)
|
||||
iinfo->i_ext.i_data,
|
||||
inode->i_sb->s_blocksize -
|
||||
sizeof(struct extendedFileEntry));
|
||||
efe->objectSize = cpu_to_le64(inode->i_size);
|
||||
efe->objectSize =
|
||||
cpu_to_le64(inode->i_size + iinfo->i_lenStreams);
|
||||
efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
|
||||
|
||||
if (iinfo->i_streamdir) {
|
||||
struct long_ad *icb_lad = &efe->streamDirectoryICB;
|
||||
|
||||
icb_lad->extLocation =
|
||||
cpu_to_lelb(iinfo->i_locStreamdir);
|
||||
icb_lad->extLength =
|
||||
cpu_to_le32(inode->i_sb->s_blocksize);
|
||||
}
|
||||
|
||||
udf_adjust_time(iinfo, inode->i_atime);
|
||||
udf_adjust_time(iinfo, inode->i_mtime);
|
||||
udf_adjust_time(iinfo, inode->i_ctime);
|
||||
|
Reference in New Issue
Block a user