Drivers: hv: hv_balloon: two additional corner cases in balloon_up()
cover Drivers: hv: hv_balloon: two additional corner cases in balloon_up()
PATCH 1/2 addresses a real issue introduced by the 'Drivers: hv: hv_balloon:
refuse to balloon below the floor' fix,
PATCH 2/2 addresses a currently impossible issue (as Hyper-V host never asks to balloon more than INT_MAX pages) and is rather a cleanup. The patch is supposed to be applied on top of previously sent 'Drivers: hv: hv_balloon:
survive ballooning request with num_pages=0'.
Both issues were found by Laszlo Ersek during code review.
Vitaly Kuznetsov (2):
Drivers: hv: hv_balloon: correctly handle val.freeram<num_pages case
Drivers: hv: hv_balloon: correctly handle num_pages>INT_MAX case
drivers/hv/hv_balloon.c | 15 ++++++++------- 1 files changed, 8 insertions(+), 7 deletions(-)
Signature · 1 line
1.7.4.1
PATCH 1/2 Drivers: hv: hv_balloon: correctly handle val.freeram<num_pages case
From: Vitaly Kuznetsov <[email protected]>
'Drivers: hv: hv_balloon: refuse to balloon below the floor' fix does not correctly handle the case when val.freeram < num_pages as val.freeram is __kernel_ulong_t and the 'val.freeram - num_pages' value will be a huge positive value instead of being negative.
Usually host doesn't ask us to balloon more than val.freeram but in case he have a memory hog started after we post the last pressure report we can get into troubles.
--- drivers/hv/hv_balloon.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/hv/hv_balloon.c +1 -1
@@ -1155,7 +1155,7 @@ static void balloon_up(struct work_struct *dummy) floor =compute_balloon_floor ();/* Refuse to balloon below the floor, keep the 2M granularity. */ -if (val.freeram - num_pages < floor) { +if (val.freeram < num_pages || val.freeram - num_pages < floor) { num_pages = val.freeram > floor ? (val.freeram - floor) :0 ; num_pages -= num_pages %PAGES_IN_2M ; }
Signature · 1 line
1.7.4.1
PATCH 2/2 Drivers: hv: hv_balloon: correctly handle num_pages>INT_MAX case
From: Vitaly Kuznetsov <[email protected]>
balloon_wrk.num_pages is __u32 and it comes from host in struct dm_balloon where it is also __u32. We, however, use 'int' in balloon_up() and in case we happen to receive num_pages>INT_MAX request we'll end up allocating zero pages as 'num_pages < alloc_unit' check in alloc_balloon_pages() will pass. Change num_pages type to unsigned int.
In real life ballooning request come with num_pages in [512, 32768] range so this is more a future-proof/cleanup.
--- drivers/hv/hv_balloon.c | 13 +++++++------ 1 files changed, 7 insertions(+), 6 deletions(-)
drivers/hv/hv_balloon.c +7 -6
@@ -1081,11 +1081,12 @@ static void free_balloon_pages(struct hv_dynmem_device *dm, -static int alloc_balloon_pages (struct hv_dynmem_device *dm,int num_pages, -struct dm_balloon_response *bl_resp, -int alloc_unit) +static unsigned int alloc_balloon_pages (struct hv_dynmem_device *dm, +unsigned int num_pages, +struct dm_balloon_response *bl_resp, +int alloc_unit) { -int i =0 ; +unsigned int i =0 ;struct page *pg;if (num_pages < alloc_unit)
@@ -1132,8 +1133,8 @@ static int alloc_balloon_pages(struct hv_dynmem_device *dm, int num_pages,static void balloon_up (struct work_struct *dummy) { -int num_pages = dm_device.balloon_wrk.num_pages; -int num_ballooned =0 ; +unsigned int num_pages = dm_device.balloon_wrk.num_pages; +unsigned int num_ballooned =0 ;struct dm_balloon_response *bl_resp;int alloc_unit;int ret;
Signature · 1 line
1.7.4.1