linux_gntshr_munmap: munmap takes a length, not a page count
authorDavid Scott <dave.scott@citrix.com>
Wed, 3 Sep 2014 17:34:21 +0000 (18:34 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Wed, 10 Sep 2014 14:06:50 +0000 (15:06 +0100)
This fixes a bug where if a client shares more than 1 page, the
munmap call fails to clean up everything. A process which does
a lot of sharing and unsharing can run out of resources.

This patch also fixes in-tree callers of
  - xc_gntshr_munmap
  - xc_gnttab_munmap
to supply page counts rather than lengths.

Signed-off-by: David Scott <dave.scott@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
tools/libvchan/init.c
tools/libvchan/io.c
tools/libxc/xc_linux_osdep.c

index c080a1cbe4d67649981d6310cbc9dda3cab22c00..de10817e00e1f3f18c27669f9e52fa064b1bfb8d 100644 (file)
@@ -129,9 +129,9 @@ out:
        return ring_ref;
 out_unmap_left:
        if (pages_left)
-               xc_gntshr_munmap(ctrl->gntshr, ctrl->read.buffer, pages_left * PAGE_SIZE);
+               xc_gntshr_munmap(ctrl->gntshr, ctrl->read.buffer, pages_left);
 out_ring:
-       xc_gntshr_munmap(ctrl->gntshr, ring, PAGE_SIZE);
+       xc_gntshr_munmap(ctrl->gntshr, ring, 1);
        ring_ref = -1;
        ctrl->ring = NULL;
        ctrl->write.order = ctrl->read.order = 0;
@@ -204,9 +204,9 @@ static int init_gnt_cli(struct libxenvchan *ctrl, int domain, uint32_t ring_ref)
  out_unmap_left:
        if (ctrl->write.order >= PAGE_SHIFT)
                xc_gnttab_munmap(ctrl->gnttab, ctrl->write.buffer,
-                                1 << ctrl->write.order);
+                                1 << (ctrl->write.order - PAGE_SHIFT));
  out_unmap_ring:
-       xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, PAGE_SIZE);
+       xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
        ctrl->ring = 0;
        ctrl->write.order = ctrl->read.order = 0;
        rv = -1;
index 6e6e2395df6c4601d9b16aeea7a33c8cf5d7ac4d..e66bc4e71ab53d0cf6c2b0814a8f127bb8667da9 100644 (file)
@@ -365,10 +365,10 @@ void libxenvchan_close(struct libxenvchan *ctrl)
        if (ctrl->ring) {
                if (ctrl->is_server) {
                        ctrl->ring->srv_live = 0;
-                       xc_gntshr_munmap(ctrl->gntshr, ctrl->ring, PAGE_SIZE);
+                       xc_gntshr_munmap(ctrl->gntshr, ctrl->ring, 1);
                } else {
                        ctrl->ring->cli_live = 0;
-                       xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, PAGE_SIZE);
+                       xc_gnttab_munmap(ctrl->gnttab, ctrl->ring, 1);
                }
        }
        if (ctrl->event) {
index 86bff3e1d1017fed17130520285780107fa0c14d..a19e4b69ea8c15d7bec98fe7261fe2ec09db692b 100644 (file)
@@ -847,7 +847,7 @@ static void *linux_gntshr_share_pages(xc_gntshr *xch, xc_osdep_handle h,
 static int linux_gntshr_munmap(xc_gntshr *xcg, xc_osdep_handle h,
                                void *start_address, uint32_t count)
 {
-    return munmap(start_address, count);
+    return munmap(start_address, count * XC_PAGE_SIZE);
 }
 
 static struct xc_osdep_ops linux_gntshr_ops = {