gnttab: Fix handling of dev_bus_addr during unmap
authorGeorge Dunlap <george.dunlap@citrix.com>
Thu, 15 Jun 2017 15:24:02 +0000 (16:24 +0100)
committerIan Jackson <ian.jackson@eu.citrix.com>
Thu, 7 Sep 2017 18:17:58 +0000 (19:17 +0100)
commit1fe898fd84f8e4e90f1d2e080b1b91369dfa853e
tree9d38fdb1c4e24cec3312a3bcb0cb75c00c8302db
parentfcb565b5a53004f5aa7eae2d996680c4bd369662
gnttab: Fix handling of dev_bus_addr during unmap

If a grant has been mapped with the GNTTAB_device_map flag, calling
grant_unmap_ref() with dev_bus_addr set to zero should cause the
GNTTAB_device_map part of the mapping to be left alone.

Unfortunately, at the moment, op->dev_bus_addr is implicitly checked
before clearing the map and adjusting the pin count, but only the bits
above 12; and it is not checked at all before dropping page
references.  This means a guest can repeatedly make such a call to
cause the reference count to drop to zero, causing the page to be
freed and re-used, even though it's still mapped in its pagetables.

To fix this, always check op->dev_bus_addr explicitly for being
non-zero, as well as op->flag & GNTMAP_device_map, before doing
operations on the device_map.

While we're here, make the logic a bit cleaner:

* Always initialize op->frame to zero and set it from act->frame, to reduce the
chance of untrusted input being used

* Explicitly check the full dev_bus_addr against act->frame <<
  PAGE_SHIFT, rather than ignoring the lower 12 bits

This is part of XSA-224.

Reported-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: George Dunlap <george.dunlap@citrix.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Gbp-Pq: Name gnttab-fix-handling-of-dev_bus_addr-duri
xen/common/grant_table.c