scst: Avoid that excessive data lengths cause COMPARE AND WRITE to crash

Avoid that running the libiscsi conformance tests triggers the following crash:

==================================================================
BUG: KASAN: wild-memory-access in sg_cmp_elem+0x1b6/0x490 [scst]
Read of size 8 at addr 0002000100000000 by task disk021_5/1231
CPU: 0 PID: 1231 Comm: disk021_5 Tainted: G           O      5.0.0-rc6-dbg+ #2
Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
Call Trace:
 dump_stack+0x86/0xca
 kasan_report.cold.3+0x5/0x3b
 __asan_load8+0x54/0x90
 sg_cmp_elem+0x1b6/0x490 [scst]
 sg_cmp.constprop.41+0x185/0x380 [scst]
 scst_cwr_read_cmd_finished+0x214/0x6d0 [scst]
 scst_finish_internal_cmd+0x109/0x1d0 [scst]
 scst_process_active_cmd+0x193/0x570 [scst]
 scst_process_redirect_cmd+0x214/0x300 [scst]
 scst_cmd_done_local+0xec/0x1f0 [scst]
 fileio_async_complete+0x98/0x1b0 [scst_vdisk]
 fileio_exec_async+0x3ac/0x430 [scst_vdisk]
 fileio_exec_read+0x34f/0x560 [scst_vdisk]
 vdev_do_job+0xf5/0x260 [scst_vdisk]
 fileio_exec+0x66/0x70 [scst_vdisk]
 scst_do_real_exec+0x11f/0x540 [scst]
 scst_exec_check_blocking+0x14c/0x270 [scst]
 scst_exec_check_sn+0x2ef/0x650 [scst]
 scst_process_active_cmd+0x2d2/0x570 [scst]
 scst_cmd_thread+0x1e3/0x6b0 [scst]
 kthread+0x1d2/0x1f0
 ret_from_fork+0x3a/0x50
==================================================================


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7992 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2019-02-24 17:53:27 +00:00
parent 65ad03ffd0
commit 8cf079dbed
2 changed files with 15 additions and 0 deletions

View File

@@ -868,6 +868,10 @@ static inline void sg_mark_end(struct scatterlist *sg)
{
}
static inline void sg_unmark_end(struct scatterlist *sg)
{
}
#ifndef __BACKPORT_LINUX_SCATTERLIST_H_TO_2_6_23__
static inline void sg_init_table(struct scatterlist *sgl, unsigned int nents)
@@ -895,6 +899,15 @@ static inline void sg_set_page(struct scatterlist *sg, struct page *page,
#endif /* for_each_sg */
#endif /* __BACKPORT_LINUX_SCATTERLIST_H_TO_2_6_23__ */
#elif LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
/*
* See also commit c8164d8931fd ("scatterlist: introduce sg_unmark_end";
* v3.10).
*/
static inline void sg_unmark_end(struct scatterlist *sg)
{
sg->page_link &= ~0x02;
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */
/* <linux/slab.h> */

View File

@@ -1099,6 +1099,7 @@ success:
*sgv = obj;
obj->sg_entries[cnt-1].length -= PAGE_ALIGN(size) - size;
sg_mark_end(&obj->sg_entries[cnt-1]);
TRACE_MEM("obj=%p, sg_entries %p (size=%d, pages=%d, sg_count=%d, "
"count=%d, last_len=%d)", obj, obj->sg_entries, size, pages,
@@ -1224,6 +1225,7 @@ void sgv_pool_free(struct sgv_pool_obj *obj, struct scst_mem_lim *mem_lim)
if (obj->cache_num >= 0) {
obj->sg_entries[obj->orig_sg].length = obj->orig_length;
sg_unmark_end(&obj->sg_entries[obj->orig_sg]);
sgv_put_obj(obj);
} else {
obj->owner_pool->alloc_fns.free_pages_fn(obj->sg_entries,