summaryrefslogtreecommitdiffstats
path: root/sys/cddl
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2011-10-19 23:44:38 +0000
committerpjd <pjd@FreeBSD.org>2011-10-19 23:44:38 +0000
commit2b80d6e6ddf9cf57a225d67c5555f73a2563b7e0 (patch)
tree32d4394f30f465c747e129c06c3164327e59f494 /sys/cddl
parent5418d81b3820c4a900f2188badcafc9868750457 (diff)
downloadFreeBSD-src-2b80d6e6ddf9cf57a225d67c5555f73a2563b7e0.zip
FreeBSD-src-2b80d6e6ddf9cf57a225d67c5555f73a2563b7e0.tar.gz
Always pass data size for checksum verification function, as using
physical block size declared in bp may not always be what we want. For example in case of gang block header physical block size declared in bp is much larger than SPA_GANGBLOCKSIZE (512 bytes) and checksum calculation failed. This bug could lead to accessing unallocated memory and resets/failures during boot. MFC after: 3 days
Diffstat (limited to 'sys/cddl')
-rw-r--r--sys/cddl/boot/zfs/zfssubr.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/sys/cddl/boot/zfs/zfssubr.c b/sys/cddl/boot/zfs/zfssubr.c
index 1d655c0..49cb025 100644
--- a/sys/cddl/boot/zfs/zfssubr.c
+++ b/sys/cddl/boot/zfs/zfssubr.c
@@ -181,10 +181,10 @@ zio_checksum_label_verifier(zio_cksum_t *zcp, uint64_t offset)
}
static int
-zio_checksum_error(const blkptr_t *bp, void *data, uint64_t offset)
+zio_checksum_verify(const blkptr_t *bp, void *data, uint64_t offset,
+ uint64_t size)
{
unsigned int checksum = BP_IS_GANG(bp) ? ZIO_CHECKSUM_GANG_HEADER : BP_GET_CHECKSUM(bp);
- uint64_t size = BP_GET_PSIZE(bp);
zio_checksum_info_t *ci;
zio_cksum_t actual_cksum, expected_cksum, verifier;
int byteswap;
@@ -1240,10 +1240,10 @@ vdev_child(vdev_t *pvd, uint64_t devidx)
* any ereports we generate can note it.
*/
static int
-raidz_checksum_verify(const blkptr_t *bp, void *data)
+raidz_checksum_verify(const blkptr_t *bp, void *data, uint64_t size)
{
- return (zio_checksum_error(bp, data, 0));
+ return (zio_checksum_verify(bp, data, 0, size));
}
/*
@@ -1293,7 +1293,7 @@ raidz_parity_verify(raidz_map_t *rm)
*/
static int
vdev_raidz_combrec(raidz_map_t *rm, const blkptr_t *bp, void *data,
- off_t offset, int total_errors, int data_errors)
+ off_t offset, uint64_t bytes, int total_errors, int data_errors)
{
raidz_col_t *rc;
void *orig[VDEV_RAIDZ_MAXPARITY];
@@ -1372,7 +1372,7 @@ vdev_raidz_combrec(raidz_map_t *rm, const blkptr_t *bp, void *data,
* success.
*/
code = vdev_raidz_reconstruct(rm, tgts, n);
- if (raidz_checksum_verify(bp, data) == 0) {
+ if (raidz_checksum_verify(bp, data, bytes) == 0) {
for (i = 0; i < n; i++) {
c = tgts[i];
rc = &rm->rm_col[c];
@@ -1543,7 +1543,7 @@ reconstruct:
*/
if (total_errors <= rm->rm_firstdatacol - parity_untried) {
if (data_errors == 0) {
- if (raidz_checksum_verify(bp, data) == 0) {
+ if (raidz_checksum_verify(bp, data, bytes) == 0) {
/*
* If we read parity information (unnecessarily
* as it happens since no reconstruction was
@@ -1588,7 +1588,7 @@ reconstruct:
code = vdev_raidz_reconstruct(rm, tgts, n);
- if (raidz_checksum_verify(bp, data) == 0) {
+ if (raidz_checksum_verify(bp, data, bytes) == 0) {
/*
* If we read more parity disks than were used
* for reconstruction, confirm that the other
@@ -1662,8 +1662,8 @@ reconstruct:
if (total_errors > rm->rm_firstdatacol) {
error = EIO;
} else if (total_errors < rm->rm_firstdatacol &&
- (code = vdev_raidz_combrec(rm, bp, data, offset, total_errors,
- data_errors)) != 0) {
+ (code = vdev_raidz_combrec(rm, bp, data, offset, bytes,
+ total_errors, data_errors)) != 0) {
/*
* If we didn't use all the available parity for the
* combinatorial reconstruction, verify that the remaining
OpenPOWER on IntegriCloud