Skip to contentSkip to conversation

Patch "Btrfs: make xattr replace operations atomic" has been added to the 3.10-stable tree

PATCH [email protected] 1 participant 1 message Jun 30, 2015

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer Applied
#0 lore raw

This is a note to let you know that I've just added the patch titled

Btrfs: make xattr replace operations atomic

to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
btrfs-make-xattr-replace-operations-atomic.patch
and it can be found in the queue-3.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

Quoted 1 line

From 5f5bc6b1e2d5a6f827bc860ef2dc5b6f365d1339 Mon Sep 17 00:00:00 2001

From: Filipe Manana <[email protected]>
Date: Sun, 9 Nov 2014 08:38:39 +0000
Subject: Btrfs: make xattr replace operations atomic

From: Filipe Manana <[email protected]>

commit 5f5bc6b1e2d5a6f827bc860ef2dc5b6f365d1339 upstream.

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.

[shengyong: backport to 3.10
- FIX: CVE-2014-9710
- adjust context
- ASSERT() was added v3.12, so we do check with if statement
- set the first parameter of btrfs_item_nr() as NULL, because it is not used, and is removed in v3.13
]

---
 fs/btrfs/ctree.c    |    2 
 fs/btrfs/ctree.h    |    5 +
 fs/btrfs/dir-item.c |   10 ---
 fs/btrfs/xattr.c    |  159 +++++++++++++++++++++++++++++++++-------------------
 4 files changed, 111 insertions(+), 65 deletions(-)
fs/btrfs/ctree.c +1 -1
@@ -2769,7 +2769,7 @@ done:
 	 */
 	if (!p->leave_spinning)
 		btrfs_set_path_blocking(p);
-	if (ret < 0)
+	if (ret < 0 && !p->skip_release_on_error)
 		btrfs_release_path(p);
 	return ret;
 }
fs/btrfs/ctree.h +5 -0
@@ -586,6 +586,7 @@ struct btrfs_path {
 	unsigned int skip_locking:1;
 	unsigned int leave_spinning:1;
 	unsigned int search_commit_root:1;
+	unsigned int skip_release_on_error:1;
 };
 
 /*
@@ -3406,6 +3407,10 @@ struct btrfs_dir_item *btrfs_lookup_xatt
 int verify_dir_item(struct btrfs_root *root,
 		    struct extent_buffer *leaf,
 		    struct btrfs_dir_item *dir_item);
+struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
+						 struct btrfs_path *path,
+						 const char *name,
+						 int name_len);
 
 /* orphan.c */
 int btrfs_insert_orphan_item(struct btrfs_trans_handle *trans,
fs/btrfs/dir-item.c +3 -7
@@ -21,10 +21,6 @@
 #include "hash.h"
 #include "transaction.h"
 
-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
-			      struct btrfs_path *path,
-			      const char *name, int name_len);
-
 /*
  * insert a name into a directory, doing overflow properly if there is a hash
  * collision.  data_size indicates how big the item inserted should be.  On
@@ -383,9 +379,9 @@ struct btrfs_dir_item *btrfs_lookup_xatt
  * this walks through all the entries in a dir item and finds one
  * for a specific name.
  */
-static struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
-			      struct btrfs_path *path,
-			      const char *name, int name_len)
+struct btrfs_dir_item *btrfs_match_dir_item_name(struct btrfs_root *root,
+						 struct btrfs_path *path,
+						 const char *name, int name_len)
 {
 	struct btrfs_dir_item *dir_item;
 	unsigned long name_ptr;
fs/btrfs/xattr.c +102 -57

199 lines not on this page · raw message

Patches currently in stable-queue which might be from [email protected] are

queue-3.10/btrfs-make-xattr-replace-operations-atomic.patch