aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@gmail.com>2014-06-29 16:45:40 -0400
committerChris Mason <clm@fb.com>2014-07-03 10:04:10 -0400
commit14f5979633a67de81b9bd4a36a0eb99125728f9b (patch)
tree3a54c65611af64935341b49dd1d113f182a5d54e /fs
parent0aeb8a6e67cddeac1d42cf64795fde0641a1cffb (diff)
Btrfs: fix use-after-free when cloning a trailing file hole
The transaction handle was being used after being freed. Cc: Chris Mason <clm@fb.com> Signed-off-by: Filipe David Borba Manana <fdmanana@gmail.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ioctl.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 02dc64bbf1cb..2a99f4987bb1 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -3142,7 +3142,6 @@ out:
3142static void clone_update_extent_map(struct inode *inode, 3142static void clone_update_extent_map(struct inode *inode,
3143 const struct btrfs_trans_handle *trans, 3143 const struct btrfs_trans_handle *trans,
3144 const struct btrfs_path *path, 3144 const struct btrfs_path *path,
3145 struct btrfs_file_extent_item *fi,
3146 const u64 hole_offset, 3145 const u64 hole_offset,
3147 const u64 hole_len) 3146 const u64 hole_len)
3148{ 3147{
@@ -3157,7 +3156,11 @@ static void clone_update_extent_map(struct inode *inode,
3157 return; 3156 return;
3158 } 3157 }
3159 3158
3160 if (fi) { 3159 if (path) {
3160 struct btrfs_file_extent_item *fi;
3161
3162 fi = btrfs_item_ptr(path->nodes[0], path->slots[0],
3163 struct btrfs_file_extent_item);
3161 btrfs_extent_item_to_extent_map(inode, path, fi, false, em); 3164 btrfs_extent_item_to_extent_map(inode, path, fi, false, em);
3162 em->generation = -1; 3165 em->generation = -1;
3163 if (btrfs_file_extent_type(path->nodes[0], fi) == 3166 if (btrfs_file_extent_type(path->nodes[0], fi) ==
@@ -3511,18 +3514,15 @@ process_slot:
3511 btrfs_item_ptr_offset(leaf, slot), 3514 btrfs_item_ptr_offset(leaf, slot),
3512 size); 3515 size);
3513 inode_add_bytes(inode, datal); 3516 inode_add_bytes(inode, datal);
3514 extent = btrfs_item_ptr(leaf, slot,
3515 struct btrfs_file_extent_item);
3516 } 3517 }
3517 3518
3518 /* If we have an implicit hole (NO_HOLES feature). */ 3519 /* If we have an implicit hole (NO_HOLES feature). */
3519 if (drop_start < new_key.offset) 3520 if (drop_start < new_key.offset)
3520 clone_update_extent_map(inode, trans, 3521 clone_update_extent_map(inode, trans,
3521 path, NULL, drop_start, 3522 NULL, drop_start,
3522 new_key.offset - drop_start); 3523 new_key.offset - drop_start);
3523 3524
3524 clone_update_extent_map(inode, trans, path, 3525 clone_update_extent_map(inode, trans, path, 0, 0);
3525 extent, 0, 0);
3526 3526
3527 btrfs_mark_buffer_dirty(leaf); 3527 btrfs_mark_buffer_dirty(leaf);
3528 btrfs_release_path(path); 3528 btrfs_release_path(path);
@@ -3565,12 +3565,10 @@ process_slot:
3565 btrfs_end_transaction(trans, root); 3565 btrfs_end_transaction(trans, root);
3566 goto out; 3566 goto out;
3567 } 3567 }
3568 clone_update_extent_map(inode, trans, NULL, last_dest_end,
3569 destoff + len - last_dest_end);
3568 ret = clone_finish_inode_update(trans, inode, destoff + len, 3570 ret = clone_finish_inode_update(trans, inode, destoff + len,
3569 destoff, olen); 3571 destoff, olen);
3570 if (ret)
3571 goto out;
3572 clone_update_extent_map(inode, trans, path, NULL, last_dest_end,
3573 destoff + len - last_dest_end);
3574 } 3572 }
3575 3573
3576out: 3574out: