DF-4942 / fix.diff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | --- a/sys/dev/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c +++ b/sys/dev/drm/amd/display/dc/gpio/dce80/hw_translate_dce80.c @@ -170,28 +170,36 @@ * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK * directly in the create method */ case mmDC_GPIO_DDC1_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC1; return true; case mmDC_GPIO_DDC2_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC2; return true; case mmDC_GPIO_DDC3_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC3; return true; case mmDC_GPIO_DDC4_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC4; return true; case mmDC_GPIO_DDC5_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC5; return true; case mmDC_GPIO_DDC6_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC6; return true; case mmDC_GPIO_DDCVGA_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC_VGA; return true; /* GPIO_I2CPAD */ case mmDC_GPIO_I2CPAD_A: + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_I2C_PAD; return true; /* Not implemented */ @@ -377,8 +385,12 @@ break; case GPIO_ID_GPIO_PAD: info->offset = mmGPIOPAD_A; - info->mask = (1 << en); - result = (info->mask <= GPIO_GPIO_PAD_MAX); + /* validate the pin INDEX, not the derived mask + * (mask 1<<en was compared against GPIO_GPIO_PAD_MAX==30: + * valid pads 5..30 were rejected and en >= 32 hit UB) */ + result = (en <= GPIO_GPIO_PAD_MAX); + if (result) + info->mask = (1 << en); break; case GPIO_ID_VIP_PAD: default: --- a/sys/dev/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c +++ b/sys/dev/drm/amd/display/dc/gpio/dce120/hw_translate_dce120.c @@ -163,28 +163,36 @@ * in DdcHandle it will use GPIO_ID_DDC_DATA/GPIO_ID_DDC_CLOCK * directly in the create method */ case REG(DC_GPIO_DDC1_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC1; return true; case REG(DC_GPIO_DDC2_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC2; return true; case REG(DC_GPIO_DDC3_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC3; return true; case REG(DC_GPIO_DDC4_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC4; return true; case REG(DC_GPIO_DDC5_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC5; return true; case REG(DC_GPIO_DDC6_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC6; return true; case REG(DC_GPIO_DDCVGA_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_DDC_VGA; return true; /* GPIO_I2CPAD */ case REG(DC_GPIO_I2CPAD_A): + *id = GPIO_ID_DDC_DATA; *en = GPIO_DDC_LINE_I2C_PAD; return true; /* Not implemented */ --- a/sys/dev/drm/amd/display/dc/gpio/gpio_service.c +++ b/sys/dev/drm/amd/display/dc/gpio/gpio_service.c @@ -418,6 +418,17 @@ if (!service->translate.funcs->offset_to_id(offset, mask, &id, &en)) return NULL; + /* offset_to_id() used to leave *id unwritten for DDC-family + * offsets, and returns success for non-DDC domains (e.g. the + * GPIOPAD map yields en up to GPIO_GPIO_PAD_MAX = 30) while this + * consumer treats en as a gpio_ddc_line and lets the factory index + * ddc_data_regs[]/ddc_clk_regs[] (GPIO_DDC_LINE_COUNT = 8 entries) + * with it. Only accept a genuine DDC decode. */ + if (id != GPIO_ID_DDC_DATA) { + ASSERT_CRITICAL(false); + return NULL; + } + ddc = kzalloc(sizeof(struct ddc), GFP_KERNEL); if (!ddc) { |