From patchwork Fri Jan 17 02:22:57 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Jager X-Patchwork-Id: 3501671 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id E72659F32F for ; Fri, 17 Jan 2014 02:23:05 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DAE2820172 for ; Fri, 17 Jan 2014 02:23:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C711F2014A for ; Fri, 17 Jan 2014 02:23:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751937AbaAQCXA (ORCPT ); Thu, 16 Jan 2014 21:23:00 -0500 Received: from mail-wi0-f182.google.com ([209.85.212.182]:50103 "EHLO mail-wi0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751667AbaAQCW7 (ORCPT ); Thu, 16 Jan 2014 21:22:59 -0500 Received: by mail-wi0-f182.google.com with SMTP id ex4so124919wid.9 for ; Thu, 16 Jan 2014 18:22:57 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:sender:date:message-id:subject:from :to:content-type; bh=fIyj26ahfEd0q7DAwIcKPXwY/cgBZtZTWCWYvBrLW1Y=; b=d0ebnroGl+s9/SH+jmFcJh9sWzLFJa1ZRPTCpbsDWvzY6hdfYiQGRjiHW0L2+NSmUN JoIjewvzGkBSivopLF8qnDrDUSlcL9Ol0yneLIP15NNQtZn24yjzoT5rWH1CZcwQ0InA 9x2yfKyW5QGjXWmIFNNtp4PLMqIWQO4xkKnt7hU12Zajb0+BwqTGjM4oty+bayhZvhjv NuR3jSTUkjuqVehnb4WI/N76s7FbXB3ik8NWIbhSyDNZSjCzLvikPmLVkA7gL7wbzYaN 6njuJ2Hl6GBiGmwmgQw+K04BPp1p9cBC2ToPBfU1q9i4bPx56+VFIziTBZWD4DEn3J4L CTSg== X-Gm-Message-State: ALoCoQn3MNFJBAIKMsVv0QrmqrB0SV6dIoj6Z5F0EcaV5E1MbvQQcGmRfyZNWTKQr3fL/zw5guOi MIME-Version: 1.0 X-Received: by 10.194.143.40 with SMTP id sb8mr6165810wjb.15.1389925377493; Thu, 16 Jan 2014 18:22:57 -0800 (PST) Received: by 10.194.176.66 with HTTP; Thu, 16 Jan 2014 18:22:57 -0800 (PST) X-Originating-IP: [96.235.34.22] Date: Thu, 16 Jan 2014 21:22:57 -0500 X-Google-Sender-Auth: 6KV-JxPLYPBeCvKLgR_8oOcJgiI Message-ID: Subject: [PATCH] Btrfs-progs: Fix bus error on sparc From: Ivan Jager To: linux-btrfs@vger.kernel.org Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-7.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_TVD_MIME_EPI, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hello, 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. If you like, I could also change the location->objectid references between my two changes, which would make the patch bigger, but would make it actually reduce the overall code size slightly. Feel free to make or request any necessary style changes as I couldn't find documentation on the coding style for btrfs-tools. Please CC me as I'm not on the list. Thanks, Ivan PS: Here is the gdb output in case anyone is interested. ivan@chacoi:~/src/btrfs-progs$ gdb ./btrfs-convert GNU gdb (GDB) 7.6.1 (Debian 7.6.1-1) Copyright (C) 2013 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "sparc-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /home/ivan/src/btrfs-progs/btrfs-convert...done. (gdb) run ../e4.img Starting program: /home/ivan/src/btrfs-progs/./btrfs-convert ../e4.img [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/sparc-linux-gnu/libthread_db.so.1". Program received signal SIGBUS, Bus error. btrfs_fs_roots_compare_objectids (node=0x7ab00, data=0xffffd1fb) at disk-io.c:656 656 u64 objectid = *((u64 *)data); (gdb) bt #0 btrfs_fs_roots_compare_objectids (node=0x7ab00, data=0xffffd1fb) at disk-io.c:656 #1 0x0004d964 in rb_search (root=, key=0xffffd1fb, comp=0x1ae24 , next_ret=0x0) at rbtree.c:425 #2 0x0001e048 in btrfs_read_fs_root (fs_info=0x78be0, location=0xffffd1fb) at disk-io.c:698 #3 0x00046244 in create_subvol (trans=0x7adc8, root=0x7a8e0, root_objectid=256) at btrfs-convert.c:1583 #4 0x00048eb8 in init_btrfs (root=0x7a8e0) at btrfs-convert.c:1631 #5 do_convert (devname=0xffffd935 "../e4.img", datacsum=1, packing=1, noxattr=0) at btrfs-convert.c:2275 #6 0x0004cfcc in main (argc=1, argv=0xffffd814) at btrfs-convert.c:2743 (gdb) frame 3 #3 0x00046244 in create_subvol (trans=0x7adc8, root=0x7a8e0, root_objectid=256) at btrfs-convert.c:1583 1583 new_root = btrfs_read_fs_root(root->fs_info, &key); (gdb) print &key $1 = (struct btrfs_key *) 0xffffd1fb diff --git a/disk-io.c b/disk-io.c index 0af3898..a995b52 100644 --- a/disk-io.c +++ b/disk-io.c @@ -680,6 +680,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; @@ -695,7 +696,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);