Discs must be sized in multiples of 512 bytes or odd things happen
In #36 some of the odd errors were due to seeks beyond the end of the disc. This was because the disc was "specially crafted" to be 25GB + 1 byte, which doesn't fit into the normal 512 byte sectors expected of a disc. This lead to reads going beyond the end of the disc etc. If a similarly evil disc is used with `losetup`, it just ignores the last bytes of the disc that don't fit into 512 chunks. This is what that patch does, logging an error at the same time.
This commit is contained in:
@@ -97,6 +97,15 @@ int open_and_mmap(const char* filename, int* out_fd, uint64_t *out_size, void **
|
|||||||
warn("lseek64() failed");
|
warn("lseek64() failed");
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If discs are not in multiples of 512, then odd things happen,
|
||||||
|
* resulting in reads/writes past the ends of files.
|
||||||
|
*/
|
||||||
|
if ( size != (size & (~0x1ff))) {
|
||||||
|
warn("file does not fit into 512-byte sectors; the end of the file will be ignored.");
|
||||||
|
size = size & (~0x1ff);
|
||||||
|
}
|
||||||
|
|
||||||
if (out_size) {
|
if (out_size) {
|
||||||
*out_size = size;
|
*out_size = size;
|
||||||
}
|
}
|
||||||
|
@@ -710,6 +710,15 @@ void serve_init_allocation_map(struct server* params)
|
|||||||
|
|
||||||
FATAL_IF_NEGATIVE(fd, "Couldn't open %s", params->filename );
|
FATAL_IF_NEGATIVE(fd, "Couldn't open %s", params->filename );
|
||||||
size = lseek64( fd, 0, SEEK_END );
|
size = lseek64( fd, 0, SEEK_END );
|
||||||
|
|
||||||
|
/* If discs are not in multiples of 512, then odd things happen,
|
||||||
|
* resulting in reads/writes past the ends of files.
|
||||||
|
*/
|
||||||
|
if ( size != (size & ~0x1ff)) {
|
||||||
|
warn("file does not fit into 512-byte sectors; the end of the file will be ignored.");
|
||||||
|
size &= ~0x1ff;
|
||||||
|
}
|
||||||
|
|
||||||
params->size = size;
|
params->size = size;
|
||||||
FATAL_IF_NEGATIVE( size, "Couldn't find size of %s",
|
FATAL_IF_NEGATIVE( size, "Couldn't find size of %s",
|
||||||
params->filename );
|
params->filename );
|
||||||
|
@@ -195,4 +195,18 @@ class TestServeMode < Test::Unit::TestCase
|
|||||||
assert_equal 6, op.first[3], 'msync called with incorrect flags'
|
assert_equal 6, op.first[3], 'msync called with incorrect flags'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_odd_size_discs_are_truncated_to_nearest_512
|
||||||
|
# This should get rounded down to 1024
|
||||||
|
@env.blocksize = 1024 + 511
|
||||||
|
@env.writefile1('0')
|
||||||
|
@env.serve1
|
||||||
|
client = FlexNBD::FakeSource.new(@env.ip, @env.port1, 'Connecting to server failed')
|
||||||
|
begin
|
||||||
|
result = client.read_hello
|
||||||
|
assert_equal 'NBDMAGIC', result[:passwd]
|
||||||
|
assert_equal 0x00420281861253, result[:magic]
|
||||||
|
assert_equal 1024, result[:size]
|
||||||
|
client.close
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user