drm/vmwgfx: Fix potential Spectre v1
Subsystems (3)
PATCH 1/1 drm/vmwgfx: Fix potential Spectre v1
arg.version 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/vmwgfx/vmwgfx_execbuf.c:4526 vmw_execbuf_ioctl() warn:
potential spectre issue 'copy_offset' [w]
Fix this by sanitizing arg.version before using it to index copy_offset
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
--- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +5 -2
@@ -25,6 +25,7 @@* **************************************************************************/ #include <linux/sync_file.h> +#include <linux/nospec.h> #include "vmwgfx_drv.h" #include "vmwgfx_reg.h"
@@ -4520,8 +4521,10 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,return -EINVAL ; } -if (arg.version >1 && -copy_from_user (&arg.context_handle, +if (arg.version >=ARRAY_SIZE (copy_offset)) +return -EFAULT ; + arg.version =array_index_nospec (arg.version,ARRAY_SIZE (copy_offset)); +if (copy_from_user (&arg.context_handle, (void __user *) (data + copy_offset[0 ]), copy_offset[arg.version -1 ] - copy_offset[0 ]) !=0 )
Signature · 1 line
2.7.4
Looks good to me based on my limited understanding. Thomas/Sinclair can could you please review and then we can include this in drm-fixes.
Thanks,
Deepak
Quoted 67 lines
arg.version 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/vmwgfx/vmwgfx_execbuf.c:4526vmw_execbuf_ioctl()warn:
potential spectre issue 'copy_offset' [w]Fix this by sanitizing arg.version before using it to index
copy_offsetNotice 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://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fmarc.i
nfo%2F%3Fl%3Dlinux- kernel%26m%3D152449131114778%26w%3D2&data=02%7C01%7Clinux- graphics- maintainer%40vmware.com%7Cf010b707b8ef4896c1a908d603aebcc6%7Cb39 138ca3cee4b4aa4d6cd83d9dd62f0%7C1%7C0%7C636700446365603728& sdata=0D8lnUScxOmCCWXLHh8Otc3o%2F1yF1SxgGwIklRdMlXY%3D&re served=0Signed-off-by Gustavo A. R. Silva <[email protected]>--- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +1
-0@@ -25,6 +25,7 @@* ********************************************************** ****************/ #include <linux/sync_file.h> +#include <linux/nospec.h> #include "
vmwgfx_drv.h"
#include "vmwgfx_reg.h"drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +4
-2@@ -4520,8 +4521,10 @@ int vmw_execbuf_ioctl(struct drm_device *dev,unsigned long data, return -EINVAL; } -if (arg.version >1 && -copy_from_user (&arg.context_handle, +if (arg.version >=ARRAY_SIZE (copy_offset)) +return -EFAULT ; + arg.version =array_index_nospec (arg.version,ARRAY_SIZE (copy_offset)); + if (copy_from_user(&arg.context_handle, (void __user *) (data + copy_offset[0]),drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +0
-1copy_offset[arg.version -1 ] - copy_offset[0]) != 0) --2.7.4
_______________________________________________
Sent to [email protected]
Quoted 50 lines · Deepak Singh Rawat
Looks good to me based on my limited understanding. Thomas/Sinclair can could you please review and then we can include this in drm-fixes.
Thanks,
DeepakQuoted 44 lines
arg.version 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/vmwgfx/vmwgfx_execbuf.c:4526vmw_execbuf_ioctl()warn:
potential spectre issue 'copy_offset' [w]Fix this by sanitizing arg.version before using it to index
copy_offsetNotice 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]
Signed-off-by Gustavo A. R. Silva <[email protected]>--- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +1
-0@@ -25,6 +25,7 @@* ********************************************************** ****************/ #include <linux/sync_file.h> +#include <linux/nospec.h> #include "vmwgfx_drv.h" #include "vmwgfx_reg.h"drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +0
-0@@ -4520,8 +4521,10 @@ int vmw_execbuf_ioctl(struct drm_device *dev,unsigned long data, return -EINVAL; }
Quoted 4 lines
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data, · line 4525
Quoted 4 lines
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +2
-2-if (arg.version >1 && - copy_from_user(&arg.context_handle, +if (arg.version >=ARRAY_SIZE (copy_offset)) +return -EFAULT ;
I must admit my understanding of spectre workings in this case is limited, but why do you need to compare arg.version against ARRAY_SIZE here, when it is already checked against DRM_VMW_EXECBUF_VERSION earlier?
Quoted 6 lines
Quoted 6 lines
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +2
-0+ arg.version =array_index_nospec (arg.version,ARRAY_SIZE (copy_offset)); + if (copy_from_user(&arg.context_handle, (void __user *) (data + copy_offset[0]),copy_offset[arg.version - 1] - copy_offset[0]) != 0)
Similarly, we want to perform this copy iff arg.version > 1. Why did you remove that check?
Thanks,
Thomas
Quoted 5 lines
Quoted 5 lines
--
2.7.4_______________________________________________
Sent to [email protected]
_______________________________________________
dri-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi all,
Quoted 7 lines · Thomas Hellstrom
Quoted 7 lines
Quoted 7 lines
#include "
vmwgfx_drv.h"
#include "vmwgfx_reg.h"(quoted diff) +0
-0@@ -4520,8 +4521,10 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data, return -EINVAL; }
Quoted 8 lines
Quoted 4 lines
Review int vmw_execbuf_ioctl(struct drm_device *dev, · line 4526
Quoted 4 lines
(quoted diff) +2
-2- if (arg.version > 1 && - copy_from_user(&arg.context_handle, + if (arg.version >= ARRAY_SIZE(copy_offset)) + return -EFAULT;I must admit my understanding of spectre workings in this case is limited, but why do you need to compare arg.version against
ARRAY_SIZEhere, when it is already checked againstDRM_VMW_EXECBUF_VERSIONearlier?
Oh, I wasn't aware of the value in DRM_VMW_EXECBUF_VERSION. But as arg.version is used to index copy_offset, it is safer to compare its value against the actual size of copy_offset.
So, what do you think if I replace DRM_VMW_EXECBUF_VERSION with ARRAY_SIZE instead of adding a new check against ARRAY_SIZE?
Something like:
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +3 -1
@@ -25,6 +25,7 @@* **************************************************************************/ #include <linux/sync_file.h> +#include <linux/nospec.h> #include "vmwgfx_drv.h" #include "vmwgfx_reg.h"
@@ -4514,11 +4515,12 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data,* arg.version. */ -if (unlikely (arg.version >DRM_VMW_EXECBUF_VERSION || +if (unlikely (arg.version >ARRAY_SIZE (copy_offset) || arg.version ==0 )) {DRM_ERROR ("Incorrect execbuf version.\n" );return -EINVAL ; } + arg.version =array_index_nospec (arg.version,ARRAY_SIZE (copy_offset));if (arg.version >1 && copy_from_user(&arg.context_handle,
Quoted 11 lines
Quoted 8 lines
Quoted 8 lines
(quoted diff) +2
-0+ arg.version = array_index_nospec(arg.version, ARRAY_SIZE(copy_offset)); + if (copy_from_user(&arg.context_handle, (void __user *) (data + copy_offset[0]),copy_offset[arg.version - 1] -
copy_offset[0]) != 0)Similarly, we want to perform this copy iff arg.version > 1. Why did you remove that check?
Yeah, this check must remain in place. I will add it back and send v2.
Thanks for the feedback!
--
Gustavo