Commit 477d70b6 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'vmwgfx-fixes-4.15' of git://people.freedesktop.org/~thomash/linux into drm-fixes

Two important fixes for vmwgfx.
The off-by-one fix could cause a malicious user to potentially crash the
kernel.
The framebuffer map cache fix can under some circumstances enable a user to
read from or write to freed pages.

* 'vmwgfx-fixes-4.15' of git://people.freedesktop.org/~thomash/linux:
  drm/vmwgfx: Potential off by one in vmw_view_add()
  drm/vmwgfx: Don't cache framebuffer maps
parents c59beeaf 0d9cac0c
...@@ -2731,6 +2731,8 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv, ...@@ -2731,6 +2731,8 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv,
} }
view_type = vmw_view_cmd_to_type(header->id); view_type = vmw_view_cmd_to_type(header->id);
if (view_type == vmw_view_max)
return -EINVAL;
cmd = container_of(header, typeof(*cmd), header); cmd = container_of(header, typeof(*cmd), header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter, user_surface_converter,
......
...@@ -697,7 +697,6 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane) ...@@ -697,7 +697,6 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane)
vps->pinned = 0; vps->pinned = 0;
/* Mapping is managed by prepare_fb/cleanup_fb */ /* Mapping is managed by prepare_fb/cleanup_fb */
memset(&vps->guest_map, 0, sizeof(vps->guest_map));
memset(&vps->host_map, 0, sizeof(vps->host_map)); memset(&vps->host_map, 0, sizeof(vps->host_map));
vps->cpp = 0; vps->cpp = 0;
...@@ -760,11 +759,6 @@ vmw_du_plane_destroy_state(struct drm_plane *plane, ...@@ -760,11 +759,6 @@ vmw_du_plane_destroy_state(struct drm_plane *plane,
/* Should have been freed by cleanup_fb */ /* Should have been freed by cleanup_fb */
if (vps->guest_map.virtual) {
DRM_ERROR("Guest mapping not freed\n");
ttm_bo_kunmap(&vps->guest_map);
}
if (vps->host_map.virtual) { if (vps->host_map.virtual) {
DRM_ERROR("Host mapping not freed\n"); DRM_ERROR("Host mapping not freed\n");
ttm_bo_kunmap(&vps->host_map); ttm_bo_kunmap(&vps->host_map);
......
...@@ -175,7 +175,7 @@ struct vmw_plane_state { ...@@ -175,7 +175,7 @@ struct vmw_plane_state {
int pinned; int pinned;
/* For CPU Blit */ /* For CPU Blit */
struct ttm_bo_kmap_obj host_map, guest_map; struct ttm_bo_kmap_obj host_map;
unsigned int cpp; unsigned int cpp;
}; };
......
...@@ -114,7 +114,7 @@ struct vmw_screen_target_display_unit { ...@@ -114,7 +114,7 @@ struct vmw_screen_target_display_unit {
bool defined; bool defined;
/* For CPU Blit */ /* For CPU Blit */
struct ttm_bo_kmap_obj host_map, guest_map; struct ttm_bo_kmap_obj host_map;
unsigned int cpp; unsigned int cpp;
}; };
...@@ -695,7 +695,8 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) ...@@ -695,7 +695,8 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
s32 src_pitch, dst_pitch; s32 src_pitch, dst_pitch;
u8 *src, *dst; u8 *src, *dst;
bool not_used; bool not_used;
struct ttm_bo_kmap_obj guest_map;
int ret;
if (!dirty->num_hits) if (!dirty->num_hits)
return; return;
...@@ -706,6 +707,13 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) ...@@ -706,6 +707,13 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
if (width == 0 || height == 0) if (width == 0 || height == 0)
return; return;
ret = ttm_bo_kmap(&ddirty->buf->base, 0, ddirty->buf->base.num_pages,
&guest_map);
if (ret) {
DRM_ERROR("Failed mapping framebuffer for blit: %d\n",
ret);
goto out_cleanup;
}
/* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */ /* Assume we are blitting from Host (display_srf) to Guest (dmabuf) */
src_pitch = stdu->display_srf->base_size.width * stdu->cpp; src_pitch = stdu->display_srf->base_size.width * stdu->cpp;
...@@ -713,7 +721,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) ...@@ -713,7 +721,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
src += ddirty->top * src_pitch + ddirty->left * stdu->cpp; src += ddirty->top * src_pitch + ddirty->left * stdu->cpp;
dst_pitch = ddirty->pitch; dst_pitch = ddirty->pitch;
dst = ttm_kmap_obj_virtual(&stdu->guest_map, &not_used); dst = ttm_kmap_obj_virtual(&guest_map, &not_used);
dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp; dst += ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp;
...@@ -772,6 +780,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty) ...@@ -772,6 +780,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
vmw_fifo_commit(dev_priv, sizeof(*cmd)); vmw_fifo_commit(dev_priv, sizeof(*cmd));
} }
ttm_bo_kunmap(&guest_map);
out_cleanup: out_cleanup:
ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX; ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
ddirty->right = ddirty->bottom = S32_MIN; ddirty->right = ddirty->bottom = S32_MIN;
...@@ -1109,9 +1118,6 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane, ...@@ -1109,9 +1118,6 @@ vmw_stdu_primary_plane_cleanup_fb(struct drm_plane *plane,
{ {
struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
if (vps->guest_map.virtual)
ttm_bo_kunmap(&vps->guest_map);
if (vps->host_map.virtual) if (vps->host_map.virtual)
ttm_bo_kunmap(&vps->host_map); ttm_bo_kunmap(&vps->host_map);
...@@ -1277,33 +1283,11 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, ...@@ -1277,33 +1283,11 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
*/ */
if (vps->content_fb_type == SEPARATE_DMA && if (vps->content_fb_type == SEPARATE_DMA &&
!(dev_priv->capabilities & SVGA_CAP_3D)) { !(dev_priv->capabilities & SVGA_CAP_3D)) {
struct vmw_framebuffer_dmabuf *new_vfbd;
new_vfbd = vmw_framebuffer_to_vfbd(new_fb);
ret = ttm_bo_reserve(&new_vfbd->buffer->base, false, false,
NULL);
if (ret)
goto out_srf_unpin;
ret = ttm_bo_kmap(&new_vfbd->buffer->base, 0,
new_vfbd->buffer->base.num_pages,
&vps->guest_map);
ttm_bo_unreserve(&new_vfbd->buffer->base);
if (ret) {
DRM_ERROR("Failed to map content buffer to CPU\n");
goto out_srf_unpin;
}
ret = ttm_bo_kmap(&vps->surf->res.backup->base, 0, ret = ttm_bo_kmap(&vps->surf->res.backup->base, 0,
vps->surf->res.backup->base.num_pages, vps->surf->res.backup->base.num_pages,
&vps->host_map); &vps->host_map);
if (ret) { if (ret) {
DRM_ERROR("Failed to map display buffer to CPU\n"); DRM_ERROR("Failed to map display buffer to CPU\n");
ttm_bo_kunmap(&vps->guest_map);
goto out_srf_unpin; goto out_srf_unpin;
} }
...@@ -1350,7 +1334,6 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, ...@@ -1350,7 +1334,6 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
stdu->display_srf = vps->surf; stdu->display_srf = vps->surf;
stdu->content_fb_type = vps->content_fb_type; stdu->content_fb_type = vps->content_fb_type;
stdu->cpp = vps->cpp; stdu->cpp = vps->cpp;
memcpy(&stdu->guest_map, &vps->guest_map, sizeof(vps->guest_map));
memcpy(&stdu->host_map, &vps->host_map, sizeof(vps->host_map)); memcpy(&stdu->host_map, &vps->host_map, sizeof(vps->host_map));
if (!stdu->defined) if (!stdu->defined)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment