btrfs-progs: don't write memory after sb to disk
authorZach Brown <zab@redhat.com>
Tue, 22 Jan 2013 23:03:46 +0000 (15:03 -0800)
committerZach Brown <zab@redhat.com>
Wed, 6 Feb 2013 00:09:39 +0000 (16:09 -0800)
struct btrfs_super is about 3.5k but a few writing paths were writing it
out as the full 4k BTRFS_SUPER_INFO_SIZE, leaking a few hundred bytes
after the super_block onto disk.  In practice this meant the memory
after super_copy in struct btrfs_fs_info and whatever came after it in
the heap.

Signed-off-by: Zach Brown <zab@redhat.com>
disk-io.c
volumes.c

index dd06748..eff49da 100644 (file)
--- a/disk-io.c
+++ b/disk-io.c
@@ -983,6 +983,10 @@ int write_dev_supers(struct btrfs_root *root, struct btrfs_super_block *sb,
        u64 bytenr;
        u32 crc;
        int i, ret;
+       void *buf;
+
+       buf = calloc(1, BTRFS_SUPER_INFO_SIZE);
+       BUG_ON(!buf);
 
        if (root->fs_info->super_bytenr != BTRFS_SUPER_INFO_OFFSET) {
                btrfs_set_super_bytenr(sb, root->fs_info->super_bytenr);
@@ -991,10 +995,11 @@ int write_dev_supers(struct btrfs_root *root, struct btrfs_super_block *sb,
                                      BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
                btrfs_csum_final(crc, (char *)&sb->csum[0]);
 
-               ret = pwrite64(device->fd, sb, BTRFS_SUPER_INFO_SIZE,
+               memcpy(buf, sb, sizeof(*sb));
+               ret = pwrite64(device->fd, buf, BTRFS_SUPER_INFO_SIZE,
                               root->fs_info->super_bytenr);
                BUG_ON(ret != BTRFS_SUPER_INFO_SIZE);
-               return 0;
+               goto out;
        }
 
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
@@ -1009,9 +1014,12 @@ int write_dev_supers(struct btrfs_root *root, struct btrfs_super_block *sb,
                                      BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE);
                btrfs_csum_final(crc, (char *)&sb->csum[0]);
 
-               ret = pwrite64(device->fd, sb, BTRFS_SUPER_INFO_SIZE, bytenr);
+               memcpy(buf, sb, sizeof(*sb));
+               ret = pwrite64(device->fd, buf, BTRFS_SUPER_INFO_SIZE, bytenr);
                BUG_ON(ret != BTRFS_SUPER_INFO_SIZE);
        }
+out:
+       free(buf);
        return 0;
 }
 
index 9c52719..65986e1 100644 (file)
--- a/volumes.c
+++ b/volumes.c
@@ -1502,7 +1502,7 @@ int btrfs_read_sys_array(struct btrfs_root *root)
        if (!sb)
                return -ENOMEM;
        btrfs_set_buffer_uptodate(sb);
-       write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
+       write_extent_buffer(sb, super_copy, 0, sizeof(*super_copy));
        array_size = btrfs_super_sys_array_size(super_copy);
 
        /*