]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
drm/ioctl: Fix Spectre v1 vulnerabilities
authorGustavo A. R. Silva <gustavo@embeddedor.com>
Thu, 20 Dec 2018 00:00:15 +0000 (18:00 -0600)
committerStefan Bader <stefan.bader@canonical.com>
Wed, 24 Apr 2019 08:09:11 +0000 (10:09 +0200)
nr is 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/drm_ioctl.c:805 drm_ioctl() warn: potential spectre issue 'dev->driver->ioctls' [r]
drivers/gpu/drm/drm_ioctl.c:810 drm_ioctl() warn: potential spectre issue 'drm_ioctls' [r] (local cap)
drivers/gpu/drm/drm_ioctl.c:892 drm_ioctl_flags() warn: potential spectre issue 'drm_ioctls' [r] (local cap)

Fix this by sanitizing nr before using it to index dev->driver->ioctls
and drm_ioctls.

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: Daniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20181220000015.GA18973@embeddedor
CVE-2017-5753

(cherry picked from commit 505b5240329b922f21f91d5b5d1e535c805eca6d)
Signed-off-by: Juerg Haefliger <juergh@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
drivers/gpu/drm/drm_ioctl.c

index 4aafe4802099023aea622521d3dffb8387f173bb..9e80537c288b013278f63c6c6af3a34b641e84b2 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <linux/pci.h>
 #include <linux/export.h>
+#include <linux/nospec.h>
 
 /**
  * DOC: getunique and setversion story
@@ -784,13 +785,17 @@ long drm_ioctl(struct file *filp,
 
        if (is_driver_ioctl) {
                /* driver ioctl */
-               if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls)
+               unsigned int index = nr - DRM_COMMAND_BASE;
+
+               if (index >= dev->driver->num_ioctls)
                        goto err_i1;
-               ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+               index = array_index_nospec(index, dev->driver->num_ioctls);
+               ioctl = &dev->driver->ioctls[index];
        } else {
                /* core ioctl */
                if (nr >= DRM_CORE_IOCTL_COUNT)
                        goto err_i1;
+               nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT);
                ioctl = &drm_ioctls[nr];
        }
 
@@ -872,6 +877,7 @@ bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
 
        if (nr >= DRM_CORE_IOCTL_COUNT)
                return false;
+       nr = array_index_nospec(nr, DRM_CORE_IOCTL_COUNT);
 
        *flags = drm_ioctls[nr].flags;
        return true;