|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] Ubuntu 16.04.1 LTS kernel 4.4.0-57 over-allocation and xen-access fail
On 01/10/2017 04:13 PM, Andrew Cooper wrote:
> On 10/01/17 09:06, Razvan Cojocaru wrote:
>> On 01/09/2017 02:54 PM, Andrew Cooper wrote:
>>> On 09/01/17 11:36, Razvan Cojocaru wrote:
>>>> Hello,
>>>>
>>>> We've come across a weird phenomenon: an Ubuntu 16.04.1 LTS HVM guest
>>>> running kernel 4.4.0 installed via XenCenter in XenServer Dundee seems
>>>> to eat up all the RAM it can:
>>>>
>>>> (XEN) [ 394.379760] d1v1 Over-allocation for domain 1: 524545 > 524544
>>>>
>>>> This leads to a problem with xen-access, specifically libxc which does
>>>> this in xc_vm_event_enable() (this is Xen 4.6):
>>>>
>>>> ring_page = xc_map_foreign_batch(xch, domain_id, PROT_READ | PROT_WRITE,
>>>> &mmap_pfn, 1);
>>>>
>>>> if ( mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
>>>> {
>>>> /* Map failed, populate ring page */
>>>> rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
>>>> &ring_pfn);
>>>> if ( rc1 != 0 )
>>>> {
>>>> PERROR("Failed to populate ring pfn\n");
>>>> goto out;
>>>> }
>>>>
>>>> The first time everything works fine, xen-access can map the ring page.
>>>> But most of the time the second time fails in the
>>>> xc_domain_populate_physmap_exact() call, and again this is dumped in the
>>>> Xen log (once for each failed attempt):
>>>>
>>>> (XEN) [ 395.952188] d0v3 Over-allocation for domain 1: 524545 > 524544
>>> Thinking further about this, what happens if you avoid removing the page
>>> on exit?
>>>
>>> The first populate succeeds, and if you leave the page populated, the
>>> second time you come around the loop, it should not be of type XTAB, and
>>> the map should succeed.
>> Sorry for the late reply, had to put out another fire yesterday.
>>
>> I've taken your recommendation to roughly mean this:
>>
>> diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
>> index ba9690a..805564b 100644
>> --- a/xen/common/vm_event.c
>> +++ b/xen/common/vm_event.c
>> @@ -100,8 +100,11 @@ static int vm_event_enable(
>> return 0;
>>
>> err:
>> + /*
>> destroy_ring_for_helper(&ved->ring_page,
>> ved->ring_pg_struct);
>> + */
>> + ved->ring_page = NULL;
>> vm_event_ring_unlock(ved);
>>
>> return rc;
>> @@ -229,9 +232,12 @@ static int vm_event_disable(struct domain *d,
>> struct vm_event_domain *ved)
>> }
>> }
>>
>> + /*
>> destroy_ring_for_helper(&ved->ring_page,
>> ved->ring_pg_struct);
>> + */
>>
>> + ved->ring_page = NULL;
>> vm_event_cleanup_domain(d);
>>
>> vm_event_ring_unlock(ved);
>>
>> but this unfortunately still fails to map the page the second time. Do
>> you mean to simply no longer munmap() the ring page from libxc / the
>> client application?
>
> Neither.
>
> First of all, I notice that this is probably buggy:
>
> ring_pfn = pfn;
> mmap_pfn = pfn;
> rc1 = xc_get_pfn_type_batch(xch, domain_id, 1, &mmap_pfn);
> if ( rc1 || mmap_pfn & XEN_DOMCTL_PFINFO_XTAB )
> {
> /* Page not in the physmap, try to populate it */
> rc1 = xc_domain_populate_physmap_exact(xch, domain_id, 1, 0, 0,
> &ring_pfn);
> if ( rc1 != 0 )
> {
> PERROR("Failed to populate ring pfn\n");
> goto out;
> }
> }
>
> A failure of xc_get_pfn_type_batch() is not a suggestion that population
> might work.
>
>
> What I meant was taking out this call:
>
> /* Remove the ring_pfn from the guest's physmap */
> rc1 = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0,
> &ring_pfn);
> if ( rc1 != 0 )
> PERROR("Failed to remove ring page from guest physmap");
>
> To leave the frame in the guest physmap. The issue is fundamentally
> that after this frame has been taken out, something kicks the VM to
> realise it has an extra frame of balloonable space, which it clearly
> compensates for.
>
> You can work around the added attack surface by marking it RO in EPT;
> neither Xen's nor dom0's mappings are translated via EPT, so they can
> still make updates, but the guest won't be able to write to it.
>
> I should say that this is all a gross hack, and is in desperate need of
> a proper API to make rings entirely outside of the gfn space, but this
> hack should work for now.
Thanks! So far, it seems to work like a charm like this:
diff --git a/tools/libxc/xc_vm_event.c b/tools/libxc/xc_vm_event.c
index 2fef96a..5dd00a6 100644
--- a/tools/libxc/xc_vm_event.c
+++ b/tools/libxc/xc_vm_event.c
@@ -130,9 +130,17 @@ void *xc_vm_event_enable(xc_interface *xch, domid_t
domain_id, int param,
}
/* Remove the ring_pfn from the guest's physmap */
+ /*
rc1 = xc_domain_decrease_reservation_exact(xch, domain_id, 1, 0,
&ring_pfn);
if ( rc1 != 0 )
PERROR("Failed to remove ring page from guest physmap");
+ */
+
+ if ( xc_set_mem_access(xch, domain_id, XENMEM_access_r, mmap_pfn, 1) )
+ {
+ PERROR("Could not set ring page read-only\n");
+ goto out;
+ }
out:
saved_errno = errno;
Should I send this as a patch for mainline as well?
Thanks,
Razvan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |