* What's the reason for padding the alloc_bitmap in page_alloc.c?
@ 2006-08-05 3:55 Steven Rostedt
2006-08-05 9:05 ` Keir Fraser
0 siblings, 1 reply; 2+ messages in thread
From: Steven Rostedt @ 2006-08-05 3:55 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 2617 bytes --]
I see the code in init_boot_allocator that added an extra longword to
the size of alloc_bitmap. Is there really a chance for overrun in
map_alloc or map_free as the comment suggests? I would think that
allocating or freeing more than we have would be considered a bug. I
don't know the history of that padding but I wonder if it is from
another overflow that is fixable. Doing bitmap_size = (max_page + 7)/8
should be enough.
/*
* Allocate space for the allocation bitmap. Include an extra longword
* of padding for possible overrun in map_alloc and map_free.
*/
bitmap_size = max_page / 8;
bitmap_size += sizeof(unsigned long);
bitmap_size = round_pgup(bitmap_size);
alloc_bitmap = (unsigned long *)maddr_to_virt(bitmap_start);
In page_alloc.c end_boot_allocator, there's a slight chance that the
allocated_in_map macro can cause an overflow. This is because it uses
i+1 as the parameter and i goes to i < max_pages (if i == max_pages then
we overflow).
Most of the time, this is ok because the allocation is bigger than
needed. But if it is just right, then we could have a problem.
/* Pages that are free now go to the domain sub-allocator. */
for ( i = 0; i < max_page; i++ )
{
curr_free = next_free;
next_free = !allocated_in_map(i+1);
if ( next_free )
map_alloc(i+1, 1); /* prevent merging in free_heap_pages() */
if ( curr_free )
free_heap_pages(pfn_dom_zone_type(i), mfn_to_page(i), 0);
}
and with allocate_in_map as:
#define allocated_in_map(_pn) \
( !! (alloc_bitmap[(_pn)/PAGES_PER_MAPWORD] & \
(1UL<<((_pn)&(PAGES_PER_MAPWORD-1)))) )
We see here that we are indexing past the bitmap and can cause
problems. I wonder if this was actually happening and the above padding
was done to hide this bug. Well the padding does fix the bug, but I
don't think it's the proper approach.
Attached is a patch to fix the overflow problem in end_boot_allocator.
I'll run it some time without that padding (do bitmap_size = (max_page +
7)/8 instead) and see if there's any other problems. I'll also put a
test into map_alloc and map_free to tell me if something goes past
max_page or bitmap size.
I would hate to have 134,184,960 bytes of memory: 134,184,960 / 4096 =
32,760 : 32,760 / 8 = 4095 : 4095 + 4 = 4099 And now we have an extra
page for the bitmap without it ever being used. (OK that was
hypothetical, but does make a small point. ;)
-- Steve
just in case you want the patch.
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
[-- Attachment #2: hv-page-alloc-buffer-overflow.patch --]
[-- Type: text/x-patch, Size: 1391 bytes --]
diff -r bbabdebc54ad xen/common/page_alloc.c
--- a/xen/common/page_alloc.c Wed Jul 19 21:13:36 2006 +0100
+++ b/xen/common/page_alloc.c Fri Aug 04 22:52:23 2006 -0400
@@ -256,7 +256,7 @@ void end_boot_allocator(void)
void end_boot_allocator(void)
{
unsigned long i, j;
- int curr_free = 0, next_free = 0;
+ int curr_free, prev_free;
memset(avail, 0, sizeof(avail));
@@ -265,15 +265,18 @@ void end_boot_allocator(void)
INIT_LIST_HEAD(&heap[i][j]);
/* Pages that are free now go to the domain sub-allocator. */
- for ( i = 0; i < max_page; i++ )
- {
- curr_free = next_free;
- next_free = !allocated_in_map(i+1);
- if ( next_free )
- map_alloc(i+1, 1); /* prevent merging in free_heap_pages() */
+ prev_free = !allocated_in_map(0);
+ for ( i = 1; i < max_page; i++ )
+ {
+ curr_free = !allocated_in_map(i);
if ( curr_free )
- free_heap_pages(pfn_dom_zone_type(i), mfn_to_page(i), 0);
- }
+ map_alloc(i, 1); /* prevent merging in free_heap_pages() */
+ if ( prev_free )
+ free_heap_pages(pfn_dom_zone_type(i-1), mfn_to_page(i-1), 0);
+ prev_free = curr_free;
+ }
+ if ( prev_free )
+ free_heap_pages(pfn_dom_zone_type(i-1), mfn_to_page(i-1), 0);
}
/* Hand the specified arbitrary page range to the specified heap zone. */
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: What's the reason for padding the alloc_bitmap in page_alloc.c?
2006-08-05 3:55 What's the reason for padding the alloc_bitmap in page_alloc.c? Steven Rostedt
@ 2006-08-05 9:05 ` Keir Fraser
0 siblings, 0 replies; 2+ messages in thread
From: Keir Fraser @ 2006-08-05 9:05 UTC (permalink / raw)
To: Steven Rostedt, xen-devel
On 5/8/06 4:55 am, "Steven Rostedt" <srostedt@redhat.com> wrote:
> I see the code in init_boot_allocator that added an extra longword to
> the size of alloc_bitmap. Is there really a chance for overrun in
> map_alloc or map_free as the comment suggests? I would think that
> allocating or freeing more than we have would be considered a bug. I
> don't know the history of that padding but I wonder if it is from
> another overflow that is fixable. Doing bitmap_size = (max_page + 7)/8
> should be enough.
There are plenty of places that can look one page (bit) beyond the end of
the map:
1. Map_alloc and map_free set end_idx/offset as first_page + nr_pages. This
clearly references the first page *after* the range of interest. What if
that range ends on max_page-1?
2. Free_heap_pages checks neighbouring pages of the freed range for
potential opportunities to merge to a higher-order buddy list. What if the
last page of the range being freed is max_page-1?
However, I think the bitmap allocation could be made a bit tighter. Perhaps:
bitmap_size = round_pgup(max_page/8 + 1);
This rounds down to bytes, but then adds an extra byte so that we can always
go one off the end of the bitmap (really it's just a simplification of
(max_page + 1 + 7) / 8). How does that sound?
NB. Going off the start of the bitmap is never a problem, since page 0 is
never available for allocation. :-)
-- Keir
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-08-05 9:05 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-08-05 3:55 What's the reason for padding the alloc_bitmap in page_alloc.c? Steven Rostedt
2006-08-05 9:05 ` Keir Fraser
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.