From d3170f303027138da12921f5b02ae6ce7e43169d Mon Sep 17 00:00:00 2001 From: Robert Noland Date: Sat, 6 Sep 2008 19:09:41 -0400 Subject: [PATCH] [FreeBSD] This eliminates a potential panic, but can't be pushed to master. --- shared-core/i915_dma.c | 75 +++++++++++++++++++++++++++++++++-------------- 1 files changed, 52 insertions(+), 23 deletions(-) diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 619e6ac..c3be9aa 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -470,20 +470,15 @@ static int i915_emit_cmds(struct drm_device *dev, int __user *buffer, for (i = 0; i < dwords;) { int cmd, sz; - if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) - return -EINVAL; - + cmd = buffer[i]; if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) return -EINVAL; OUT_RING(cmd); while (++i, --sz) { - if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], - sizeof(cmd))) { - return -EINVAL; - } OUT_RING(cmd); + cmd = buffer[i]; } } @@ -503,10 +498,7 @@ int i915_emit_box(struct drm_device * dev, struct drm_clip_rect box; RING_LOCALS; - if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { - return -EFAULT; - } - + box = boxes[i]; if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", box.x1, box.y1, box.x2, box.y2); @@ -781,6 +773,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_batchbuffer_t *batch = data; + size_t cliplen; int ret; if (!dev_priv->allow_batchbuffer) { @@ -793,14 +786,29 @@ static int i915_batchbuffer(struct drm_device *dev, void *data, LOCK_TEST_WITH_RETURN(dev, file_priv); + DRM_UNLOCK(); + cliplen = batch->num_cliprects * sizeof(drm_clip_rect_t); if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, - batch->num_cliprects * - sizeof(struct drm_clip_rect))) + cliplen)) { + DRM_LOCK(); return -EFAULT; - + } + if (batch->num_cliprects) { + ret = vslock(batch->cliprects, cliplen); + if (ret) { + DRM_ERROR("Fault wiring cliprects\n"); + DRM_LOCK(); + return -EFAULT; + } + } + DRM_LOCK(); ret = i915_dispatch_batchbuffer(dev, batch); sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + DRM_UNLOCK(); + if (batch->num_cliprects) + vsunlock(batch->cliprects, cliplen); + DRM_LOCK(); return ret; } @@ -811,6 +819,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; drm_i915_cmdbuffer_t *cmdbuf = data; + size_t cliplen; int ret; DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", @@ -818,22 +827,42 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, LOCK_TEST_WITH_RETURN(dev, file_priv); + DRM_UNLOCK(); + cliplen = cmdbuf->num_cliprects * sizeof(drm_clip_rect_t); if (cmdbuf->num_cliprects && - DRM_VERIFYAREA_READ(cmdbuf->cliprects, - cmdbuf->num_cliprects * - sizeof(struct drm_clip_rect))) { + DRM_VERIFYAREA_READ(cmdbuf->cliprects, cliplen)) { DRM_ERROR("Fault accessing cliprects\n"); + DRM_LOCK(); return -EFAULT; } - + if (cmdbuf->num_cliprects) { + ret = vslock(cmdbuf->cliprects, cliplen); + if (ret) { + DRM_ERROR("Fault wiring cliprects\n"); + DRM_LOCK(); + return -EFAULT; + } + ret = vslock(cmdbuf->buf, cmdbuf->sz); + if (ret) { + vsunlock(cmdbuf->cliprects, cliplen); + DRM_ERROR("Fault wiring cmds\n"); + DRM_LOCK(); + return -EFAULT; + } + } + DRM_LOCK(); ret = i915_dispatch_cmdbuffer(dev, cmdbuf); - if (ret) { + if (ret == 0) + sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + else DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); - return ret; + DRM_UNLOCK(); + if (cmdbuf->num_cliprects) { + vsunlock(cmdbuf->buf, cmdbuf->sz); + vsunlock(cmdbuf->cliprects, cliplen); } - - sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); - return 0; + DRM_LOCK(); + return (ret); } #if defined(DRM_DEBUG_CODE) -- 1.5.6