1*ca0eca91SMax Reitz#!/bin/bash 2*ca0eca91SMax Reitz# 3*ca0eca91SMax Reitz# Test case for image corruption (overlapping data structures) in qcow2 4*ca0eca91SMax Reitz# 5*ca0eca91SMax Reitz# Copyright (C) 2013 Red Hat, Inc. 6*ca0eca91SMax Reitz# 7*ca0eca91SMax Reitz# This program is free software; you can redistribute it and/or modify 8*ca0eca91SMax Reitz# it under the terms of the GNU General Public License as published by 9*ca0eca91SMax Reitz# the Free Software Foundation; either version 2 of the License, or 10*ca0eca91SMax Reitz# (at your option) any later version. 11*ca0eca91SMax Reitz# 12*ca0eca91SMax Reitz# This program is distributed in the hope that it will be useful, 13*ca0eca91SMax Reitz# but WITHOUT ANY WARRANTY; without even the implied warranty of 14*ca0eca91SMax Reitz# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*ca0eca91SMax Reitz# GNU General Public License for more details. 16*ca0eca91SMax Reitz# 17*ca0eca91SMax Reitz# You should have received a copy of the GNU General Public License 18*ca0eca91SMax Reitz# along with this program. If not, see <http://www.gnu.org/licenses/>. 19*ca0eca91SMax Reitz# 20*ca0eca91SMax Reitz 21*ca0eca91SMax Reitz# creator 22*ca0eca91SMax Reitzowner=mreitz@redhat.com 23*ca0eca91SMax Reitz 24*ca0eca91SMax Reitzseq=`basename $0` 25*ca0eca91SMax Reitzecho "QA output created by $seq" 26*ca0eca91SMax Reitz 27*ca0eca91SMax Reitzhere=`pwd` 28*ca0eca91SMax Reitztmp=/tmp/$$ 29*ca0eca91SMax Reitzstatus=1 # failure is the default! 30*ca0eca91SMax Reitz 31*ca0eca91SMax Reitz_cleanup() 32*ca0eca91SMax Reitz{ 33*ca0eca91SMax Reitz _cleanup_test_img 34*ca0eca91SMax Reitz} 35*ca0eca91SMax Reitztrap "_cleanup; exit \$status" 0 1 2 3 15 36*ca0eca91SMax Reitz 37*ca0eca91SMax Reitz# get standard environment, filters and checks 38*ca0eca91SMax Reitz. ./common.rc 39*ca0eca91SMax Reitz. ./common.filter 40*ca0eca91SMax Reitz 41*ca0eca91SMax Reitz# This tests qocw2-specific low-level functionality 42*ca0eca91SMax Reitz_supported_fmt qcow2 43*ca0eca91SMax Reitz_supported_proto generic 44*ca0eca91SMax Reitz_supported_os Linux 45*ca0eca91SMax Reitz 46*ca0eca91SMax Reitzrt_offset=65536 # 0x10000 (XXX: just an assumption) 47*ca0eca91SMax Reitzrb_offset=131072 # 0x20000 (XXX: just an assumption) 48*ca0eca91SMax Reitzl1_offset=196608 # 0x30000 (XXX: just an assumption) 49*ca0eca91SMax Reitzl2_offset=262144 # 0x40000 (XXX: just an assumption) 50*ca0eca91SMax Reitz 51*ca0eca91SMax ReitzIMGOPTS="compat=1.1" 52*ca0eca91SMax Reitz 53*ca0eca91SMax Reitzecho 54*ca0eca91SMax Reitzecho "=== Testing L2 reference into L1 ===" 55*ca0eca91SMax Reitzecho 56*ca0eca91SMax Reitz_make_test_img 64M 57*ca0eca91SMax Reitz# Link first L1 entry (first L2 table) onto itself 58*ca0eca91SMax Reitz# (Note the MSb in the L1 entry is set, ensuring the refcount is one - else any 59*ca0eca91SMax Reitz# later write will result in a COW operation, effectively ruining this attempt 60*ca0eca91SMax Reitz# on image corruption) 61*ca0eca91SMax Reitzpoke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x03\x00\x00" 62*ca0eca91SMax Reitz_check_test_img 63*ca0eca91SMax Reitz 64*ca0eca91SMax Reitz# The corrupt bit should not be set anyway 65*ca0eca91SMax Reitz./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features 66*ca0eca91SMax Reitz 67*ca0eca91SMax Reitz# Try to write something, thereby forcing the corrupt bit to be set 68*ca0eca91SMax Reitz$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io 69*ca0eca91SMax Reitz 70*ca0eca91SMax Reitz# The corrupt bit must now be set 71*ca0eca91SMax Reitz./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features 72*ca0eca91SMax Reitz 73*ca0eca91SMax Reitz# Try to open the image R/W (which should fail) 74*ca0eca91SMax Reitz$QEMU_IO -c "read 0 512" "$TEST_IMG" 2>&1 | _filter_qemu_io | sed -e "s/can't open device .*$/can't open device/" 75*ca0eca91SMax Reitz 76*ca0eca91SMax Reitz# Try to open it RO (which should succeed) 77*ca0eca91SMax Reitz$QEMU_IO -c "read 0 512" -r "$TEST_IMG" | _filter_qemu_io 78*ca0eca91SMax Reitz 79*ca0eca91SMax Reitz# We could now try to fix the image, but this would probably fail (how should an 80*ca0eca91SMax Reitz# L2 table linked onto the L1 table be fixed?) 81*ca0eca91SMax Reitz 82*ca0eca91SMax Reitzecho 83*ca0eca91SMax Reitzecho "=== Testing cluster data reference into refcount block ===" 84*ca0eca91SMax Reitzecho 85*ca0eca91SMax Reitz_make_test_img 64M 86*ca0eca91SMax Reitz# Allocate L2 table 87*ca0eca91SMax Reitztruncate -s "$(($l2_offset+65536))" "$TEST_IMG" 88*ca0eca91SMax Reitzpoke_file "$TEST_IMG" "$l1_offset" "\x80\x00\x00\x00\x00\x04\x00\x00" 89*ca0eca91SMax Reitz# Mark cluster as used 90*ca0eca91SMax Reitzpoke_file "$TEST_IMG" "$(($rb_offset+8))" "\x00\x01" 91*ca0eca91SMax Reitz# Redirect new data cluster onto refcount block 92*ca0eca91SMax Reitzpoke_file "$TEST_IMG" "$l2_offset" "\x80\x00\x00\x00\x00\x02\x00\x00" 93*ca0eca91SMax Reitz_check_test_img 94*ca0eca91SMax Reitz./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features 95*ca0eca91SMax Reitz$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io 96*ca0eca91SMax Reitz./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features 97*ca0eca91SMax Reitz 98*ca0eca91SMax Reitz# Try to fix it 99*ca0eca91SMax Reitz_check_test_img -r all 100*ca0eca91SMax Reitz 101*ca0eca91SMax Reitz# The corrupt bit should be cleared 102*ca0eca91SMax Reitz./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features 103*ca0eca91SMax Reitz 104*ca0eca91SMax Reitz# Look if it's really really fixed 105*ca0eca91SMax Reitz$QEMU_IO -c "write -P 0x2a 0 512" "$TEST_IMG" | _filter_qemu_io 106*ca0eca91SMax Reitz./qcow2.py "$TEST_IMG" dump-header | grep incompatible_features 107*ca0eca91SMax Reitz 108*ca0eca91SMax Reitz# success, all done 109*ca0eca91SMax Reitzecho "*** done" 110*ca0eca91SMax Reitzrm -f $seq.full 111*ca0eca91SMax Reitzstatus=0 112