Skip to content

Commit 3ccc937

Browse files
committed
virtio_balloon: fix handling of PAGE_SIZE != 4k
As reported by David Gibson, current code handles PAGE_SIZE != 4k completely wrong which can lead to guest memory corruption errors: - page_to_balloon_pfn is wrong: e.g. on system with 64K page size it gives the same pfn value for 16 different pages. - we also need to convert back to linux pfns when we free. - for each linux page we need to tell host about multiple balloon pages, but code only adds one pfn to the array. This patch fixes all that, tested with a 64k ppc64 kernel. Reported-by: David Gibson <[email protected]> Tested-by: David Gibson <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 1a87228 commit 3ccc937

File tree

1 file changed

+41
-10
lines changed

1 file changed

+41
-10
lines changed

drivers/virtio/virtio_balloon.c

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@
2828
#include <linux/slab.h>
2929
#include <linux/module.h>
3030

31+
/*
32+
* Balloon device works in 4K page units. So each page is pointed to by
33+
* multiple balloon pages. All memory counters in this driver are in balloon
34+
* page units.
35+
*/
36+
#define VIRTIO_BALLOON_PAGES_PER_PAGE (PAGE_SIZE >> VIRTIO_BALLOON_PFN_SHIFT)
37+
3138
struct virtio_balloon
3239
{
3340
struct virtio_device *vdev;
@@ -42,8 +49,13 @@ struct virtio_balloon
4249
/* Waiting for host to ack the pages we released. */
4350
struct completion acked;
4451

45-
/* The pages we've told the Host we're not using. */
52+
/* Number of balloon pages we've told the Host we're not using. */
4653
unsigned int num_pages;
54+
/*
55+
* The pages we've told the Host we're not using.
56+
* Each page on this list adds VIRTIO_BALLOON_PAGES_PER_PAGE
57+
* to num_pages above.
58+
*/
4759
struct list_head pages;
4860

4961
/* The array of pfns we tell the Host about. */
@@ -66,7 +78,13 @@ static u32 page_to_balloon_pfn(struct page *page)
6678

6779
BUILD_BUG_ON(PAGE_SHIFT < VIRTIO_BALLOON_PFN_SHIFT);
6880
/* Convert pfn from Linux page size to balloon page size. */
69-
return pfn >> (PAGE_SHIFT - VIRTIO_BALLOON_PFN_SHIFT);
81+
return pfn * VIRTIO_BALLOON_PAGES_PER_PAGE;
82+
}
83+
84+
static struct page *balloon_pfn_to_page(u32 pfn)
85+
{
86+
BUG_ON(pfn % VIRTIO_BALLOON_PAGES_PER_PAGE);
87+
return pfn_to_page(pfn / VIRTIO_BALLOON_PAGES_PER_PAGE);
7088
}
7189

7290
static void balloon_ack(struct virtqueue *vq)
@@ -96,12 +114,23 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
96114
wait_for_completion(&vb->acked);
97115
}
98116

117+
static void set_page_pfns(u32 pfns[], struct page *page)
118+
{
119+
unsigned int i;
120+
121+
/* Set balloon pfns pointing at this page.
122+
* Note that the first pfn points at start of the page. */
123+
for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
124+
pfns[i] = page_to_balloon_pfn(page) + i;
125+
}
126+
99127
static void fill_balloon(struct virtio_balloon *vb, size_t num)
100128
{
101129
/* We can only do one array worth at a time. */
102130
num = min(num, ARRAY_SIZE(vb->pfns));
103131

104-
for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
132+
for (vb->num_pfns = 0; vb->num_pfns < num;
133+
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
105134
struct page *page = alloc_page(GFP_HIGHUSER | __GFP_NORETRY |
106135
__GFP_NOMEMALLOC | __GFP_NOWARN);
107136
if (!page) {
@@ -113,9 +142,9 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
113142
msleep(200);
114143
break;
115144
}
116-
vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page);
145+
set_page_pfns(vb->pfns + vb->num_pfns, page);
146+
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
117147
totalram_pages--;
118-
vb->num_pages++;
119148
list_add(&page->lru, &vb->pages);
120149
}
121150

@@ -130,8 +159,9 @@ static void release_pages_by_pfn(const u32 pfns[], unsigned int num)
130159
{
131160
unsigned int i;
132161

133-
for (i = 0; i < num; i++) {
134-
__free_page(pfn_to_page(pfns[i]));
162+
/* Find pfns pointing at start of each page, get pages and free them. */
163+
for (i = 0; i < num; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
164+
__free_page(balloon_pfn_to_page(pfns[i]));
135165
totalram_pages++;
136166
}
137167
}
@@ -143,11 +173,12 @@ static void leak_balloon(struct virtio_balloon *vb, size_t num)
143173
/* We can only do one array worth at a time. */
144174
num = min(num, ARRAY_SIZE(vb->pfns));
145175

146-
for (vb->num_pfns = 0; vb->num_pfns < num; vb->num_pfns++) {
176+
for (vb->num_pfns = 0; vb->num_pfns < num;
177+
vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
147178
page = list_first_entry(&vb->pages, struct page, lru);
148179
list_del(&page->lru);
149-
vb->pfns[vb->num_pfns] = page_to_balloon_pfn(page);
150-
vb->num_pages--;
180+
set_page_pfns(vb->pfns + vb->num_pfns, page);
181+
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
151182
}
152183

153184
/*

0 commit comments

Comments
 (0)