Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: erofs: avoid loop in submit chains

As reported by erofs-utils fuzzer, 2 conditions
can happen in corrupted images, which can cause
unexpected behaviors.
- access the same pcluster one more time;
- access the tail end pcluster again, e.g.
_ access again (will trigger tail merging)
|
1 2 3 1 2 -> 1 2 3 1
|_ tail end of the chain \___/ (unexpected behavior)
Let's detect and avoid them now.

Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Gao Xiang <gaoxiang25@huawei.com>
Link: https://lore.kernel.org/r/20190821030908.40282-1-gaoxiang25@huawei.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Gao Xiang and committed by
Greg Kroah-Hartman
bfc4ccb1 2cb05d87

+15 -1
+15 -1
drivers/staging/erofs/zdata.c
··· 132 132 struct z_erofs_collector { 133 133 struct z_erofs_pagevec_ctor vector; 134 134 135 - struct z_erofs_pcluster *pcl; 135 + struct z_erofs_pcluster *pcl, *tailpcl; 136 136 struct z_erofs_collection *cl; 137 137 struct page **compressedpages; 138 138 z_erofs_next_pcluster_t owned_head; ··· 353 353 return NULL; 354 354 355 355 pcl = container_of(grp, struct z_erofs_pcluster, obj); 356 + if (clt->owned_head == &pcl->next || pcl == clt->tailpcl) { 357 + DBG_BUGON(1); 358 + erofs_workgroup_put(grp); 359 + return ERR_PTR(-EFSCORRUPTED); 360 + } 356 361 357 362 cl = z_erofs_primarycollection(pcl); 358 363 if (unlikely(cl->pageofs != (map->m_la & ~PAGE_MASK))) { ··· 386 381 } 387 382 } 388 383 mutex_lock(&cl->lock); 384 + /* used to check tail merging loop due to corrupted images */ 385 + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) 386 + clt->tailpcl = pcl; 389 387 clt->mode = try_to_claim_pcluster(pcl, &clt->owned_head); 388 + /* clean tailpcl if the current owned_head is Z_EROFS_PCLUSTER_TAIL */ 389 + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) 390 + clt->tailpcl = NULL; 390 391 clt->pcl = pcl; 391 392 clt->cl = cl; 392 393 return cl; ··· 445 434 kmem_cache_free(pcluster_cachep, pcl); 446 435 return ERR_PTR(-EAGAIN); 447 436 } 437 + /* used to check tail merging loop due to corrupted images */ 438 + if (clt->owned_head == Z_EROFS_PCLUSTER_TAIL) 439 + clt->tailpcl = pcl; 448 440 clt->owned_head = &pcl->next; 449 441 clt->pcl = pcl; 450 442 clt->cl = cl;