fs/ntfs3: Check fields while reading
Subsystems (3)
PATCH 1/1 fs/ntfs3: Check fields while reading
commit 0e8235d28f3a0e9eda9f02ff67ee566d5f42b66b upstream.
Added new functions index_hdr_check and index_buf_check. Now we check all stuff for correctness while reading from disk. Also fixed bug with stale nfs data.
--- fs/ntfs3/index.c | 84 ++++++++++++++++++++++++++++++---- fs/ntfs3/inode.c | 18 ++++---- fs/ntfs3/ntfs_fs.h | 4 +- fs/ntfs3/run.c | 7 ++- fs/ntfs3/xattr.c | 109 +++++++++++++++++++++++++++++---------------- 5 files changed, 164 insertions(+), 58 deletions(-)
fs/ntfs3/index.c +76 -8
@@ -605,11 +605,58 @@ static const struct NTFS_DE *hdr_insert_head(struct INDEX_HDR *hdr,return e; } +/* +* index_hdr_check +* +* return true if INDEX_HDR is valid +*/ +static bool index_hdr_check (const struct INDEX_HDR *hdr,u32 bytes) +{ +u32 end =le32_to_cpu (hdr->used); +u32 tot =le32_to_cpu (hdr->total); +u32 off =le32_to_cpu (hdr->de_off); + +if (!IS_ALIGNED (off,8 ) || tot > bytes || end > tot || + off +sizeof (struct NTFS_DE ) > end) { +/* incorrect index buffer. */ +return false; + } + +return true; +} + +/* +* index_buf_check +* +* return true if INDEX_BUFFER seems is valid +*/ +static bool index_buf_check (const struct INDEX_BUFFER *ib,u32 bytes, +const CLST *vbn) +{ +const struct NTFS_RECORD_HEADER *rhdr = &ib->rhdr; +u16 fo =le16_to_cpu (rhdr->fix_off); +u16 fn =le16_to_cpu (rhdr->fix_num); + +if (bytes <= offsetof(struct INDEX_BUFFER , ihdr) || + rhdr->sign !=NTFS_INDX_SIGNATURE || + fo <sizeof (struct INDEX_BUFFER ) +/* Check index buffer vbn. */ + || (vbn && *vbn !=le64_to_cpu (ib->vbn)) || (fo %sizeof (short )) || + fo + fn *sizeof (short ) >= bytes || + fn != ((bytes >>SECTOR_SHIFT ) +1 )) { +/* incorrect index buffer. */ +return false; + } + +return index_hdr_check (&ib->ihdr, + bytes - offsetof(struct INDEX_BUFFER , ihdr)); +} +void fnd_clear (struct ntfs_fnd *fnd) {int i; -for (i =0 ; i < fnd->level; i++) { +for (i = fnd->level -1 ; i >=0 ; i--) {struct indx_node *n = fnd->nodes[i];if (!n)
@@ -828,9 +875,16 @@ int indx_init(struct ntfs_index *indx, struct ntfs_sb_info *sbi,u32 t32;const struct INDEX_ROOT *root =resident_data (attr); + t32 =le32_to_cpu (attr->res.data_size); +if (t32 <= offsetof(struct INDEX_ROOT , ihdr) || + !index_hdr_check (&root->ihdr, + t32 - offsetof(struct INDEX_ROOT , ihdr))) { + goto out; + } +/* Check root fields. */ if (!root->index_block_clst) -return -EINVAL ; + goto out; indx->type = type; indx->idx2vbn_bits =__ffs (root->index_block_clst);
@@ -842,19 +896,19 @@ int indx_init(struct ntfs_index *indx, struct ntfs_sb_info *sbi,if (t32 < sbi->cluster_size) {/* Index record is smaller than a cluster, use 512 blocks. */ if (t32 != root->index_block_clst *SECTOR_SIZE ) -return -EINVAL ; + goto out;/* Check alignment to a cluster. */ if ((sbi->cluster_size >>SECTOR_SHIFT ) & (root->index_block_clst -1 )) { -return -EINVAL ; + goto out; } indx->vbn2vbo_bits =SECTOR_SHIFT ; }else {/* Index record must be a multiple of cluster size. */ if (t32 != root->index_block_clst << sbi->cluster_bits) -return -EINVAL ; + goto out; indx->vbn2vbo_bits = sbi->cluster_bits; }
@@ -862,7 +916,14 @@ int indx_init(struct ntfs_index *indx, struct ntfs_sb_info *sbi,init_rwsem (&indx->run_lock); indx->cmp =get_cmp_func (root); -return indx->cmp ?0 : -EINVAL ; +if (!indx->cmp) + goto out; + +return 0 ; + +out: +ntfs_set_state (sbi,NTFS_DIRTY_DIRTY ); +return -EINVAL ; } static struct indx_node *indx_new(struct ntfs_index *indx,
@@ -1020,6 +1081,13 @@ int indx_read(struct ntfs_index *indx, struct ntfs_inode *ni, CLST vbn, goto out; ok: +if (!index_buf_check (ib, bytes, &vbn)) { +ntfs_inode_err (&ni->vfs_inode,"directory corrupted" ); +ntfs_set_state (ni->mi.sbi,NTFS_DIRTY_ERROR ); + err = -EINVAL ; + goto out; + } +if (err == -E_NTFS_FIXUP ) {ntfs_write_bh (ni->mi.sbi, &ib->rhdr, &in->nb,0 ); err =0 ;
@@ -1607,9 +1675,9 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni,if (err) {/* Restore root. */ -if (mi_resize_attr (mi, attr, -ds_root)) +if (mi_resize_attr (mi, attr, -ds_root)) {memcpy (attr, a_root, asize); -else { + }else {/* Bug? */ ntfs_set_state (sbi,NTFS_DIRTY_ERROR ); }
fs/ntfs3/inode.c +10 -8
@@ -81,7 +81,7 @@ static struct inode *ntfs_read_mft(struct inode *inode, le16_to_cpu(ref->seq), le16_to_cpu(rec->seq)); goto out; }else if (!is_rec_inuse (rec)) { - err = -EINVAL ; + err = -ESTALE ;ntfs_err (sb,"Inode r=%x is not in use!" , (u32 )ino); goto out; }
@@ -92,8 +92,10 @@ static struct inode *ntfs_read_mft(struct inode *inode, goto out; } -if (!is_rec_base (rec)) - goto Ok; +if (!is_rec_base (rec)) { + err = -EINVAL ; + goto out; + }/* Record should contain $I30 root. */ is_dir = rec->flags &RECORD_FLAG_DIR ;
@@ -472,7 +474,6 @@ static struct inode *ntfs_read_mft(struct inode *inode, inode->i_flags |=S_NOSEC ; } -Ok:if (ino ==MFT_REC_MFT && !sb->s_root) sbi->mft.ni =NULL ;
@@ -526,6 +527,9 @@ struct inode *ntfs_iget5(struct super_block *sb, const struct MFT_REF *ref,_ntfs_bad_inode (inode); } +if (IS_ERR (inode) && name) +ntfs_set_state (sb->s_fs_info,NTFS_DIRTY_ERROR ); +return inode; }
@@ -1641,10 +1645,8 @@ struct inode *ntfs_create_inode(struct user_namespace *mnt_userns,ntfs_remove_reparse (sbi,IO_REPARSE_TAG_SYMLINK , &new_de->ref); out5: -if (S_ISDIR (mode) ||run_is_empty (&ni->file.run)) - goto out4; - -run_deallocate (sbi, &ni->file.run, false); +if (!S_ISDIR (mode)) +run_deallocate (sbi, &ni->file.run, false); out4:clear_rec_inuse (rec);
fs/ntfs3/ntfs_fs.h +2 -2
@@ -794,12 +794,12 @@ int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf, u32 run_buf_size, CLST *packed_vcns);int run_unpack (struct runs_tree *run,struct ntfs_sb_info *sbi,CLST ino,CLST svcn,CLST evcn,CLST vcn,const u8 *run_buf, -u32 run_buf_size); +int run_buf_size);#ifdef NTFS3_CHECK_FREE_CLST int run_unpack_ex (struct runs_tree *run,struct ntfs_sb_info *sbi,CLST ino,CLST svcn,CLST evcn,CLST vcn,const u8 *run_buf, -u32 run_buf_size); +int run_buf_size);#else #define run_unpack_ex run_unpack#endif
fs/ntfs3/run.c +5 -2
@@ -919,12 +919,15 @@ int run_pack(const struct runs_tree *run, CLST svcn, CLST len, u8 *run_buf,*/ int run_unpack (struct runs_tree *run,struct ntfs_sb_info *sbi,CLST ino,CLST svcn,CLST evcn,CLST vcn,const u8 *run_buf, -u32 run_buf_size) +int run_buf_size) {u64 prev_lcn, vcn64, lcn, next_vcn;const u8 *run_last, *run_0;bool is_mft = ino ==MFT_REC_MFT ; +if (run_buf_size <0 ) +return -EINVAL ; +/* Check for empty. */ if (evcn +1 == svcn)return 0 ;
@@ -1046,7 +1049,7 @@ int run_unpack(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,*/ int run_unpack_ex (struct runs_tree *run,struct ntfs_sb_info *sbi,CLST ino,CLST svcn,CLST evcn,CLST vcn,const u8 *run_buf, -u32 run_buf_size) +int run_buf_size) {int ret, err;CLST next_vcn, lcn, len;
fs/ntfs3/xattr.c +71 -38
204 lines not on this page · raw message
Signature · 1 line
2.41.0.455.g037347b96a-goog
Greg KH
maintainerQuoted 11 lines · Lee Jones
commit
0e8235d28f3a0e9eda9f02ff67ee566d5f42b66bupstream.Added new functions
index_hdr_checkandindex_buf_check. Now we check all stuff for correctness while reading from disk. Also fixed bug with stale nfs data.Reported-by van fantasy <[email protected]>Signed-off-by Konstantin Komarov <[email protected]>Fixes 82cae269cfa95 ("fs/ntfs3: Add initialization of super block")Signed-off-by Lee Jones <[email protected]>---
What stable tree(s) is this for?
thanks,
greg k-h
Quoted 7 lines · Greg KH
Quoted 6 lines · Lee Jones
commit
0e8235d28f3a0e9eda9f02ff67ee566d5f42b66bupstream.Added new functions
index_hdr_checkandindex_buf_check. Now we check all stuff for correctness while reading from disk. Also fixed bug with stale nfs data.
Quoted 7 lines
Quoted 5 lines
Reported-by van fantasy <[email protected]>Signed-off-by Konstantin Komarov <[email protected]>Fixes 82cae269cfa95 ("fs/ntfs3: Add initialization of super block")Signed-off-by Lee Jones <[email protected]>---
What stable tree(s) is this for?
I thought you had tooling that used the Fixes: tag for this?
v6.1 and v5.15 please.
Signature · 1 line
Lee Jones [李琼斯]
Greg KH
maintainerQuoted 15 lines · Lee Jones
Quoted 13 lines · Greg KH
Quoted 11 lines · Lee Jones
commit
0e8235d28f3a0e9eda9f02ff67ee566d5f42b66bupstream.Added new functions
index_hdr_checkandindex_buf_check. Now we check all stuff for correctness while reading from disk. Also fixed bug with stale nfs data.Reported-by van fantasy <[email protected]>Signed-off-by Konstantin Komarov <[email protected]>Fixes 82cae269cfa95 ("fs/ntfs3: Add initialization of super block")Signed-off-by Lee Jones <[email protected]>---
Quoted 3 lines
Quoted 1 line
What stable tree(s) is this for?
I thought you had tooling that used the Fixes: tag for this?
Yes, but that tells me how far back to take a patch, but not what a hand-crafted backport should be applied to :)
Now queued up, thanks.
greg k-h