summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.h
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2014-11-09 03:38:39 -0500
committerChris Mason <clm@fb.com>2014-11-20 20:20:07 -0500
commit5f5bc6b1e2d5a6f827bc860ef2dc5b6f365d1339 (patch)
treed17afbf1a528b003f34d43cf557d2da62a7a6b1b /fs/btrfs/ctree.h
parentc7bc6319c59cc791743cf1b6e98f86be69444495 (diff)
Btrfs: make xattr replace operations atomic
Replacing a xattr consists of doing a lookup for its existing value, delete the current value from the respective leaf, release the search path and then finally insert the new value. This leaves a time window where readers (getxattr, listxattrs) won't see any value for the xattr. Xattrs are used to store ACLs, so this has security implications. This change also fixes 2 other existing issues which were: *) Deleting the old xattr value without verifying first if the new xattr will fit in the existing leaf item (in case multiple xattrs are packed in the same item due to name hash collision); *) Returning -EEXIST when the flag XATTR_CREATE is given and the xattr doesn't exist but we have have an existing item that packs muliple xattrs with the same name hash as the input xattr. In this case we should return ENOSPC. A test case for xfstests follows soon. Thanks to Alexandre Oliva for reporting the non-atomicity of the xattr replace implementation. Reported-by: Alexandre Oliva <oliva@gnu.org> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/ctree.h')
-rw-r--r--fs/btrfs/ctree.h5
1 files changed, 5 insertions, 0 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index fa14081e3383..a9466e346358 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -607,6 +607,7 @@ struct btrfs_path {
607 unsigned int leave_spinning:1; 607 unsigned int leave_spinning:1;
608 unsigned int search_commit_root:1; 608 unsigned int search_commit_root:1;
609 unsigned int need_commit_sem:1; 609 unsigned int need_commit_sem:1;
610 unsigned int skip_release_on_error:1;
610}; 611};
611 612
612/* 613/*
@@ -3690,6 +3691,10 @@ struct btrfs_dir_item *btrfs_lookup_xattr(struct btrfs_trans_handle *trans,
3690int verify_dir_item(struct btrfs_root *root, 3691int verify_dir_item(struct btrfs_root *root,
3691 struct extent_buffer *leaf, 3692 struct extent_buffer *leaf,
3692 struct btrfs_dir_item *dir_item); 3693 struct btrfs_dir_item *dir_item);
3694struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
3695 struct btrfs_path *path,
3696 const char *name,
3697 int name_len);
3693 3698
3694/* orphan.c */ 3699/* orphan.c */
3695int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans, 3700int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans,