diff options
author | Dan Carpenter | 2021-08-24 10:51:04 +0300 |
---|---|---|
committer | Konstantin Komarov | 2021-08-27 17:05:14 +0300 |
commit | b8155e95de38b25a69dfb03e4731fd6c5a28531e (patch) | |
tree | cfd1fbd953fe01926acc0c44a891ff0094679c08 /fs/ntfs3 | |
parent | 8c83a4851da1c7eda83098ade238665b15774da3 (diff) |
fs/ntfs3: Fix error handling in indx_insert_into_root()
There are three bugs in this code:
1) If indx_get_root() fails, then return -EINVAL instead of success.
2) On the "/* make root external */" -EOPNOTSUPP; error path it should
free "re" but it has a memory leak.
3) If indx_new() fails then it will lead to an error pointer dereference
when we call put_indx_node().
I've re-written the error handling to be more clear.
Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Kari Argillander <kari.argillander@gmail.com>
Signed-off-by: Konstantin Komarov <almaz.alexandrovich@paragon-software.com>
Diffstat (limited to 'fs/ntfs3')
-rw-r--r-- | fs/ntfs3/index.c | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/fs/ntfs3/index.c b/fs/ntfs3/index.c index f4729aa50671..69c6c4e0b4d9 100644 --- a/fs/ntfs3/index.c +++ b/fs/ntfs3/index.c @@ -1555,12 +1555,12 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, u32 root_size, new_root_size; struct ntfs_sb_info *sbi; int ds_root; - struct INDEX_ROOT *root, *a_root = NULL; + struct INDEX_ROOT *root, *a_root; /* Get the record this root placed in */ root = indx_get_root(indx, ni, &attr, &mi); if (!root) - goto out; + return -EINVAL; /* * Try easy case: @@ -1592,10 +1592,8 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, /* Make a copy of root attribute to restore if error */ a_root = kmemdup(attr, asize, GFP_NOFS); - if (!a_root) { - err = -ENOMEM; - goto out; - } + if (!a_root) + return -ENOMEM; /* copy all the non-end entries from the index root to the new buffer.*/ to_move = 0; @@ -1605,7 +1603,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, for (e = e0;; e = hdr_next_de(hdr, e)) { if (!e) { err = -EINVAL; - goto out; + goto out_free_root; } if (de_is_last(e)) @@ -1613,14 +1611,13 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, to_move += le16_to_cpu(e->size); } - n = NULL; if (!to_move) { re = NULL; } else { re = kmemdup(e0, to_move, GFP_NOFS); if (!re) { err = -ENOMEM; - goto out; + goto out_free_root; } } @@ -1637,7 +1634,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, if (ds_root > 0 && used + ds_root > sbi->max_bytes_per_attr) { /* make root external */ err = -EOPNOTSUPP; - goto out; + goto out_free_re; } if (ds_root) @@ -1667,7 +1664,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, /* bug? */ ntfs_set_state(sbi, NTFS_DIRTY_ERROR); err = -EINVAL; - goto out1; + goto out_free_re; } if (err) { @@ -1678,7 +1675,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, /* bug? */ ntfs_set_state(sbi, NTFS_DIRTY_ERROR); } - goto out1; + goto out_free_re; } e = (struct NTFS_DE *)(root + 1); @@ -1689,7 +1686,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, n = indx_new(indx, ni, new_vbn, sub_vbn); if (IS_ERR(n)) { err = PTR_ERR(n); - goto out1; + goto out_free_re; } hdr = &n->index->ihdr; @@ -1716,7 +1713,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, put_indx_node(n); fnd_clear(fnd); err = indx_insert_entry(indx, ni, new_de, ctx, fnd); - goto out; + goto out_free_root; } /* @@ -1726,7 +1723,7 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, e = hdr_insert_de(indx, hdr, new_de, NULL, ctx); if (!e) { err = -EINVAL; - goto out1; + goto out_put_n; } fnd_push(fnd, n, e); @@ -1735,12 +1732,11 @@ static int indx_insert_into_root(struct ntfs_index *indx, struct ntfs_inode *ni, n = NULL; -out1: +out_put_n: + put_indx_node(n); +out_free_re: kfree(re); - if (n) - put_indx_node(n); - -out: +out_free_root: kfree(a_root); return err; } |