Commit edce6820a9fdda85521211cb334a183e34cc455e

Authored by Jeffrey Carlyle
Committed by Jens Axboe
1 parent b76b4014f9

scatterlist: prevent invalid free when alloc fails

When alloc fails, free_table is being called. Depending on the number of
bytes requested, we determine if we are going to call _get_free_page()
or kmalloc(). When alloc fails, our math is wrong (due to sg_size - 1),
and the last buffer is wrongfully assumed to have been allocated by
kmalloc. Hence, kfree gets called and a panic occurs.

Signed-off-by: Jeffrey Carlyle <jeff.carlyle@motorola.com>
Signed-off-by: Olusanya Soyannwo <c23746@motorola.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>

Showing 1 changed file with 12 additions and 2 deletions Side-by-side Diff

... ... @@ -248,8 +248,18 @@
248 248 left -= sg_size;
249 249  
250 250 sg = alloc_fn(alloc_size, gfp_mask);
251   - if (unlikely(!sg))
252   - return -ENOMEM;
  251 + if (unlikely(!sg)) {
  252 + /*
  253 + * Adjust entry count to reflect that the last
  254 + * entry of the previous table won't be used for
  255 + * linkage. Without this, sg_kfree() may get
  256 + * confused.
  257 + */
  258 + if (prv)
  259 + table->nents = ++table->orig_nents;
  260 +
  261 + return -ENOMEM;
  262 + }
253 263  
254 264 sg_init_table(sg, alloc_size);
255 265 table->nents = table->orig_nents += sg_size;