arm64/sme: Always exit sme_alloc() early with existing storage

Message ID 20240115-arm64-sme-flush-v1-1-7472bd3459b7@kernel.org
State New
Headers
Series arm64/sme: Always exit sme_alloc() early with existing storage |

Commit Message

Mark Brown Jan. 15, 2024, 8:15 p.m. UTC
  When sme_alloc() is called with existing storage and we are not flushing we
will always allocate new storage, both leaking the existing storage and
corrupting the state. Fix this by separating the checks for flushing and
for existing storage as we do for SVE.

Callers that reallocate (eg, due to changing the vector length) should
call sme_free() themselves.

Fixes: 5d0a8d2fba50 (arm64/ptrace: Ensure that SME is set up for target when writing SSVE state)
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc:  <stable@vger.kernel.org>
---
 arch/arm64/kernel/fpsimd.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)


---
base-commit: 0dd3ee31125508cd67f7e7172247f05b7fd1753a
change-id: 20240112-arm64-sme-flush-09bdc40bb4fc

Best regards,
  

Comments

Will Deacon Jan. 18, 2024, 12:02 p.m. UTC | #1
On Mon, 15 Jan 2024 20:15:46 +0000, Mark Brown wrote:
> When sme_alloc() is called with existing storage and we are not flushing we
> will always allocate new storage, both leaking the existing storage and
> corrupting the state. Fix this by separating the checks for flushing and
> for existing storage as we do for SVE.
> 
> Callers that reallocate (eg, due to changing the vector length) should
> call sme_free() themselves.
> 
> [...]

Applied to arm64 (for-next/core), thanks!

[1/1] arm64/sme: Always exit sme_alloc() early with existing storage
      https://git.kernel.org/arm64/c/dc7eb8755797

Cheers,
  

Patch

diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 1559c706d32d..7363f2eb98e8 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1245,8 +1245,10 @@  void fpsimd_release_task(struct task_struct *dead_task)
  */
 void sme_alloc(struct task_struct *task, bool flush)
 {
-	if (task->thread.sme_state && flush) {
-		memset(task->thread.sme_state, 0, sme_state_size(task));
+	if (task->thread.sme_state) {
+		if (flush)
+			memset(task->thread.sme_state, 0,
+			       sme_state_size(task));
 		return;
 	}