|
@@ -1760,11 +1760,11 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
|
|
unsigned int type;
|
|
|
int i, prev;
|
|
|
int error;
|
|
|
- union swap_header *swap_header = NULL;
|
|
|
- unsigned int nr_good_pages = 0;
|
|
|
+ union swap_header *swap_header;
|
|
|
+ unsigned int nr_good_pages;
|
|
|
int nr_extents = 0;
|
|
|
sector_t span;
|
|
|
- unsigned long maxpages = 1;
|
|
|
+ unsigned long maxpages;
|
|
|
unsigned long swapfilepages;
|
|
|
unsigned char *swap_map = NULL;
|
|
|
struct page *page = NULL;
|
|
@@ -1923,9 +1923,13 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
|
|
* swap pte.
|
|
|
*/
|
|
|
maxpages = swp_offset(pte_to_swp_entry(
|
|
|
- swp_entry_to_pte(swp_entry(0, ~0UL)))) - 1;
|
|
|
- if (maxpages > swap_header->info.last_page)
|
|
|
- maxpages = swap_header->info.last_page;
|
|
|
+ swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1;
|
|
|
+ if (maxpages > swap_header->info.last_page) {
|
|
|
+ maxpages = swap_header->info.last_page + 1;
|
|
|
+ /* p->max is an unsigned int: don't overflow it */
|
|
|
+ if ((unsigned int)maxpages == 0)
|
|
|
+ maxpages = UINT_MAX;
|
|
|
+ }
|
|
|
p->highest_bit = maxpages - 1;
|
|
|
|
|
|
error = -EINVAL;
|
|
@@ -1949,23 +1953,24 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
|
|
}
|
|
|
|
|
|
memset(swap_map, 0, maxpages);
|
|
|
+ nr_good_pages = maxpages - 1; /* omit header page */
|
|
|
+
|
|
|
for (i = 0; i < swap_header->info.nr_badpages; i++) {
|
|
|
- int page_nr = swap_header->info.badpages[i];
|
|
|
- if (page_nr <= 0 || page_nr >= swap_header->info.last_page) {
|
|
|
+ unsigned int page_nr = swap_header->info.badpages[i];
|
|
|
+ if (page_nr == 0 || page_nr > swap_header->info.last_page) {
|
|
|
error = -EINVAL;
|
|
|
goto bad_swap;
|
|
|
}
|
|
|
- swap_map[page_nr] = SWAP_MAP_BAD;
|
|
|
+ if (page_nr < maxpages) {
|
|
|
+ swap_map[page_nr] = SWAP_MAP_BAD;
|
|
|
+ nr_good_pages--;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
error = swap_cgroup_swapon(type, maxpages);
|
|
|
if (error)
|
|
|
goto bad_swap;
|
|
|
|
|
|
- nr_good_pages = swap_header->info.last_page -
|
|
|
- swap_header->info.nr_badpages -
|
|
|
- 1 /* header page */;
|
|
|
-
|
|
|
if (nr_good_pages) {
|
|
|
swap_map[0] = SWAP_MAP_BAD;
|
|
|
p->max = maxpages;
|