⬢ DragonFlyBSD Kernel Audit
DF-3783 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/video/bktr/bktr_reg.h
+++ b/sys/dev/video/bktr/bktr_reg.h
@@ -454,6 +454,8 @@
     vm_offset_t vbibuffer;   /* Circular buffer holding VBI data for the user */
     vm_offset_t dma_prog;    /* RISC prog for single and/or even field capture*/
     vm_offset_t odd_dma_prog;/* RISC program for Odd field capture */
+	    vm_offset_t dma_prog_limit;	/* one dword past the usable end
+					   of the RISC program buffer being built (DF-3783) */
 
     /* the following definitions are common over all platforms */
     int		alloc_pages;	/* number of pages in bigbuf */
--- a/sys/dev/video/bktr/bktr_core.c
+++ b/sys/dev/video/bktr/bktr_core.c
@@ -2538,6 +2538,10 @@
 		    volatile u_char ** target_buffer, int cols ) {
 
  u_long flag, flag2;
+
+	/* DF-3783: never emit past the fixed-size program buffer */
+	if (*dma_prog + 4 > (volatile uint32_t *)bktr->dma_prog_limit)
+		return FALSE;
  struct meteor_pixfmt *pf = &pixfmt_table[ bktr->pixfmt ].public;
  u_int  skip, start_skip;
 
@@ -2664,6 +2668,11 @@
 	bktr->capcontrol = 3 << 2 |  3;
 
 	dma_prog = (uint32_t *) bktr->dma_prog;
+ 	bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16;
+	bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16;
+	bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16;
+	bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16;
+	bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16;
 
 	/* Construct Write */
 
@@ -2703,6 +2712,8 @@
 		*dma_prog++ = 0;  /* NULL WORD */
 		width = cols;
 		for (i = 0; i < (rows/interlace); i++) {
+		if (dma_prog + 5 > (volatile uint32_t *)bktr->dma_prog_limit)
+			break;	/* DF-3783: program buffer full */
 		    target = target_buffer;
 		    if ( notclipped(bktr, i, width)) {
 			split(bktr, &dma_prog, bktr->y2 - bktr->y, OP_WRITE,
@@ -2915,6 +2926,10 @@
 	        target_buffer = buffer + pitch; 
 
 		dma_prog = (uint32_t *) bktr->odd_dma_prog;
+		bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16;
+		bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16;
+		bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16;
+		bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16;
 
 		/* sync vre IRQ bit */
 		*dma_prog++ = OP_SYNC | BKTR_RESYNC | BKTR_FM1;
@@ -3052,6 +3067,8 @@
 		*dma_prog++ = 0;  /* NULL WORD */
 
 		for (i = 0; i < (rows/interlace) ; i++) {
+			if (dma_prog + 5 > (volatile uint32_t *)bktr->dma_prog_limit)
+				break;	/* DF-3783: program buffer full */
 			*dma_prog++ = inst;
 			*dma_prog++ = target_buffer;
 			*dma_prog++ = inst3;
@@ -3088,6 +3105,7 @@
 	OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt);
 
 	dma_prog = (uint32_t*) bktr->dma_prog;
+	bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16;
 
 	bktr->capcontrol =   1 << 6 | 1 << 4 |	3;
 
@@ -3124,6 +3142,10 @@
 	*dma_prog++ = 0;  /* NULL WORD */
 
 	for (i = 0; i < (rows/interlace ) ; i++) {
+		if (dma_prog + 6 > (volatile uint32_t *)bktr->dma_prog_limit)
+			break;	/* DF-3783: program buffer full */
+		if (dma_prog + 6 > (volatile uint32_t *)bktr->dma_prog_limit)
+			break;	/* DF-3783: program buffer full */
 		*dma_prog++ = inst;
 		*dma_prog++ = cols/2 | cols/2 << 16;
 		*dma_prog++ = target_buffer;
@@ -3223,6 +3245,8 @@
  	*dma_prog++ = 0;  /* NULL WORD */
  	       
  	for (i = 0; i < (rows/interlace )/2 ; i++) {
+ 		if (dma_prog + 8 > (volatile uint32_t *)bktr->dma_prog_limit)
+ 			break;	/* DF-3783: program buffer full */
 		*dma_prog++ = inst;
  		*dma_prog++ = cols/2 | (cols/2 << 16);
  		*dma_prog++ = target_buffer;
@@ -3271,6 +3295,8 @@
 		*dma_prog++ = 0;  /* NULL WORD */
 
 		for (i = 0; i < ((rows/interlace )/2 ) ; i++) {
+		    if (dma_prog + 8 > (volatile uint32_t *)bktr->dma_prog_limit)
+			    break;	/* DF-3783: program buffer full */
 		    *dma_prog++ = inst;
 		    *dma_prog++ = cols/2 | (cols/2 << 16);
          	    *dma_prog++ = target_buffer;