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
This commit is contained in:
Pawel Jakub Dawidek 2011-10-19 23:44:38 +00:00
parent 8565a6f600
commit 81fdf04870
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=226553
2 changed files with 11 additions and 11 deletions

View File

@ -347,7 +347,7 @@ vdev_read_phys(vdev_t *vdev, const blkptr_t *bp, void *buf,
rc = vdev->v_phys_read(vdev, vdev->v_read_priv, offset, buf, psize);
if (rc)
return (rc);
if (bp && zio_checksum_error(bp, buf, offset))
if (bp && zio_checksum_verify(bp, buf, offset, psize))
return (EIO);
return (0);

View File

@ -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 @@ vdev_raidz_read(vdev_t *vd, const blkptr_t *bp, void *data,
*/
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 @@ vdev_raidz_read(vdev_t *vd, const blkptr_t *bp, void *data,
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 @@ vdev_raidz_read(vdev_t *vd, const blkptr_t *bp, void *data,
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