Commit edce6820a9fdda85521211cb334a183e34cc455e
Committed by
Jens Axboe
1 parent
b76b4014f9
Exists in
master
and in
7 other branches
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
lib/scatterlist.c
... | ... | @@ -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; |