diff mbox

drm/radeon: copy userspace cmd to local copy before processing it v3

Message ID 1360365230-19922-1-git-send-email-j.glisse@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jerome Glisse Feb. 8, 2013, 11:13 p.m. UTC
From: Jerome Glisse <jglisse@redhat.com>

In some rare case were packet is big enough to go over page boundary
we might not have copied yet the userspace data into the local copy
resulting in kernel reading garbage data.

Without this patch kernel might submit unprocessed/unrelocated cmd
to the GPU which might lead to GPU lockup.

v2: Make sure we do copy all the page and don't forget some when
    the packet count dw is bigger than 1 page
v3: Rebase patch against Linus master

Signed-off-by: Jerome Glisse <jglisse@redhat.com>
---
 drivers/gpu/drm/radeon/evergreen_cs.c | 35 ++++++++++++++++++++++++++++++++++-
 drivers/gpu/drm/radeon/r600_cs.c      | 19 ++++++++++++++++++-
 2 files changed, 52 insertions(+), 2 deletions(-)

Comments

Alex Deucher Feb. 8, 2013, 11:15 p.m. UTC | #1
On Fri, Feb 8, 2013 at 6:13 PM,  <j.glisse@gmail.com> wrote:
> From: Jerome Glisse <jglisse@redhat.com>
>
> In some rare case were packet is big enough to go over page boundary
> we might not have copied yet the userspace data into the local copy
> resulting in kernel reading garbage data.
>
> Without this patch kernel might submit unprocessed/unrelocated cmd
> to the GPU which might lead to GPU lockup.
>
> v2: Make sure we do copy all the page and don't forget some when
>     the packet count dw is bigger than 1 page
> v3: Rebase patch against Linus master
>
> Signed-off-by: Jerome Glisse <jglisse@redhat.com>

Reviewed-by: Alex Deucher <alexander.deucher@amd.com>

