All of lore.kernel.org
 help / color / mirror / Atom feed
* [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler()
@ 2025-01-15 10:23 Dan Carpenter
  2025-01-15 11:18 ` Khaled Ali Ahmed
       [not found] ` <GV2PR08MB795595222CD06A1F5B60CD0FEB192@GV2PR08MB7955.eurprd08.prod.outlook.com>
  0 siblings, 2 replies; 4+ messages in thread
From: Dan Carpenter @ 2025-01-15 10:23 UTC (permalink / raw)
  To: Khaled Ali Ahmed; +Cc: arm-scmi@vger.kernel.org

I'm not sure how scmi_api->write_payload() is supposed to work and
I'm getting memory corruption in scmi_pin_control_list_associations_handler().

module/scmi_pin_control/src/mod_scmi_pin_control.c
   309  static int scmi_pin_control_list_associations_handler(
   310      fwk_id_t service_id,
   311      const uint32_t *payload)
   312  {
   313      const struct scmi_pin_control_list_associations_a2p *parameters;
   314      uint32_t payload_size;
   315      uint16_t identifiers_count;
   316      uint16_t total_number_of_associations;
   317      uint16_t remaining_associations;
   318      uint16_t identifier_index;
   319      size_t buffer_allowed_identifiers;
   320      uint16_t mapped_identifier;
   321  
   322      int status;
   323  
   324      struct scmi_pin_control_list_associations_p2a return_values = {
   325          .status = (int32_t)SCMI_GENERIC_ERROR,
   326          .flags = 0,
   327      };
   328  
   329      payload_size = (uint32_t)sizeof(return_values);
   330  
   331      parameters = (const struct scmi_pin_control_list_associations_a2p *)payload;
   332  
   333      status = map_identifier(parameters->identifier, &mapped_identifier);
   334  
   335      if (status != FWK_SUCCESS) {
   336          return_values.status = SCMI_NOT_FOUND;
   337          goto exit;
   338      }
   339  
   340      status = scmi_pin_control_ctx.pinctrl_api->get_total_number_of_associations(
   341          mapped_identifier, parameters->flags, &total_number_of_associations);
   342      if (status != FWK_SUCCESS) {
   343          return_values.status = SCMI_NOT_FOUND;
   344          goto exit;
   345      }
   346  
   347      if (parameters->index >= total_number_of_associations) {
   348          return_values.status = SCMI_NOT_FOUND;
   349          goto exit;
   350      }
   351  
   352      remaining_associations = total_number_of_associations - parameters->index;
   353  
   354      status = number_of_elements_allowed_in_payload(
   355          service_id,
   356          sizeof(struct scmi_pin_control_list_associations_p2a),
   357          sizeof(uint16_t),
   358          (size_t *)&buffer_allowed_identifiers);
   359      if (status != FWK_SUCCESS) {
   360          goto exit;
   361      }
   362  
   363      identifiers_count = (uint16_t)FWK_MIN(
   364          buffer_allowed_identifiers, remaining_associations);
   365  
   366      return_values.flags = identifiers_count;
   367      return_values.flags |= SHIFT_LEFT_BY_POS(
   368          (remaining_associations - identifiers_count),
   369          NUM_OF_REMAINING_ELEMENTS_POS);
   370  
   371      for (identifier_index = 0; identifier_index < identifiers_count;
   372           identifier_index++) {
   373          uint16_t object_id;
   374  
   375          status = scmi_pin_control_ctx.pinctrl_api->get_list_associations(
   376              mapped_identifier,
   377              parameters->flags,
   378              (parameters->index + identifier_index),
   379              &object_id);
   380          if (status != FWK_SUCCESS) {
   381              return_values.status = SCMI_NOT_FOUND;
   382              goto exit;
   383          }
   384  
   385          status = scmi_pin_control_ctx.scmi_api->write_payload(
   386              service_id, payload_size, &object_id, sizeof(object_id));

This code writes the u16 object id to the correct place.  It happens
in transport_write_payload()

   387          if (status != FWK_SUCCESS) {
   388              goto exit;
   389          }
   390  
   391          payload_size += (uint32_t)sizeof(object_id);
   392      }
   393  
   394      return_values.status = (int32_t)SCMI_SUCCESS;
   395  
   396  exit:
   397      return scmi_pin_control_ctx.scmi_api->respond(
   398          service_id,
   399          (return_values.status == SCMI_SUCCESS) ? (void *)&return_values :
   400                                                   (void *)&return_values.status,
   401          (return_values.status == SCMI_SUCCESS) ? payload_size :

But this payload_size will overwrite it again with data from beyond
the end of the return_values struct.  I don't really understand how
write payload is supposed to work.  Maybe we need to create a different
type of ->done() function pointer so that we could call ->write_payload()
in a loop and then call ->done() to actually send the data?

For now, I've just removed the ->write_payload() and done send the
response using ->respond() with an allocated buffer and that solves
my issues.

regards,
dan carpenter

   402                                                   sizeof(return_values.status));
   403  }




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler()
  2025-01-15 10:23 [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler() Dan Carpenter
@ 2025-01-15 11:18 ` Khaled Ali Ahmed
       [not found] ` <GV2PR08MB795595222CD06A1F5B60CD0FEB192@GV2PR08MB7955.eurprd08.prod.outlook.com>
  1 sibling, 0 replies; 4+ messages in thread
From: Khaled Ali Ahmed @ 2025-01-15 11:18 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: arm-scmi@vger.kernel.org


Hi Dan,

write_payload API is a helpful function and can lead to easier and more effective implementation, while we ask the Transport to set an object into a certain offset in a service_id buffer, the main reason for that is that we don't know if we will continue the loop successfully or not.
after that, we should call respond which will trigger the Transport that the buffer now is completed and please respond whenever you are ready.

regarding the previous description, I encourage you to use write_payload whenever you can.

thanks, Dan so much


________________________________________
From: Dan Carpenter <dan.carpenter@linaro.org>
Sent: Wednesday, January 15, 2025 10:23 AM
To: Khaled Ali Ahmed <Khaled.AliAhmed@arm.com>
Cc: arm-scmi@vger.kernel.org <arm-scmi@vger.kernel.org>
Subject: [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler()

I'm not sure how scmi_api->write_payload() is supposed to work and
I'm getting memory corruption in scmi_pin_control_list_associations_handler().

module/scmi_pin_control/src/mod_scmi_pin_control.c
   309  static int scmi_pin_control_list_associations_handler(
   310      fwk_id_t service_id,
   311      const uint32_t *payload)
   312  {
   313      const struct scmi_pin_control_list_associations_a2p *parameters;
   314      uint32_t payload_size;
   315      uint16_t identifiers_count;
   316      uint16_t total_number_of_associations;
   317      uint16_t remaining_associations;
   318      uint16_t identifier_index;
   319      size_t buffer_allowed_identifiers;
   320      uint16_t mapped_identifier;
   321
   322      int status;
   323
   324      struct scmi_pin_control_list_associations_p2a return_values = {
   325          .status = (int32_t)SCMI_GENERIC_ERROR,
   326          .flags = 0,
   327      };
   328
   329      payload_size = (uint32_t)sizeof(return_values);
   330
   331      parameters = (const struct scmi_pin_control_list_associations_a2p *)payload;
   332
   333      status = map_identifier(parameters->identifier, &mapped_identifier);
   334
   335      if (status != FWK_SUCCESS) {
   336          return_values.status = SCMI_NOT_FOUND;
   337          goto exit;
   338      }
   339
   340      status = scmi_pin_control_ctx.pinctrl_api->get_total_number_of_associations(
   341          mapped_identifier, parameters->flags, &total_number_of_associations);
   342      if (status != FWK_SUCCESS) {
   343          return_values.status = SCMI_NOT_FOUND;
   344          goto exit;
   345      }
   346
   347      if (parameters->index >= total_number_of_associations) {
   348          return_values.status = SCMI_NOT_FOUND;
   349          goto exit;
   350      }
   351
   352      remaining_associations = total_number_of_associations - parameters->index;
   353
   354      status = number_of_elements_allowed_in_payload(
   355          service_id,
   356          sizeof(struct scmi_pin_control_list_associations_p2a),
   357          sizeof(uint16_t),
   358          (size_t *)&buffer_allowed_identifiers);
   359      if (status != FWK_SUCCESS) {
   360          goto exit;
   361      }
   362
   363      identifiers_count = (uint16_t)FWK_MIN(
   364          buffer_allowed_identifiers, remaining_associations);
   365
   366      return_values.flags = identifiers_count;
   367      return_values.flags |= SHIFT_LEFT_BY_POS(
   368          (remaining_associations - identifiers_count),
   369          NUM_OF_REMAINING_ELEMENTS_POS);
   370
   371      for (identifier_index = 0; identifier_index < identifiers_count;
   372           identifier_index++) {
   373          uint16_t object_id;
   374
   375          status = scmi_pin_control_ctx.pinctrl_api->get_list_associations(
   376              mapped_identifier,
   377              parameters->flags,
   378              (parameters->index + identifier_index),
   379              &object_id);
   380          if (status != FWK_SUCCESS) {
   381              return_values.status = SCMI_NOT_FOUND;
   382              goto exit;
   383          }
   384
   385          status = scmi_pin_control_ctx.scmi_api->write_payload(
   386              service_id, payload_size, &object_id, sizeof(object_id));

This code writes the u16 object id to the correct place.  It happens
in transport_write_payload()

   387          if (status != FWK_SUCCESS) {
   388              goto exit;
   389          }
   390
   391          payload_size += (uint32_t)sizeof(object_id);
   392      }
   393
   394      return_values.status = (int32_t)SCMI_SUCCESS;
   395
   396  exit:
   397      return scmi_pin_control_ctx.scmi_api->respond(
   398          service_id,
   399          (return_values.status == SCMI_SUCCESS) ? (void *)&return_values :
   400                                                   (void *)&return_values.status,
   401          (return_values.status == SCMI_SUCCESS) ? payload_size :

But this payload_size will overwrite it again with data from beyond
the end of the return_values struct.  I don't really understand how
write payload is supposed to work.  Maybe we need to create a different
type of ->done() function pointer so that we could call ->write_payload()
in a loop and then call ->done() to actually send the data?

For now, I've just removed the ->write_payload() and done send the
response using ->respond() with an allocated buffer and that solves
my issues.

regards,
dan carpenter

   402                                                   sizeof(return_values.status));
   403  }


IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler()
       [not found] ` <GV2PR08MB795595222CD06A1F5B60CD0FEB192@GV2PR08MB7955.eurprd08.prod.outlook.com>
@ 2025-01-15 12:14   ` Dan Carpenter
  2025-01-15 12:31     ` Khaled Ali Ahmed
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2025-01-15 12:14 UTC (permalink / raw)
  To: Khaled Ali Ahmed; +Cc: arm-scmi@vger.kernel.org

On Wed, Jan 15, 2025 at 11:15:25AM +0000, Khaled Ali Ahmed wrote:
> Hi Dan,
> 
> write_payload API is a helpful function and can lead to easier and
> more effective implementation, while we ask the Transport to set an
> object into a certain offset in a service_id buffer, the main reason
> for that is that we don't know if we will continue the loop
> successfully or not.
>
> after that, we should call respond which will trigger the Transport
> that the buffer now is completed and please respond whenever you are
> ready.
> 
> regarding the previous description, I encourage you to use write_payload
> whenever you can.
> 

I get how it could be nice, but it doesn't work.  I am looking
at transport_write_payload() in particular.

>    385          status = scmi_pin_control_ctx.scmi_api->write_payload(
>    386              service_id, payload_size, &object_id, sizeof(object_id));

In this code we're writing sizeof(object_id) bytes to the middle of the
buffer.  Nothing in transport_write_payload() is saving the "size" so we
don't record which bytes have been written to.

>    397      return scmi_pin_control_ctx.scmi_api->respond(
>    398          service_id,
>    399          (return_values.status == SCMI_SUCCESS) ? (void *)&return_values :
>    400                                                   (void *)&return_values.status,
>    401          (return_values.status == SCMI_SUCCESS) ? payload_size :
>    402                                                   sizeof(return_values.status));

Ideally this code would write sizeof(return_values) bytes to the start
of the buffer and do the transfer.  But we're not passing
sizeof(return_values) as a parameter.

Instead, in this code we're passing "payload_size", which is the total
number of bytes.  So it does the equivalent to
memcpy(channel_ctx->out->buffer, &return_values, payload_size).  That is
a read overflow of the return_values struct and it scribbles over the
data that we copied earlier with the transport_write_payload().

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler()
  2025-01-15 12:14   ` Dan Carpenter
@ 2025-01-15 12:31     ` Khaled Ali Ahmed
  0 siblings, 0 replies; 4+ messages in thread
From: Khaled Ali Ahmed @ 2025-01-15 12:31 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: arm-scmi@vger.kernel.org

Hello Dan,

the name of the variable may be tricky. I agree its current name is payload_size but it would be better to change its name into payload_offset or something else.
the write_payload function using  fwk_str_memcpy which is implementing memory copy. it makes a copy of the payload into payload address + offset.

> Ideally this code would write sizeof(return_values) bytes to the start
> of the buffer and do the transfer.  But we're not passing
> sizeof(return_values) as a parameter.
this means that the actual response size will depend on the status of the response if it is successful we will send the whole buffer, otherwise we will send just the error code as a return value.

I am not sure if it is clear for you otherwise let's plan a meeting and let me clarify more.

regards,
khaled Ahmed

________________________________________
From: Dan Carpenter <dan.carpenter@linaro.org>
Sent: Wednesday, January 15, 2025 12:14 PM
To: Khaled Ali Ahmed <Khaled.AliAhmed@arm.com>
Cc: arm-scmi@vger.kernel.org <arm-scmi@vger.kernel.org>
Subject: Re: [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler()

On Wed, Jan 15, 2025 at 11:15:25AM +0000, Khaled Ali Ahmed wrote:
> Hi Dan,
>
> write_payload API is a helpful function and can lead to easier and
> more effective implementation, while we ask the Transport to set an
> object into a certain offset in a service_id buffer, the main reason
> for that is that we don't know if we will continue the loop
> successfully or not.
>
> after that, we should call respond which will trigger the Transport
> that the buffer now is completed and please respond whenever you are
> ready.
>
> regarding the previous description, I encourage you to use write_payload
> whenever you can.
>

I get how it could be nice, but it doesn't work.  I am looking
at transport_write_payload() in particular.

>    385          status = scmi_pin_control_ctx.scmi_api->write_payload(
>    386              service_id, payload_size, &object_id, sizeof(object_id));

In this code we're writing sizeof(object_id) bytes to the middle of the
buffer.  Nothing in transport_write_payload() is saving the "size" so we
don't record which bytes have been written to.

>    397      return scmi_pin_control_ctx.scmi_api->respond(
>    398          service_id,
>    399          (return_values.status == SCMI_SUCCESS) ? (void *)&return_values :
>    400                                                   (void *)&return_values.status,
>    401          (return_values.status == SCMI_SUCCESS) ? payload_size :
>    402                                                   sizeof(return_values.status));

Ideally this code would write sizeof(return_values) bytes to the start
of the buffer and do the transfer.  But we're not passing
sizeof(return_values) as a parameter.

Instead, in this code we're passing "payload_size", which is the total
number of bytes.  So it does the equivalent to
memcpy(channel_ctx->out->buffer, &return_values, payload_size).  That is
a read overflow of the return_values struct and it scribbles over the
data that we copied earlier with the transport_write_payload().

regards,
dan carpenter
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2025-01-15 12:31 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-15 10:23 [bug report] SCP: memory corruption in scmi_pin_control_list_associations_handler() Dan Carpenter
2025-01-15 11:18 ` Khaled Ali Ahmed
     [not found] ` <GV2PR08MB795595222CD06A1F5B60CD0FEB192@GV2PR08MB7955.eurprd08.prod.outlook.com>
2025-01-15 12:14   ` Dan Carpenter
2025-01-15 12:31     ` Khaled Ali Ahmed

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.