NOMMU: Fix cleanup handling in ramfs_nommu_get_umapped_area()
Fix cleanup handling in ramfs_nommu_get_umapped_area() by only freeing the number of pages that find_get_pages() said it had returned (nr) rather than attempting to free the number of pages we asked for (lpages) - thus avoiding the situation whereby put_page() may be handed NULL pointers if find_get_pages() returned fewer pages that were requested. Also avoid a warning about nr being uninitialised and the need for an if-statement in the cleanup path by using appropriate gotos. Signed-off-by: David Howells <dhowells@redhat.com>
This commit is contained in:
@@ -262,11 +262,11 @@ unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
|
|||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
pages = kzalloc(lpages * sizeof(struct page *), GFP_KERNEL);
|
pages = kzalloc(lpages * sizeof(struct page *), GFP_KERNEL);
|
||||||
if (!pages)
|
if (!pages)
|
||||||
goto out;
|
goto out_free;
|
||||||
|
|
||||||
nr = find_get_pages(inode->i_mapping, pgoff, lpages, pages);
|
nr = find_get_pages(inode->i_mapping, pgoff, lpages, pages);
|
||||||
if (nr != lpages)
|
if (nr != lpages)
|
||||||
goto out; /* leave if some pages were missing */
|
goto out_free_pages; /* leave if some pages were missing */
|
||||||
|
|
||||||
/* check the pages for physical adjacency */
|
/* check the pages for physical adjacency */
|
||||||
ptr = pages;
|
ptr = pages;
|
||||||
@@ -274,19 +274,18 @@ unsigned long ramfs_nommu_get_unmapped_area(struct file *file,
|
|||||||
page++;
|
page++;
|
||||||
for (loop = lpages; loop > 1; loop--)
|
for (loop = lpages; loop > 1; loop--)
|
||||||
if (*ptr++ != page++)
|
if (*ptr++ != page++)
|
||||||
goto out;
|
goto out_free_pages;
|
||||||
|
|
||||||
/* okay - all conditions fulfilled */
|
/* okay - all conditions fulfilled */
|
||||||
ret = (unsigned long) page_address(pages[0]);
|
ret = (unsigned long) page_address(pages[0]);
|
||||||
|
|
||||||
out:
|
out_free_pages:
|
||||||
if (pages) {
|
ptr = pages;
|
||||||
ptr = pages;
|
for (loop = nr; loop > 0; loop--)
|
||||||
for (loop = lpages; loop > 0; loop--)
|
put_page(*ptr++);
|
||||||
put_page(*ptr++);
|
out_free:
|
||||||
kfree(pages);
|
kfree(pages);
|
||||||
}
|
out:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user