[bug report] drm/amd/display: Read AUX channel even if only status byte is returned

Leo Li sunpeng.li at amd.com
Tue Jul 31 19:48:15 UTC 2018



On 2018-07-31 02:24 PM, Dan Carpenter wrote:
> [ Potential security issue, if I'm reading the code correctly.  I don't
>    really know the code and I haven't looked at the larger context. -dan ]
> 
> Hello Leo (Sunpeng) Li,
> 
> The patch edf6ffe4f47e: "drm/amd/display: Read AUX channel even if
> only status byte is returned" from Jun 26, 2018, leads to the
> following static checker warning:
> 
> 	drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_ddc.c:673 dc_link_aux_transfer()
> 	warn: 'returned_bytes' is unsigned
> 
> drivers/gpu/drm/amd/amdgpu/../display/dc/core/dc_link_ddc.c
>     634  int dc_link_aux_transfer(struct ddc_service *ddc,
>     635                               unsigned int address,
>     636                               uint8_t *reply,
>     637                               void *buffer,
>     638                               unsigned int size,
>     639                               enum aux_transaction_type type,
>     640                               enum i2caux_transaction_action action)
>     641  {
>     642          struct ddc *ddc_pin = ddc->ddc_pin;
>     643          struct engine *engine;
>     644          struct aux_engine *aux_engine;
>     645          enum aux_channel_operation_result operation_result;
>     646          struct aux_request_transaction_data aux_req;
>     647          struct aux_reply_transaction_data aux_rep;
>     648          uint8_t returned_bytes = 0;
>                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
> returned_bytes is a u8.
> 
>     649          int res = -1;
>     650          uint32_t status;
>     651
>     652          memset(&aux_req, 0, sizeof(aux_req));
>     653          memset(&aux_rep, 0, sizeof(aux_rep));
>     654
>     655          engine = ddc->ctx->dc->res_pool->engines[ddc_pin->pin_data->en];
>     656          aux_engine = engine->funcs->acquire(engine, ddc_pin);
>     657
>     658          aux_req.type = type;
>     659          aux_req.action = action;
>     660
>     661          aux_req.address = address;
>     662          aux_req.delay = 0;
>     663          aux_req.length = size;
>     664          aux_req.data = buffer;
>     665
>     666          aux_engine->funcs->submit_channel_request(aux_engine, &aux_req);
>     667          operation_result = aux_engine->funcs->get_channel_status(aux_engine, &returned_bytes);
>     668
>     669          switch (operation_result) {
>     670          case AUX_CHANNEL_OPERATION_SUCCEEDED:
>     671                  res = returned_bytes;
>                          ^^^^^^^^^^^^^^^^^^^^
> res = 0-255
> 
>     672
>     673                  if (res <= size && res >= 0)
>                              ^^^^^^^^^^^^^^^^^^^^^^^
> So obviously the res >= 0 check can be removed, but that's harmless.
> The bigger problem is that the other test looks to be reversed.  Instead
> of <= it should be >= size.  Otherwise we are reading beyond the end of
> the returned bytes.

Right, the >= 0 is pointless. And upon closer look at the context, the
<= size check also seems to be pointless.

`size` refers to the size of the buffer we're given to save the reply
in. So although the `res <= size` check seems correct, it is redundant.
Calling read_channel_reply will read from hw the returned_bytes again,
and check for a buffer overflow. (At least all the current hooks do).

Thanks for the catch, will clean it up.
Leo

> 
>     674                          res = aux_engine->funcs->read_channel_reply(aux_engine, size,
>     675                                                                  buffer, reply,
>     676                                                                  &status);
>     677
>     678                  break;
> 
> regards,
> dan carpenter
> 


More information about the dri-devel mailing list