Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
	if (view_type == vmw_view_max)
		return -EINVAL;
	cmd = container_of(header, typeof(*cmd), header);
	ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
				user_surface_converter,
+0 −6
Original line number Diff line number Diff line
@@ -697,7 +697,6 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane)
	vps->pinned = 0;

	/* 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));
	vps->cpp = 0;

@@ -760,11 +759,6 @@ vmw_du_plane_destroy_state(struct drm_plane *plane,


	/* 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) {
		DRM_ERROR("Host mapping not freed\n");
		ttm_bo_kunmap(&vps->host_map);
+1 −1
Original line number Diff line number Diff line
@@ -175,7 +175,7 @@ struct vmw_plane_state {
	int pinned;

	/* For CPU Blit */
	struct ttm_bo_kmap_obj host_map, guest_map;
	struct ttm_bo_kmap_obj host_map;
	unsigned int cpp;
};

+12 −29
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ struct vmw_screen_target_display_unit {
	bool defined;

	/* For CPU Blit */
	struct ttm_bo_kmap_obj host_map, guest_map;
	struct ttm_bo_kmap_obj host_map;
	unsigned int cpp;
};

@@ -695,7 +695,8 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
	s32 src_pitch, dst_pitch;
	u8 *src, *dst;
	bool not_used;

	struct ttm_bo_kmap_obj guest_map;
	int ret;

	if (!dirty->num_hits)
		return;
@@ -706,6 +707,13 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
	if (width == 0 || height == 0)
		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) */
	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)
	src += ddirty->top * src_pitch + ddirty->left * stdu->cpp;

	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;


@@ -772,6 +780,7 @@ static void vmw_stdu_dmabuf_cpu_commit(struct vmw_kms_dirty *dirty)
		vmw_fifo_commit(dev_priv, sizeof(*cmd));
	}

	ttm_bo_kunmap(&guest_map);
out_cleanup:
	ddirty->left = ddirty->top = ddirty->fb_left = ddirty->fb_top = S32_MAX;
	ddirty->right = ddirty->bottom = S32_MIN;
@@ -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);

	if (vps->guest_map.virtual)
		ttm_bo_kunmap(&vps->guest_map);

	if (vps->host_map.virtual)
		ttm_bo_kunmap(&vps->host_map);

@@ -1277,33 +1283,11 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane,
	 */
	if (vps->content_fb_type == SEPARATE_DMA &&
	    !(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,
				  vps->surf->res.backup->base.num_pages,
				  &vps->host_map);
		if (ret) {
			DRM_ERROR("Failed to map display buffer to CPU\n");
			ttm_bo_kunmap(&vps->guest_map);
			goto out_srf_unpin;
		}

@@ -1350,7 +1334,6 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
	stdu->display_srf = vps->surf;
	stdu->content_fb_type = vps->content_fb_type;
	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));

	if (!stdu->defined)