Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1a880a9 authored by Sami Tolvanen's avatar Sami Tolvanen Committed by Mike Snitzer
Browse files

dm verity fec: limit error correction recursion



If the hash tree itself is sufficiently corrupt in addition to data blocks,
it's possible for error correction to end up in a deep recursive loop,
which eventually causes a kernel panic.  This change limits the
recursion to a reasonable level during a single I/O operation.

Fixes: a739ff3f ("dm verity: add support for forward error correction")
Signed-off-by: default avatarSami Tolvanen <samitolvanen@google.com>
Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
Cc: stable@vger.kernel.org # v4.5+
parent 4495c08e
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -439,6 +439,13 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
	if (!verity_fec_is_enabled(v))
		return -EOPNOTSUPP;

	if (fio->level >= DM_VERITY_FEC_MAX_RECURSION) {
		DMWARN_LIMIT("%s: FEC: recursion too deep", v->data_dev->name);
		return -EIO;
	}

	fio->level++;

	if (type == DM_VERITY_BLOCK_TYPE_METADATA)
		block += v->data_blocks;

@@ -470,7 +477,7 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
	if (r < 0) {
		r = fec_decode_rsb(v, io, fio, rsb, offset, true);
		if (r < 0)
			return r;
			goto done;
	}

	if (dest)
@@ -480,6 +487,8 @@ int verity_fec_decode(struct dm_verity *v, struct dm_verity_io *io,
		r = verity_for_bv_block(v, io, iter, fec_bv_copy);
	}

done:
	fio->level--;
	return r;
}

@@ -520,6 +529,7 @@ void verity_fec_init_io(struct dm_verity_io *io)
	memset(fio->bufs, 0, sizeof(fio->bufs));
	fio->nbufs = 0;
	fio->output = NULL;
	fio->level = 0;
}

/*
+4 −0
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@
#define DM_VERITY_FEC_BUF_MAX \
	(1 << (PAGE_SHIFT - DM_VERITY_FEC_BUF_RS_BITS))

/* maximum recursion level for verity_fec_decode */
#define DM_VERITY_FEC_MAX_RECURSION	4

#define DM_VERITY_OPT_FEC_DEV		"use_fec_from_device"
#define DM_VERITY_OPT_FEC_BLOCKS	"fec_blocks"
#define DM_VERITY_OPT_FEC_START		"fec_start"
@@ -58,6 +61,7 @@ struct dm_verity_fec_io {
	unsigned nbufs;		/* number of buffers allocated */
	u8 *output;		/* buffer for corrected output */
	size_t output_pos;
	unsigned level;		/* recursion level */
};

#ifdef CONFIG_DM_VERITY_FEC