scst_mem: Fix a memory leak triggered by the scst_user driver

Avoid that the following memory leak can occur:
- sgv_pool_alloc() is called with SGV_POOL_RETURN_OBJ_ON_ALLOC_FAIL
  set, with neither SGV_POOL_NO_ALLOC_ON_CACHE_MISS nor
  SGV_POOL_ALLOC_NO_CACHED set and with 'size' such that
  sgv_max_local_pages < pages_to_alloc <= pool->max_cached_pages.
- sgv_get_obj() and sgv_alloc_arrays() succeed.
- sgv_alloc_sg_entries() fails.
- sgv_get_obj() returns the SGV object with no buffers.
- A call to sgv_pool_free() adds this object to the recycle list.
- sgv_pool_alloc() is called a second time with the same parameters.
- sgv_get_obj() retrieves the object that was previously added to
  the recycle list.
- sgv_alloc_arrays() is called and overwrites the obj->sg_entries
  pointer although it still points at allocated memory, resulting
  in a memory leak.

Reported-by: Shahar Salzman <shahar.salzman@kaminario.com>


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5829 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2014-10-03 12:26:14 +00:00
parent d4c49fcd64
commit e706313fc6

View File

@@ -1021,7 +1021,13 @@ struct scatterlist *sgv_pool_alloc(struct sgv_pool *pool, unsigned int size,
goto out_fail_free;
}
TRACE_MEM("Brand new obj %p", obj);
if (likely(!obj->recycling_list_entry.next)) {
TRACE_MEM("Brand new obj %p", obj);
} else if (unlikely(obj->sg_entries != obj->sg_entries_data)) {
TRACE_MEM("Cached obj %p with sg_count == 0", obj);
kfree(obj->sg_entries);
obj->sg_entries = NULL;
}
if (pages_to_alloc <= sgv_max_local_pages) {
obj->sg_entries = obj->sg_entries_data;