From 2eccaef52dab614a753aba8029714fe5424c26e1 Mon Sep 17 00:00:00 2001 From: Tomohiro Kusumi Date: Sun, 4 Dec 2016 18:57:15 +0900 Subject: [PATCH] sbin/hammer: Add hammer strip command This command is inspired by hammer recover command, and does opposite of what recover command does. This command zero clears zone-8(B-Tree) big-blocks, zone-9(meta) big-blocks, and then the whole volume header, except that volume signature field is overwritten with "STRIPPED" instead of zeros. After running, a filesystem is no longer mountable or recoverable with hammer recover command. This command is also fast as it only zero clears good enough ondisk data to make it unmountable and unrecoverable. Keep in mind that this command does _not_ zero clear user data. Users would normally use a software designed to completely shred a filesystem. This command is not designed to shred a filesystem. The name "strip" gives better idea of what it really does than using "shred"/etc. -- example # newfs_hammer -L TEST /dev/da1 /dev/da2 /dev/da3 > /dev/null # mount_hammer /dev/da1:/dev/da2:/dev/da3 /HAMMER # cd /HAMMER # dd if=/dev/urandom of=./out bs=1M count=120000 120000+0 records in 120000+0 records out 125829120000 bytes transferred in 1766.417077 secs (71234094 bytes/sec) # cd # umount /HAMMER # hammer -f /dev/da1:/dev/da2:/dev/da3 strip You have requested that HAMMER filesystem (TEST) be stripped Do you really want to do this? [y/n] y Stripping HAMMER filesystem (TEST) in 5 4 3 2 1.. starting destruction pass 8000000021000000 9000000021800000 800000019c000000 800000030c000000 800000047e000000 80000005f7000000 8000000767000000 80000008d8000000 8000000a51800000 8000000bc5000000 8000000d37800000 8000000ead000000 800000101e800000 8000001193000000 8000001304000000 8000001478800000 80000015ee000000 8000001760800000 80000018d1800000 8000001a47000000 8000001bb6000000 801000013c000000 /dev/da1 /dev/da2 /dev/da3 # mount_hammer /dev/da1:/dev/da2:/dev/da3 /HAMMER mount: Invalid argument mount_hammer: /dev/da1: Invalid volume signature 4445505049525453 --- sbin/hammer/Makefile | 3 +- sbin/hammer/cmd_strip.c | 181 +++++++++++++++++++++++++++++++++++++++++ sbin/hammer/hammer.8 | 27 +++++- sbin/hammer/hammer.c | 7 ++ sbin/hammer/hammer.h | 1 + sys/vfs/hammer/hammer_ondisk.c | 4 +- 6 files changed, 219 insertions(+), 4 deletions(-) create mode 100644 sbin/hammer/cmd_strip.c diff --git a/sbin/hammer/Makefile b/sbin/hammer/Makefile index 54361cb7ca..ea119a2933 100644 --- a/sbin/hammer/Makefile +++ b/sbin/hammer/Makefile @@ -5,7 +5,8 @@ SRCS= hammer.c ondisk.c blockmap.c cache.c misc.c cycle.c \ cmd_synctid.c cmd_stats.c cmd_remote.c \ cmd_pfs.c cmd_snapshot.c cmd_mirror.c \ cmd_cleanup.c cmd_info.c cmd_version.c cmd_volume.c \ - cmd_config.c cmd_recover.c cmd_dedup.c cmd_abort.c + cmd_config.c cmd_recover.c cmd_dedup.c cmd_abort.c \ + cmd_strip.c MAN= hammer.8 CFLAGS+= -I${.CURDIR}/../../sys diff --git a/sbin/hammer/cmd_strip.c b/sbin/hammer/cmd_strip.c new file mode 100644 index 0000000000..7512396040 --- /dev/null +++ b/sbin/hammer/cmd_strip.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2007-2016 The DragonFly Project. All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Matthew Dillon + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "hammer.h" + +static void hammer_strip_bigblock(int zone, hammer_off_t offset); +static void hammer_ask_yn(void); + +void +hammer_cmd_strip(void) +{ + struct volume_info *vol; + hammer_blockmap_t rootmap; + hammer_blockmap_layer1_t layer1; + hammer_blockmap_layer2_t layer2; + struct buffer_info *buffer1 = NULL; + struct buffer_info *buffer2 = NULL; + hammer_off_t layer1_offset; + hammer_off_t layer2_offset; + hammer_off_t phys_offset; + hammer_off_t block_offset; + hammer_off_t offset; + int i, zone = HAMMER_ZONE_FREEMAP_INDEX; + + hammer_ask_yn(); + + vol = get_root_volume(); + rootmap = &vol->ondisk->vol0_blockmap[zone]; + assert(rootmap->phys_offset != 0); + + for (phys_offset = HAMMER_ZONE_ENCODE(zone, 0); + phys_offset < HAMMER_ZONE_ENCODE(zone, HAMMER_OFF_LONG_MASK); + phys_offset += HAMMER_BLOCKMAP_LAYER2) { + /* + * Dive layer 1. + */ + layer1_offset = rootmap->phys_offset + + HAMMER_BLOCKMAP_LAYER1_OFFSET(phys_offset); + layer1 = get_buffer_data(layer1_offset, &buffer1, 0); + + if (layer1->phys_offset == HAMMER_BLOCKMAP_UNAVAIL) + continue; + + for (block_offset = 0; + block_offset < HAMMER_BLOCKMAP_LAYER2; + block_offset += HAMMER_BIGBLOCK_SIZE) { + offset = phys_offset + block_offset; + /* + * Dive layer 2, each entry represents a big-block. + */ + layer2_offset = layer1->phys_offset + + HAMMER_BLOCKMAP_LAYER2_OFFSET(block_offset); + layer2 = get_buffer_data(layer2_offset, &buffer2, 0); + + if (layer2->zone == HAMMER_ZONE_BTREE_INDEX || + layer2->zone == HAMMER_ZONE_META_INDEX) { + hammer_strip_bigblock(layer2->zone, offset); + layer2->zone = HAMMER_ZONE_UNAVAIL_INDEX; + layer2->append_off = HAMMER_BIGBLOCK_SIZE; + layer2->bytes_free = 0; + hammer_crc_set_layer2(layer2); + buffer2->cache.modified = 1; + } else if (layer2->zone == HAMMER_ZONE_UNAVAIL_INDEX) { + break; + } + } + } + rel_buffer(buffer1); + rel_buffer(buffer2); + + for (i = 0; i < HAMMER_MAX_VOLUMES; i++) { + vol = get_volume(i); + if (vol) { + printf("%s\n", vol->name); + bzero(vol->ondisk, sizeof(*vol->ondisk)); + memcpy(&vol->ondisk->vol_signature, "STRIPPED", 8); + } + } + + flush_all_volumes(); +} + +static void +hammer_strip_bigblock(int zone, hammer_off_t offset) +{ + struct buffer_info *buffer = NULL; + int i; + + assert(hammer_is_zone2_mapped_index(zone)); + assert((offset & HAMMER_BIGBLOCK_MASK64) == 0); + assert((offset & HAMMER_BUFMASK) == 0); + offset = hammer_xlate_to_zoneX(zone, offset); + + /* + * This format is taken from hammer blockmap. + */ + if (VerboseOpt) { + printf("%016jx zone=%-2d vol=%-3d L1#=%-6d L2#=%-6d L1=%-7lu L2=%-7lu\n", + offset, + zone, + HAMMER_VOL_DECODE(offset), + HAMMER_BLOCKMAP_LAYER1_INDEX(offset), + HAMMER_BLOCKMAP_LAYER2_INDEX(offset), + HAMMER_BLOCKMAP_LAYER1_OFFSET(offset), + HAMMER_BLOCKMAP_LAYER2_OFFSET(offset)); + } else { + printf("%016jx\n", offset); + } + + for (i = 0; i < HAMMER_BIGBLOCK_SIZE; i += HAMMER_BUFSIZE) { + get_buffer_data(offset + i, &buffer, 1); + assert(buffer); + } +} + +static void +hammer_ask_yn(void) +{ + struct volume_info *vol; + int i; + + vol = get_root_volume(); + + /* + * This format is taken from hammer pfs-destroy. + */ + printf("You have requested that HAMMER filesystem (%s) be stripped\n", + vol->ondisk->vol_label); + printf("Do you really want to do this? [y/n] "); + fflush(stdout); + + if (getyn() == 0) { + fprintf(stderr, "No action taken\n"); + exit(1); + } + + printf("Stripping HAMMER filesystem (%s)", vol->ondisk->vol_label); + + if (DebugOpt) { + printf("\n"); + } else { + printf(" in"); + for (i = 5; i; --i) { + printf(" %d", i); + fflush(stdout); + sleep(1); + } + printf(".. starting destruction pass\n"); + } +} diff --git a/sbin/hammer/hammer.8 b/sbin/hammer/hammer.8 index 089dbb1cf9..338cb61cae 100644 --- a/sbin/hammer/hammer.8 +++ b/sbin/hammer/hammer.8 @@ -30,7 +30,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd April 9, 2016 +.Dd December 4, 2016 .Dt HAMMER 8 .Os .Sh NAME @@ -492,6 +492,31 @@ recovering data from a dead filesystem. This command needs the .Fl f Ar blkdevs option. +.\" ==== strip ==== +.It Cm strip +Strip +.Nm HAMMER +filesystem volume header and other meta-data by overwriting them with irrelevant data. +.Nm HAMMER +volumes need to be unmounted. +.Pp +This is a fast way to make +.Nm HAMMER +filesystem unmountable and unrecoverable. +After running this command, +.Nm HAMMER +filesystem data is no longer recoverable using +.Cm recover +command, although the data still exists within the +.Nm HAMMER +volumes. +As safety measure the +.Fl y +flag have no effect on this directive. +.Pp +This command needs the +.Fl f Ar blkdevs +option. .\" ==== namekey1 ==== .It Cm namekey1 Ar filename Generate a diff --git a/sbin/hammer/hammer.c b/sbin/hammer/hammer.c index be8f9a1b47..b30683d926 100644 --- a/sbin/hammer/hammer.c +++ b/sbin/hammer/hammer.c @@ -552,6 +552,12 @@ main(int ac, char **av) hammer_cmd_checkmap(); exit(0); } + if (strcmp(av[0], "strip") == 0) { + hammer_parsedevs(blkdevs, O_RDWR); + hammer_cmd_strip(); + exit(0); + } + usage(1); /* not reached */ return(0); @@ -712,6 +718,7 @@ usage(int exit_code) "hammer -f blkdevs [-qqq] show [lo:objid]\n" "hammer -f blkdevs show-undo\n" "hammer -f blkdevs recover \n" + "hammer -f blkdevs strip\n" ); fprintf(stderr, "\nHAMMER utility version 5+ commands:\n"); diff --git a/sbin/hammer/hammer.h b/sbin/hammer/hammer.h index a9ad333a04..a16cc2e91e 100644 --- a/sbin/hammer/hammer.h +++ b/sbin/hammer/hammer.h @@ -137,6 +137,7 @@ void hammer_cmd_volume_blkdevs(char **av, int ac); void hammer_cmd_dedup_simulate(char **av, int ac); void hammer_cmd_dedup(char **av, int ac); void hammer_cmd_abort_cleanup(char **av, int ac); +void hammer_cmd_strip(void); void hammer_get_cycle(hammer_base_elm_t base, hammer_tid_t *tidp); void hammer_set_cycle(hammer_base_elm_t base, hammer_tid_t tid); diff --git a/sys/vfs/hammer/hammer_ondisk.c b/sys/vfs/hammer/hammer_ondisk.c index 83db7bc6f9..a0193f54a7 100644 --- a/sys/vfs/hammer/hammer_ondisk.c +++ b/sys/vfs/hammer/hammer_ondisk.c @@ -188,8 +188,8 @@ hammer_install_volume(hammer_mount_t hmp, const char *volname, if (ronly == 0 && data) { img = (hammer_volume_ondisk_t)data; if (ondisk->vol_signature == HAMMER_FSBUF_VOLUME) { - hkprintf("Formatting of valid HAMMER volume " - "%s denied. Erase with dd!\n", volname); + hkprintf("Formatting of valid HAMMER volume %s denied. " + "Erase with hammer strip or dd!\n", volname); error = EFTYPE; goto late_failure; } -- 2.11.4.GIT