diff options
authorIvan Jager <aij+@mrph.org>2014-01-17 15:00:43 +0100
committerChris Mason <clm@fb.com>2014-01-31 08:22:29 -0800
commit0511ca4b502f1cbdd5e92c287d97c8356cdaff66 (patch)
parentef3f6124f0b5e8be126999f27f7f299a6bb3fbf6 (diff)
btrfs-progs: Fix bus error on sparc
Currently, as of 8cae1840afb3ea44dcc298f32983e577480dfee4 when running btrfs-convert I get a bus error. The problem is that struct btrfs_key has __attribute__ ((__packed__)) so it is not aligned. Then, a pointer to it's objectid field is taken, cast to a void*, then eventually cast back to a u64* and dereferenced. The problem is that the dereferenced u64* is not necessarily aligned (ie, not necessarily a valid u64*), resulting in undefined behavior. This patch adds a local u64 variable which would of course be properly aligned and then uses a pointer to that. I did not modify the call from btrfs_fs_roots_compare_roots as that uses struct btrfs_root which is a regular struct and would thus have it's members correctly aligned to begin with. After patching this I realized Liu Bo had already written a similar patch, but I think mine is cleaner, so I'm sending it anyway. Signed-off-by: Ivan Jager <aij+@mrph.org> Signed-off-by: David Sterba <dsterba@suse.cz> Signed-off-by: Chris Mason <clm@fb.com>
1 files changed, 2 insertions, 1 deletions
diff --git a/disk-io.c b/disk-io.c
index e4550bd..e840177 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -683,6 +683,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
struct btrfs_root *root;
struct rb_node *node;
int ret;
+ u64 objectid = location->objectid;
if (location->objectid == BTRFS_ROOT_TREE_OBJECTID)
return fs_info->tree_root;
@@ -698,7 +699,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
BUG_ON(location->objectid == BTRFS_TREE_RELOC_OBJECTID ||
location->offset != (u64)-1);
- node = rb_search(&fs_info->fs_root_tree, (void *)&location->objectid,
+ node = rb_search(&fs_info->fs_root_tree, (void *)&objectid,
btrfs_fs_roots_compare_objectids, NULL);
if (node)
return container_of(node, struct btrfs_root, rb_node);