Xen/gntdev: correct error checking in gntdev_map_grant_pages()
authorJan Beulich <jbeulich@suse.com>
Mon, 15 Feb 2021 07:52:27 +0000 (08:52 +0100)
committerJuergen Gross <jgross@suse.com>
Mon, 15 Feb 2021 07:52:27 +0000 (08:52 +0100)
Failure of the kernel part of the mapping operation should also be
indicated as an error to the caller, or else it may assume the
respective kernel VA is okay to access.

Furthermore gnttab_map_refs() failing still requires recording
successfully mapped handles, so they can be unmapped subsequently. This
in turn requires there to be a way to tell full hypercall failure from
partial success - preset map_op status fields such that they won't
"happen" to look as if the operation succeeded.

Also again use GNTST_okay instead of implying its value (zero).

This is part of XSA-361.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Cc: stable@vger.kernel.org
Reviewed-by: Juergen Gross <jgross@suse.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
drivers/xen/gntdev.c
include/xen/grant_table.h

index aece224a4e705866e9be1f2a3466d060a271eaf9..5447c5156b2e62ea50f8190609a85db42904b4ed 100644 (file)
@@ -334,21 +334,22 @@ int gntdev_map_grant_pages(struct gntdev_grant_map *map)
        pr_debug("map %d+%d\n", map->index, map->count);
        err = gnttab_map_refs(map->map_ops, use_ptemod ? map->kmap_ops : NULL,
                        map->pages, map->count);
-       if (err)
-               return err;
 
        for (i = 0; i < map->count; i++) {
-               if (map->map_ops[i].status) {
+               if (map->map_ops[i].status == GNTST_okay)
+                       map->unmap_ops[i].handle = map->map_ops[i].handle;
+               else if (!err)
                        err = -EINVAL;
-                       continue;
-               }
 
                if (map->flags & GNTMAP_device_map)
                        map->unmap_ops[i].dev_bus_addr = map->map_ops[i].dev_bus_addr;
 
-               map->unmap_ops[i].handle = map->map_ops[i].handle;
-               if (use_ptemod)
-                       map->kunmap_ops[i].handle = map->kmap_ops[i].handle;
+               if (use_ptemod) {
+                       if (map->kmap_ops[i].status == GNTST_okay)
+                               map->kunmap_ops[i].handle = map->kmap_ops[i].handle;
+                       else if (!err)
+                               err = -EINVAL;
+               }
        }
        return err;
 }
index b9c937b3a1499ca73651ab50293633e2af583b68..0b1182a3cf4128b4502b7e3db59adeb8522daea5 100644 (file)
@@ -157,6 +157,7 @@ gnttab_set_map_op(struct gnttab_map_grant_ref *map, phys_addr_t addr,
        map->flags = flags;
        map->ref = ref;
        map->dom = domid;
+       map->status = 1; /* arbitrary positive value */
 }
 
 static inline void