summaryrefslogtreecommitdiff
path: root/disk-io.c
diff options
context:
space:
mode:
authorZach Brown <zab@redhat.com>2013-01-22 15:03:46 -0800
committerZach Brown <zab@redhat.com>2013-02-05 16:09:39 -0800
commit7d365c5a87cdb542c204086b4d1d7aa00cd7b09f (patch)
tree7a205be4ba3348d6d576f35482fbd9912eeebe65 /disk-io.c
parentfd732dd81a698c90387a3611134e5fffec07411b (diff)
btrfs-progs: don't write memory after sb to disk
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>
Diffstat (limited to 'disk-io.c')
-rw-r--r--disk-io.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/disk-io.c b/disk-io.c
index dd06748b..eff49dac 100644
--- 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;
}