diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 11f10493125427b2e99d33320475ec5d40fdc2de..48be49cffbc0739ba6a3ac0414692a0071c68f94 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1374,6 +1374,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode) ret = -EIO; goto out; } + iinfo->i_hidden = hidden_inode; iinfo->i_unique = 0; iinfo->i_lenEAttr = 0; iinfo->i_lenExtents = 0; @@ -1681,8 +1682,12 @@ static int udf_update_inode(struct inode *inode, int do_sync) if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0) fe->fileLinkCount = cpu_to_le16(inode->i_nlink - 1); - else - fe->fileLinkCount = cpu_to_le16(inode->i_nlink); + else { + if (iinfo->i_hidden) + fe->fileLinkCount = cpu_to_le16(0); + else + fe->fileLinkCount = cpu_to_le16(inode->i_nlink); + } fe->informationLength = cpu_to_le64(inode->i_size); @@ -1843,8 +1848,13 @@ struct inode *__udf_iget(struct super_block *sb, struct kernel_lb_addr *ino, if (!inode) return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) + if (!(inode->i_state & I_NEW)) { + if (UDF_I(inode)->i_hidden != hidden_inode) { + iput(inode); + return ERR_PTR(-EFSCORRUPTED); + } return inode; + } memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); err = udf_read_inode(inode, hidden_inode); diff --git a/fs/udf/super.c b/fs/udf/super.c index 699cda7f89f938453b0e71c0496dab027a5b01fd..5c2d7a97df9ad69b8f93d15e4eb2fe348aa5f554 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -154,6 +154,7 @@ static struct inode *udf_alloc_inode(struct super_block *sb) ei->i_next_alloc_block = 0; ei->i_next_alloc_goal = 0; ei->i_strat4096 = 0; + ei->i_hidden = 0; init_rwsem(&ei->i_data_sem); ei->cached_extent.lstart = -1; spin_lock_init(&ei->i_extent_cache_lock); diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h index 2ef0e212f08a3d55ce25b8c6e34843a03fa5f88c..c6acbc7c1c85921923ef82e1320f39ac800abe6b 100644 --- a/fs/udf/udf_i.h +++ b/fs/udf/udf_i.h @@ -42,7 +42,8 @@ struct udf_inode_info { unsigned i_efe : 1; /* extendedFileEntry */ unsigned i_use : 1; /* unallocSpaceEntry */ unsigned i_strat4096 : 1; - unsigned reserved : 26; + unsigned i_hidden : 1; /* hidden system inode */ + unsigned reserved : 25; union { struct short_ad *i_sad; struct long_ad *i_lad;