Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm: validate flags, etc

After reading a nice article on LWN[1], I went back and double checked
my handling of invalid-input checking. Turns out there were a couple
places I had missed.

Since the driver is fairly young, and the devices it supports are really
only just barely usable for basic stuff (serial console) with an
upstream kernel, I think we should fix this now and revert specific
parts of this patch later in the unlikely event that a regression is
reported.

[1] https://lwn.net/Articles/588444/

Signed-off-by: Rob Clark <robdclark@gmail.com>

Rob Clark 93ddb0d3 060530f1

+43 -3
+19 -1
drivers/gpu/drm/msm/msm_drv.c
··· 664 664 struct drm_file *file) 665 665 { 666 666 struct drm_msm_gem_new *args = data; 667 + 668 + if (args->flags & ~MSM_BO_FLAGS) { 669 + DRM_ERROR("invalid flags: %08x\n", args->flags); 670 + return -EINVAL; 671 + } 672 + 667 673 return msm_gem_new_handle(dev, file, args->size, 668 674 args->flags, &args->handle); 669 675 } ··· 682 676 struct drm_msm_gem_cpu_prep *args = data; 683 677 struct drm_gem_object *obj; 684 678 int ret; 679 + 680 + if (args->op & ~MSM_PREP_FLAGS) { 681 + DRM_ERROR("invalid op: %08x\n", args->op); 682 + return -EINVAL; 683 + } 685 684 686 685 obj = drm_gem_object_lookup(dev, file, args->handle); 687 686 if (!obj) ··· 742 731 struct drm_file *file) 743 732 { 744 733 struct drm_msm_wait_fence *args = data; 745 - return msm_wait_fence_interruptable(dev, args->fence, &TS(args->timeout)); 734 + 735 + if (args->pad) { 736 + DRM_ERROR("invalid pad: %08x\n", args->pad); 737 + return -EINVAL; 738 + } 739 + 740 + return msm_wait_fence_interruptable(dev, args->fence, 741 + &TS(args->timeout)); 746 742 } 747 743 748 744 static const struct drm_ioctl_desc msm_ioctls[] = {
+13 -2
drivers/gpu/drm/msm/msm_gem_submit.c
··· 23 23 * Cmdstream submission: 24 24 */ 25 25 26 - #define BO_INVALID_FLAGS ~(MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE) 27 26 /* make sure these don't conflict w/ MSM_SUBMIT_BO_x */ 28 27 #define BO_VALID 0x8000 29 28 #define BO_LOCKED 0x4000 ··· 76 77 goto out_unlock; 77 78 } 78 79 79 - if (submit_bo.flags & BO_INVALID_FLAGS) { 80 + if (submit_bo.flags & ~MSM_SUBMIT_BO_FLAGS) { 80 81 DRM_ERROR("invalid flags: %x\n", submit_bo.flags); 81 82 ret = -EINVAL; 82 83 goto out_unlock; ··· 365 366 ret = copy_from_user(&submit_cmd, userptr, sizeof(submit_cmd)); 366 367 if (ret) { 367 368 ret = -EFAULT; 369 + goto out; 370 + } 371 + 372 + /* validate input from userspace: */ 373 + switch (submit_cmd.type) { 374 + case MSM_SUBMIT_CMD_BUF: 375 + case MSM_SUBMIT_CMD_IB_TARGET_BUF: 376 + case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 377 + break; 378 + default: 379 + DRM_ERROR("invalid type: %08x\n", submit_cmd.type); 380 + ret = -EINVAL; 368 381 goto out; 369 382 } 370 383
+11
include/uapi/drm/msm_drm.h
··· 70 70 #define MSM_BO_WC 0x00020000 71 71 #define MSM_BO_UNCACHED 0x00040000 72 72 73 + #define MSM_BO_FLAGS (MSM_BO_SCANOUT | \ 74 + MSM_BO_GPU_READONLY | \ 75 + MSM_BO_CACHED | \ 76 + MSM_BO_WC | \ 77 + MSM_BO_UNCACHED) 78 + 73 79 struct drm_msm_gem_new { 74 80 uint64_t size; /* in */ 75 81 uint32_t flags; /* in, mask of MSM_BO_x */ ··· 91 85 #define MSM_PREP_READ 0x01 92 86 #define MSM_PREP_WRITE 0x02 93 87 #define MSM_PREP_NOSYNC 0x04 88 + 89 + #define MSM_PREP_FLAGS (MSM_PREP_READ | MSM_PREP_WRITE | MSM_PREP_NOSYNC) 94 90 95 91 struct drm_msm_gem_cpu_prep { 96 92 uint32_t handle; /* in */ ··· 161 153 */ 162 154 #define MSM_SUBMIT_BO_READ 0x0001 163 155 #define MSM_SUBMIT_BO_WRITE 0x0002 156 + 157 + #define MSM_SUBMIT_BO_FLAGS (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE) 158 + 164 159 struct drm_msm_gem_submit_bo { 165 160 uint32_t flags; /* in, mask of MSM_SUBMIT_BO_x */ 166 161 uint32_t handle; /* in, GEM handle */