page-alloc: detect double free earlier

Right now this goes unnoticed until some subsequent page allocator
operation stumbles across the thus corrupted list. We can do better:
Only PGC_state_inuse and PGC_state_offlining pages can legitimately be
passed to free_heap_pages().

Take the opportunity and also restrict the PGC_broken check to the
PGC_state_offlining case, as only pages of that type or
PGC_state_offlined may have this flag set on them. Similarly, since
PGC_state_offlined is not a valid input state, the setting of "tainted"
can be restricted to just this case.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Jan Beulich committed 2019-05-13 09:58:57 +02:00
1 parent 24f1a58d19
commit f882fadbeb
1 file changed
+15 -6
+15 -6
View File
@@ -1413,13 +1413,22 @@ static void free_heap_pages(
* in its pseudophysical address space).
* In all the above cases there can be no guest mappings of this page.
*/
ASSERT(!page_state_is(&pg[i], offlined));
pg[i].count_info =
((pg[i].count_info & PGC_broken) |
(page_state_is(&pg[i], offlining)
? PGC_state_offlined : PGC_state_free));
if ( page_state_is(&pg[i], offlined) )
switch ( pg[i].count_info & PGC_state )
{
case PGC_state_inuse:
BUG_ON(pg[i].count_info & PGC_broken);
pg[i].count_info = PGC_state_free;
break;
case PGC_state_offlining:
pg[i].count_info = (pg[i].count_info & PGC_broken) |
PGC_state_offlined;
tainted = 1;
break;
default:
BUG();
}
/* If a page has no owner it will need no safety TLB flush. */
pg[i].u.free.need_tlbflush = (page_get_owner(&pg[i]) != NULL);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.