⬢ DragonFlyBSD Kernel Audit
DF-4787 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/amd/display/dc/gpio/gpio_service.c
+++ b/sys/dev/drm/amd/display/dc/gpio/gpio_service.c
@@ -241,36 +241,53 @@ enum gpio_result dal_gpio_service_open(
 	struct hw_gpio_pin *pin;
 
 	if (!service->busyness[id]) {
 		ASSERT_CRITICAL(false);
 		return GPIO_RESULT_OPEN_FAILED;
 	}
 
+	if (en >= service->factory.number_of_pins[id]) {
+		ASSERT_CRITICAL(false);
+		return GPIO_RESULT_INVALID_DATA;
+	}
+
 	switch (id) {
 	case GPIO_ID_DDC_DATA:
+		if (!service->factory.funcs->create_ddc_data) {
+			ASSERT_CRITICAL(false);
+			return GPIO_RESULT_NON_SPECIFIC_ERROR;
+		}
 		pin = service->factory.funcs->create_ddc_data(
 			service->ctx, id, en);
-		service->factory.funcs->define_ddc_registers(pin, en);
 	break;
 	case GPIO_ID_DDC_CLOCK:
+		if (!service->factory.funcs->create_ddc_clock) {
+			ASSERT_CRITICAL(false);
+			return GPIO_RESULT_NON_SPECIFIC_ERROR;
+		}
 		pin = service->factory.funcs->create_ddc_clock(
 			service->ctx, id, en);
-		service->factory.funcs->define_ddc_registers(pin, en);
 	break;
 	case GPIO_ID_GENERIC:
+		if (!service->factory.funcs->create_generic) {
+			ASSERT_CRITICAL(false);
+			return GPIO_RESULT_NON_SPECIFIC_ERROR;
+		}
 		pin = service->factory.funcs->create_generic(
 			service->ctx, id, en);
 	break;
 	case GPIO_ID_HPD:
+		if (!service->factory.funcs->create_hpd) {
+			ASSERT_CRITICAL(false);
+			return GPIO_RESULT_NON_SPECIFIC_ERROR;
+		}
 		pin = service->factory.funcs->create_hpd(
 			service->ctx, id, en);
-		service->factory.funcs->define_hpd_registers(pin, en);
 	break;
 	case GPIO_ID_SYNC:
+		if (!service->factory.funcs->create_sync) {
+			ASSERT_CRITICAL(false);
+			return GPIO_RESULT_NON_SPECIFIC_ERROR;
+		}
 		pin = service->factory.funcs->create_sync(
 			service->ctx, id, en);
 	break;
 	case GPIO_ID_GSL:
+		if (!service->factory.funcs->create_gsl) {
+			ASSERT_CRITICAL(false);
+			return GPIO_RESULT_NON_SPECIFIC_ERROR;
+		}
 		pin = service->factory.funcs->create_gsl(
 			service->ctx, id, en);
 	break;
 	default:
 		ASSERT_CRITICAL(false);
 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
@@ -281,6 +298,19 @@ enum gpio_result dal_gpio_service_open(
 		return GPIO_RESULT_NON_SPECIFIC_ERROR;
 	}
 
+	/* register tables can only be defined for a successfully created pin */
+	switch (id) {
+	case GPIO_ID_DDC_DATA:
+	case GPIO_ID_DDC_CLOCK:
+		service->factory.funcs->define_ddc_registers(pin, en);
+		break;
+	case GPIO_ID_HPD:
+		service->factory.funcs->define_hpd_registers(pin, en);
+		break;
+	default:
+		break;
+	}
+
 	if (!pin->funcs->open(pin, mode)) {
 		ASSERT_CRITICAL(false);
 		dal_gpio_service_close(service, &pin);
 		return GPIO_RESULT_OPEN_FAILED;
 	}