Skip to content

ams and clk fixes#10881

Open
lgirdwood wants to merge 3 commits into
thesofproject:mainfrom
lgirdwood:fix-lib
Open

ams and clk fixes#10881
lgirdwood wants to merge 3 commits into
thesofproject:mainfrom
lgirdwood:fix-lib

Conversation

@lgirdwood

Copy link
Copy Markdown
Member

Small fixes for AMS and clk manager.

The slot copy length came from a macro that adds the message length,
which over-read past the payload struct since the message data is
referenced by pointer, not stored inline. Copy exactly the struct size,
which is what the slot stores and the consumer reads back.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Copilot AI review requested due to automatic review settings June 11, 2026 14:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR applies two small safety/correctness fixes in core infrastructure code: CPU clock frequency selection and AMS slot payload copying.

Changes:

  • Prevent out-of-bounds indexing in request_freq_change() when the requested frequency exceeds the highest entry in the clock frequency table.
  • Fix ams_push_slot() to copy only the struct ams_message_payload into a slot, avoiding an out-of-bounds read caused by using AMS_MESSAGE_SIZE() with a payload type that contains a pointer (not inline data).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/lib/cpu-clk-manager.c Clamps selected_freq_id to the last valid frequency-table entry before indexing, preventing OOB access.
src/lib/ams.c Adjusts slot copy size to sizeof(*msg) to avoid over-reading past struct ams_message_payload.

@kv2019i kv2019i left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code changes good, commit messages have invalid line wrapping.

Comment thread src/lib/cpu-clk-manager.c Outdated
break;
}

/* if no entry was larger than the requested frequency the loop runs off

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit message needs fixing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reflowed the commit message body to wrap at <=72 columns (kernel/git convention, under the old checkpatch 75-char limit) and force-pushed.

Comment thread src/lib/ams.c
err = memcpy_s((__sparse_force void *)ctx_shared->slots[i].u.msg_raw,
sizeof(ctx_shared->slots[i].u.msg_raw),
msg, AMS_MESSAGE_SIZE(msg));
msg, sizeof(*msg));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how AMS works, but this looks suspicious - the type of msg is also called "...payload" which seems to suggest that the data is also attached to the header, which would then be dropped by this change?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message field is a pointer (uint8_t *message), not inline data — ams_helper_prepare_payload() does payload->message = message, pointing at a caller-owned buffer. So the payload bytes are referenced by the pointer, not appended after the struct.

AMS_MESSAGE_SIZE() = sizeof(*msg) - 1 + message_length therefore reads message_length - 1 bytes past the end of the struct (adjacent memory), not the actual payload. The slot only needs to carry the struct itself (which already includes the message pointer and message_length); ams_process_slot() copies the slot back into a struct ams_message_payload and uses those fields. So copying sizeof(*msg) preserves exactly what the consumer reads back and just removes the over-read — no payload is dropped.

(Whether that message pointer stays valid by the time another core consumes the slot is a separate, pre-existing concern this patch doesn't change.)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lgirdwood yes, I saw that comment, and I don't quite understand or follow it. "The message field is a pointer (uint8_t *message), not inline data" - of course it is a pointer - a local variable, containing a pointer. A pointer to a buffer that begins with a header which is followed by data. What's the difference?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I traced the full path to be sure, and the by-pointer reading holds:

  • Producer (detect_test.c: ams_notify_kpb): ams_helper_prepare_payload() sets message = (uint8_t *)&cd->client_data (persistent component data) and message_length = sizeof(struct kpb_client).
  • Consumer (kpb.c: kpb_ams_kpd_notification): struct kpb_client *cli_data = (struct kpb_client *)payload->message; — it casts the message pointer and dereferences it; nothing reads inline bytes.
  • Same-core delivery passes the producer's payload straight to the callback (no slot copy at all).
  • Cross-core delivery: send_message_over_ixc() sends an IDC message carrying only the slot index (size = 0, payload = NULL); the target core reads the slot struct from the shared coherent context and dereferences message (valid across SMP cores).

So the payload is never stored inline — the slot only needs the struct (which holds the message pointer + length). AMS_MESSAGE_SIZE() = sizeof(*msg) - 1 + message_length was reading message_length - 1 bytes past the producer struct and copying bytes the consumer never looks at; sizeof(*msg) copies exactly what's read back. So the fix is correct and no payload is dropped.

It was also the only user of AMS_MESSAGE_SIZE(), and AMS_SLOT_SIZE() had none, so I've removed both as dead/misleading in a follow-up commit.

(Orthogonal, pre-existing: the by-pointer design requires the producer's buffer to outlive async cross-core delivery — current clients point at persistent state, so that's fine; just noting the contract.)

Comment thread src/lib/cpu-clk-manager.c Outdated
/* if no entry was larger than the requested frequency the loop runs off
* the end of the table; clamp to the last valid entry before indexing
*/
if (selected_freq_id >= clk->freqs_num)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make the condition == for clarity

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, changed to ==. After the loop selected_freq_id can only be < freqs_num (loop break) or exactly == freqs_num (ran off the end), so == is precise and reads clearer.

When the requested frequency was at least every table entry, the search
index ran off the end of the table and the following access read one
element past it. Clamp the index to the last valid entry.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
AMS_MESSAGE_SIZE() and AMS_SLOT_SIZE() assumed the message payload was
stored inline after the header, but ams_message_payload.message is a
pointer to a caller-owned buffer (set in ams_helper_prepare_payload) and
the slot only carries the fixed-size struct. The last use of
AMS_MESSAGE_SIZE() was replaced by sizeof(*msg); AMS_SLOT_SIZE() had no
users. Remove both as dead and misleading.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants