Commit 16d862d0 authored by wangyalong's avatar wangyalong Committed by Tomasz Zawadzki
Browse files

lib/blob: Handle numerical overflows in the unmap process.



In function blob_free_cluster_msg(), ctx->cluster(U32) may get a number that exceeds U32_max.
When the LBA (unit of blocklen) of the cluster to be released exceeds U32_max,
data overflow occurs, and the cluster located in the LBA%U32_max will be released,
resulting in data inconsistencies or coredump on bs_release_cluster():148.

For example, if the blocklen of lvstore is 512 bytes, and the ctx->cluster type is U32,
the maximum offset of the cluster that can be represented is only ((1<<32)-1)*512=2TB.
If the LBA of cluster to release exceeded, the problem will occur.

Fixes #3358

Change-Id: Idfe7a56f866321770c2a5f3d0189f2c0a42ac7b0
Signed-off-by: default avatarwangyalong <wang597672534@gmail.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/23816


Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <smatsumoto@nvidia.com>
Reviewed-by: default avatarMateusz Kozlowski <mateusz.kozlowski@solidigm.com>
parent e5160883
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -8768,7 +8768,7 @@ blob_free_cluster_msg_cb(void *arg, int bserrno)
	struct spdk_blob_cluster_op_ctx *ctx = arg;

	spdk_spin_lock(&ctx->blob->bs->used_lock);
	bs_release_cluster(ctx->blob->bs, bs_lba_to_cluster(ctx->blob->bs, ctx->cluster));
	bs_release_cluster(ctx->blob->bs, ctx->cluster);
	spdk_spin_unlock(&ctx->blob->bs->used_lock);

	ctx->rc = bserrno;
@@ -8946,7 +8946,7 @@ blob_free_cluster_msg(void *arg)
	bool free_extent_page = true;
	size_t i;

	ctx->cluster = ctx->blob->active.clusters[ctx->cluster_num];
	ctx->cluster = bs_lba_to_cluster(ctx->blob->bs, ctx->blob->active.clusters[ctx->cluster_num]);

	/* There were concurrent unmaps to the same cluster, only release the cluster on the first one */
	if (ctx->cluster == 0) {
@@ -8962,7 +8962,7 @@ blob_free_cluster_msg(void *arg)
	if (ctx->blob->use_extent_table == false) {
		/* Extent table is not used, proceed with sync of md that will only use extents_rle. */
		spdk_spin_lock(&ctx->blob->bs->used_lock);
		bs_release_cluster(ctx->blob->bs, bs_lba_to_cluster(ctx->blob->bs, ctx->cluster));
		bs_release_cluster(ctx->blob->bs, ctx->cluster);
		spdk_spin_unlock(&ctx->blob->bs->used_lock);
		ctx->blob->state = SPDK_BLOB_STATE_DIRTY;
		blob_sync_md(ctx->blob, blob_op_cluster_msg_cb, ctx);