⬢ DragonFlyBSD Kernel Audit
DF-3856 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/radeon_combios.c
+++ b/sys/dev/drm/radeon/radeon_combios.c
@@ -654,8 +654,11 @@
 				clk = RBIOS8(offset + 3 + (i * 5) + 3);
 				data = RBIOS8(offset + 3 + (i * 5) + 4);
 				/* gpiopad */
-				i2c = combios_setup_i2c_bus(rdev, DDC_MONID,
-							    (1 << clk), (1 << data));
+				if ((clk < 32) && (data < 32))
+					i2c = combios_setup_i2c_bus(rdev, DDC_MONID,
+								    (1 << clk), (1 << data));
+				else
+					i2c.valid = false;
 				break;
 			}
 		}
@@ -2683,7 +2686,7 @@
 				i2c_bus.hw_capable = true;
 				i2c_bus.mm_i2c = true;
 				i2c_bus.i2c_id = 0xa0;
-			} else if (gpio == DDC_GPIO)
+			} else if ((gpio == DDC_GPIO) && (clk_bit < 32) && (data_bit < 32))
 				i2c_bus = combios_setup_i2c_bus(rdev, gpio, 1 << clk_bit, 1 << data_bit);
 			else
 				i2c_bus = combios_setup_i2c_bus(rdev, gpio, 0, 0);
@@ -3100,8 +3103,17 @@
 				WREG32_PLL(addr, val);
 				break;
 			case 1:
-				shift = RBIOS8(offset) * 8;
+				shift = RBIOS8(offset);
 				offset++;
+				if (shift > 3) {
+					/* shift >= 32 bits is undefined behavior;
+					 * skip the 2 operand bytes and the write */
+					DRM_ERROR("combios pll table: bad shift %u\n",
+						  (unsigned)shift);
+					offset += 2;
+					break;
+				}
+				shift *= 8;
 				and_mask = RBIOS8(offset) << shift;
 				and_mask |= ~(0xff << shift);
 				offset++;