> ---
>  drivers/gpu/drm/radeon/evergreen_cs.c | 35 ++++++++++++++++++++++++++++++++++-
>  drivers/gpu/drm/radeon/r600_cs.c      | 19 ++++++++++++++++++-
>  2 files changed, 52 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
> index 7a44566..51ad74a 100644
> --- a/drivers/gpu/drm/radeon/evergreen_cs.c
> +++ b/drivers/gpu/drm/radeon/evergreen_cs.c
> @@ -1021,7 +1021,7 @@ static int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
>                               unsigned idx)
>  {
>         struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
> -       uint32_t header;
> +       uint32_t header, i, npages;
>
>         if (idx >= ib_chunk->length_dw) {
>                 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
> @@ -1052,6 +1052,11 @@ static int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
>                           pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
>                 return -EINVAL;
>         }
> +       /* make sure we copied packet fully from userspace */
> +       npages = ((idx + pkt->count + 1) >> 10) - (idx >> 10);
> +       for (i = 1; i <= npages; i++) {
> +               radeon_get_ib_value(p, (idx & 0xfffffc00) + i * 0x400);
> +       }
>         return 0;
>  }
>
> @@ -2909,12 +2914,16 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                 return -EINVAL;
>                         }
>                         if (tiled) {
> +                               /* make sure we copied packet fully from userspace */
> +                               radeon_get_ib_value(p, idx + 6);
>                                 dst_offset = ib[idx+1];
>                                 dst_offset <<= 8;
>
>                                 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
>                                 p->idx += count + 7;
>                         } else {
> +                               /* make sure we copied packet fully from userspace */
> +                               radeon_get_ib_value(p, idx + 2);
>                                 dst_offset = ib[idx+1];
>                                 dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
>
> @@ -2945,6 +2954,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                         switch (misc) {
>                                         case 0:
>                                                 /* L2T, frame to fields */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 9);
>                                                 if (idx_value & (1 << 31)) {
>                                                         DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
>                                                         return -EINVAL;
> @@ -2983,6 +2994,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                                 break;
>                                         case 1:
>                                                 /* L2T, T2L partial */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 11);
>                                                 if (p->family < CHIP_CAYMAN) {
>                                                         DRM_ERROR("L2T, T2L Partial is cayman only !\n");
>                                                         return -EINVAL;
> @@ -3005,6 +3018,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                                 break;
>                                         case 3:
>                                                 /* L2T, broadcast */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 9);
>                                                 if (idx_value & (1 << 31)) {
>                                                         DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
>                                                         return -EINVAL;
> @@ -3043,6 +3058,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                                 break;
>                                         case 4:
>                                                 /* L2T, T2L */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 8);
>                                                 /* detile bit */
>                                                 if (idx_value & (1 << 31)) {
>                                                         /* tiled src, linear dst */
> @@ -3079,6 +3096,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                                 break;
>                                         case 5:
>                                                 /* T2T partial */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 12);
>                                                 if (p->family < CHIP_CAYMAN) {
>                                                         DRM_ERROR("L2T, T2L Partial is cayman only !\n");
>                                                         return -EINVAL;
> @@ -3089,6 +3108,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                                 break;
>                                         case 7:
>                                                 /* L2T, broadcast */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 9);
>                                                 if (idx_value & (1 << 31)) {
>                                                         DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
>                                                         return -EINVAL;
> @@ -3132,6 +3153,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                 } else {
>                                         switch (misc) {
>                                         case 0:
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 8);
>                                                 /* detile bit */
>                                                 if (idx_value & (1 << 31)) {
>                                                         /* tiled src, linear dst */
> @@ -3176,6 +3199,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                         switch (misc) {
>                                         case 0:
>                                                 /* L2L, byte */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 4);
>                                                 src_offset = ib[idx+2];
>                                                 src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
>                                                 dst_offset = ib[idx+1];
> @@ -3198,6 +3223,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                                 break;
>                                         case 1:
>                                                 /* L2L, partial */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 8);
>                                                 if (p->family < CHIP_CAYMAN) {
>                                                         DRM_ERROR("L2L Partial is cayman only !\n");
>                                                         return -EINVAL;
> @@ -3211,6 +3238,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                                 break;
>                                         case 4:
>                                                 /* L2L, dw, broadcast */
> +                                               /* make sure we copied packet fully from userspace */
> +                                               radeon_get_ib_value(p, idx + 6);
>                                                 r = r600_dma_cs_next_reloc(p, &dst2_reloc);
>                                                 if (r) {
>                                                         DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
> @@ -3251,6 +3280,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                                         }
>                                 } else {
>                                         /* L2L, dw */
> +                                       /* make sure we copied packet fully from userspace */
> +                                       radeon_get_ib_value(p, idx + 4);
>                                         src_offset = ib[idx+2];
>                                         src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
>                                         dst_offset = ib[idx+1];
> @@ -3274,6 +3305,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
>                         }
>                         break;
>                 case DMA_PACKET_CONSTANT_FILL:
> +                       /* make sure we copied packet fully from userspace */
> +                       radeon_get_ib_value(p, idx + 3);
>                         r = r600_dma_cs_next_reloc(p, &dst_reloc);
>                         if (r) {
>                                 DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
> diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
> index 69ec24a..d36f9e6 100644
> --- a/drivers/gpu/drm/radeon/r600_cs.c
> +++ b/drivers/gpu/drm/radeon/r600_cs.c
> @@ -796,7 +796,7 @@ static int r600_cs_packet_parse(struct radeon_cs_parser *p,
>                         unsigned idx)
>  {
>         struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
> -       uint32_t header;
> +       uint32_t header, i, npages;
>
>         if (idx >= ib_chunk->length_dw) {
>                 DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
> @@ -827,6 +827,11 @@ static int r600_cs_packet_parse(struct radeon_cs_parser *p,
>                           pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
>                 return -EINVAL;
>         }
> +       /* make sure we copied packet fully from userspace */
> +       npages = ((idx + pkt->count + 1) >> 10) - (idx >> 10);
> +       for (i = 1; i <= npages; i++) {
> +               radeon_get_ib_value(p, (idx & 0xfffffc00) + i * 0x400);
> +       }
>         return 0;
>  }
>
> @@ -2623,12 +2628,16 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
>                                 return -EINVAL;
>                         }
>                         if (tiled) {
> +                               /* make sure we copied packet fully from userspace */
> +                               radeon_get_ib_value(p, idx + 4);
>                                 dst_offset = ib[idx+1];
>                                 dst_offset <<= 8;
>
>                                 ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
>                                 p->idx += count + 5;
>                         } else {
> +                               /* make sure we copied packet fully from userspace */
> +                               radeon_get_ib_value(p, idx + 2);
>                                 dst_offset = ib[idx+1];
>                                 dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
>
> @@ -2654,6 +2663,8 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
>                                 return -EINVAL;
>                         }
>                         if (tiled) {
> +                               /* make sure we copied packet fully from userspace */
> +                               radeon_get_ib_value(p, idx + 6);
>                                 idx_value = radeon_get_ib_value(p, idx + 2);
>                                 /* detile bit */
>                                 if (idx_value & (1 << 31)) {
> @@ -2680,6 +2691,8 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
>                                 p->idx += 7;
>                         } else {
>                                 if (p->family >= CHIP_RV770) {
> +                                       /* make sure we copied packet fully from userspace */
> +                                       radeon_get_ib_value(p, idx + 4);
>                                         src_offset = ib[idx+2];
>                                         src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
>                                         dst_offset = ib[idx+1];
> @@ -2691,6 +2704,8 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
>                                         ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
>                                         p->idx += 5;
>                                 } else {
> +                                       /* make sure we copied packet fully from userspace */
> +                                       radeon_get_ib_value(p, idx + 3);
>                                         src_offset = ib[idx+2];
>                                         src_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
>                                         dst_offset = ib[idx+1];
> @@ -2715,6 +2730,8 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p)
>                         }
>                         break;
>                 case DMA_PACKET_CONSTANT_FILL:
> +                       /* make sure we copied packet fully from userspace */
> +                       radeon_get_ib_value(p, idx + 3);
>                         if (p->family < CHIP_RV770) {
>                                 DRM_ERROR("Constant Fill is 7xx only !\n");
>                                 return -EINVAL;
> --
> 1.7.11.7
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff mbox

Patch

diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 7a44566..51ad74a 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -1021,7 +1021,7 @@  static int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
 			      unsigned idx)
 {
 	struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-	uint32_t header;
+	uint32_t header, i, npages;
 
 	if (idx >= ib_chunk->length_dw) {
 		DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
@@ -1052,6 +1052,11 @@  static int evergreen_cs_packet_parse(struct radeon_cs_parser *p,
 			  pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
 		return -EINVAL;
 	}
+	/* make sure we copied packet fully from userspace */
+	npages = ((idx + pkt->count + 1) >> 10) - (idx >> 10);
+	for (i = 1; i <= npages; i++) {
+		radeon_get_ib_value(p, (idx & 0xfffffc00) + i * 0x400);
+	}
 	return 0;
 }
 
@@ -2909,12 +2914,16 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 				return -EINVAL;
 			}
 			if (tiled) {
+				/* make sure we copied packet fully from userspace */
+				radeon_get_ib_value(p, idx + 6);
 				dst_offset = ib[idx+1];
 				dst_offset <<= 8;
 
 				ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
 				p->idx += count + 7;
 			} else {
+				/* make sure we copied packet fully from userspace */
+				radeon_get_ib_value(p, idx + 2);
 				dst_offset = ib[idx+1];
 				dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
 
@@ -2945,6 +2954,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 					switch (misc) {
 					case 0:
 						/* L2T, frame to fields */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 9);
 						if (idx_value & (1 << 31)) {
 							DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
 							return -EINVAL;
@@ -2983,6 +2994,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 						break;
 					case 1:
 						/* L2T, T2L partial */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 11);
 						if (p->family < CHIP_CAYMAN) {
 							DRM_ERROR("L2T, T2L Partial is cayman only !\n");
 							return -EINVAL;
@@ -3005,6 +3018,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 						break;
 					case 3:
 						/* L2T, broadcast */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 9);
 						if (idx_value & (1 << 31)) {
 							DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
 							return -EINVAL;
@@ -3043,6 +3058,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 						break;
 					case 4:
 						/* L2T, T2L */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 8);
 						/* detile bit */
 						if (idx_value & (1 << 31)) {
 							/* tiled src, linear dst */
@@ -3079,6 +3096,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 						break;
 					case 5:
 						/* T2T partial */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 12);
 						if (p->family < CHIP_CAYMAN) {
 							DRM_ERROR("L2T, T2L Partial is cayman only !\n");
 							return -EINVAL;
@@ -3089,6 +3108,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 						break;
 					case 7:
 						/* L2T, broadcast */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 9);
 						if (idx_value & (1 << 31)) {
 							DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
 							return -EINVAL;
@@ -3132,6 +3153,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 				} else {
 					switch (misc) {
 					case 0:
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 8);
 						/* detile bit */
 						if (idx_value & (1 << 31)) {
 							/* tiled src, linear dst */
@@ -3176,6 +3199,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 					switch (misc) {
 					case 0:
 						/* L2L, byte */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 4);
 						src_offset = ib[idx+2];
 						src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
 						dst_offset = ib[idx+1];
@@ -3198,6 +3223,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 						break;
 					case 1:
 						/* L2L, partial */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 8);
 						if (p->family < CHIP_CAYMAN) {
 							DRM_ERROR("L2L Partial is cayman only !\n");
 							return -EINVAL;
@@ -3211,6 +3238,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 						break;
 					case 4:
 						/* L2L, dw, broadcast */
+						/* make sure we copied packet fully from userspace */
+						radeon_get_ib_value(p, idx + 6);
 						r = r600_dma_cs_next_reloc(p, &dst2_reloc);
 						if (r) {
 							DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
@@ -3251,6 +3280,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 					}
 				} else {
 					/* L2L, dw */
+					/* make sure we copied packet fully from userspace */
+					radeon_get_ib_value(p, idx + 4);
 					src_offset = ib[idx+2];
 					src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
 					dst_offset = ib[idx+1];
@@ -3274,6 +3305,8 @@  int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
 			}
 			break;
 		case DMA_PACKET_CONSTANT_FILL:
+			/* make sure we copied packet fully from userspace */
+			radeon_get_ib_value(p, idx + 3);
 			r = r600_dma_cs_next_reloc(p, &dst_reloc);
 			if (r) {
 				DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 69ec24a..d36f9e6 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -796,7 +796,7 @@  static int r600_cs_packet_parse(struct radeon_cs_parser *p,
 			unsigned idx)
 {
 	struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
-	uint32_t header;
+	uint32_t header, i, npages;
 
 	if (idx >= ib_chunk->length_dw) {
 		DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
@@ -827,6 +827,11 @@  static int r600_cs_packet_parse(struct radeon_cs_parser *p,
 			  pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw);
 		return -EINVAL;
 	}
+	/* make sure we copied packet fully from userspace */
+	npages = ((idx + pkt->count + 1) >> 10) - (idx >> 10);
+	for (i = 1; i <= npages; i++) {
+		radeon_get_ib_value(p, (idx & 0xfffffc00) + i * 0x400);
+	}
 	return 0;
 }
 
@@ -2623,12 +2628,16 @@  int r600_dma_cs_parse(struct radeon_cs_parser *p)
 				return -EINVAL;
 			}
 			if (tiled) {
+				/* make sure we copied packet fully from userspace */
+				radeon_get_ib_value(p, idx + 4);
 				dst_offset = ib[idx+1];
 				dst_offset <<= 8;
 
 				ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
 				p->idx += count + 5;
 			} else {
+				/* make sure we copied packet fully from userspace */
+				radeon_get_ib_value(p, idx + 2);
 				dst_offset = ib[idx+1];
 				dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
 
@@ -2654,6 +2663,8 @@  int r600_dma_cs_parse(struct radeon_cs_parser *p)
 				return -EINVAL;
 			}
 			if (tiled) {
+				/* make sure we copied packet fully from userspace */
+				radeon_get_ib_value(p, idx + 6);
 				idx_value = radeon_get_ib_value(p, idx + 2);
 				/* detile bit */
 				if (idx_value & (1 << 31)) {
@@ -2680,6 +2691,8 @@  int r600_dma_cs_parse(struct radeon_cs_parser *p)
 				p->idx += 7;
 			} else {
 				if (p->family >= CHIP_RV770) {
+					/* make sure we copied packet fully from userspace */
+					radeon_get_ib_value(p, idx + 4);
 					src_offset = ib[idx+2];
 					src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
 					dst_offset = ib[idx+1];
@@ -2691,6 +2704,8 @@  int r600_dma_cs_parse(struct radeon_cs_parser *p)
 					ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
 					p->idx += 5;
 				} else {
+					/* make sure we copied packet fully from userspace */
+					radeon_get_ib_value(p, idx + 3);
 					src_offset = ib[idx+2];
 					src_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
 					dst_offset = ib[idx+1];
@@ -2715,6 +2730,8 @@  int r600_dma_cs_parse(struct radeon_cs_parser *p)
 			}
 			break;
 		case DMA_PACKET_CONSTANT_FILL:
+			/* make sure we copied packet fully from userspace */
+			radeon_get_ib_value(p, idx + 3);
 			if (p->family < CHIP_RV770) {
 				DRM_ERROR("Constant Fill is 7xx only !\n");
 				return -EINVAL;