drm/i915/kvmgt: Fix potential Spectre v1
authorGustavo A. R. Silva <gustavo@embeddedor.com>
Fri, 3 Aug 2018 03:40:19 +0000 (22:40 -0500)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Tue, 14 Aug 2018 07:26:49 +0000 (15:26 +0800)
info.index can be indirectly controlled by user-space, hence leading
to a potential exploitation of the Spectre variant 1 vulnerability.

This issue was detected with the help of Smatch:

drivers/gpu/drm/i915/gvt/kvmgt.c:1232 intel_vgpu_ioctl() warn:
potential spectre issue 'vgpu->vdev.region' [r]

Fix this by sanitizing info.index before indirectly using it to index
vgpu->vdev.region

Notice that given that speculation windows are large, the policy is
to kill the speculation on the first load and not worry if it can be
completed with a dependent load/store [1].

[1] https://marc.info/?l=linux-kernel&m=152449131114778&w=2

Cc: stable@vger.kernel.org
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/kvmgt.c

index 31986c1c253ed7b858151a5652e212032e3c2865..9ba70826737aba9a1ed6b574c94d19df5751bf7d 100644 (file)
@@ -43,6 +43,8 @@
 #include <linux/mdev.h>
 #include <linux/debugfs.h>
 
+#include <linux/nospec.h>
+
 #include "i915_drv.h"
 #include "gvt.h"
 
@@ -1139,7 +1141,8 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
        } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
                struct vfio_region_info info;
                struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
-               int i, ret;
+               unsigned int i;
+               int ret;
                struct vfio_region_info_cap_sparse_mmap *sparse = NULL;
                size_t size;
                int nr_areas = 1;
@@ -1224,6 +1227,10 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd,
                                if (info.index >= VFIO_PCI_NUM_REGIONS +
                                                vgpu->vdev.num_regions)
                                        return -EINVAL;
+                               info.index =
+                                       array_index_nospec(info.index,
+                                                       VFIO_PCI_NUM_REGIONS +
+                                                       vgpu->vdev.num_regions);
 
                                i = info.index - VFIO_PCI_NUM_REGIONS;