* [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL
@ 2023-07-20 18:38 Mark Brown
2023-07-20 18:38 ` [PATCH v2 1/3] arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes Mark Brown
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Mark Brown @ 2023-07-20 18:38 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Shuah Khan
Cc: David Spickett, linux-arm-kernel, linux-kernel, linux-kselftest,
Mark Brown, stable
This series fixes an issue which David Spickett found where if we change
the SVE VL while SME is in use we can end up attempting to save state to
an unallocated buffer and adds testing coverage for that plus a bit more
coverage of VL changes, just for paranioa.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
Changes in v2:
- Always reallocate the SVE state.
- Rebase onto v6.5-rc2.
- Link to v1: https://lore.kernel.org/r/20230713-arm64-fix-sve-sme-vl-change-v1-0-129dd8611413@kernel.org
---
Mark Brown (3):
arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes
kselftest/arm64: Add a test case for SVE VL changes with SME active
kselftest/arm64: Validate that changing one VL type does not affect another
arch/arm64/kernel/fpsimd.c | 33 +++++--
tools/testing/selftests/arm64/fp/vec-syscfg.c | 127 +++++++++++++++++++++++++-
2 files changed, 148 insertions(+), 12 deletions(-)
---
base-commit: 06785562d1b99ff6dc1cd0af54be5e3ff999dc02
change-id: 20230713-arm64-fix-sve-sme-vl-change-60eb1fa6a707
Best regards,
--
Mark Brown <broonie@kernel.org>
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/3] arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes
2023-07-20 18:38 [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Mark Brown
@ 2023-07-20 18:38 ` Mark Brown
2023-07-20 18:38 ` [PATCH v2 2/3] kselftest/arm64: Add a test case for SVE VL changes with SME active Mark Brown
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2023-07-20 18:38 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Shuah Khan
Cc: David Spickett, linux-arm-kernel, linux-kernel, linux-kselftest,
Mark Brown, stable
When we reconfigure the SVE vector length we discard the backing storage
for the SVE vectors and then reallocate on next SVE use, leaving the SME
specific state alone. This means that we do not enable SME traps if they
were already disabled. That means that userspace code can enter streaming
mode without trapping, putting the task in a state where if we try to save
the state of the task we will fault.
Since the ABI does not specify that changing the SVE vector length disturbs
SME state, and since SVE code may not be aware of SME code in the process,
we shouldn't simply discard any ZA state. Instead immediately reallocate
the storage for SVE, and disable SME if we change the SVE vector length
while there is no SME state active.
Disabling SME traps on SVE vector length changes would make the overall
code more complex since we would have a state where we have valid SME state
stored but might get a SME trap.
Fixes: 9e4ab6c89109 ("arm64/sme: Implement vector length configuration prctl()s")
Reported-by: David Spickett <David.Spickett@arm.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
---
arch/arm64/kernel/fpsimd.c | 33 +++++++++++++++++++++++++--------
1 file changed, 25 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 7a1aeb95d7c3..89d54a5242d1 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -847,6 +847,8 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
int vec_set_vector_length(struct task_struct *task, enum vec_type type,
unsigned long vl, unsigned long flags)
{
+ bool free_sme = false;
+
if (flags & ~(unsigned long)(PR_SVE_VL_INHERIT |
PR_SVE_SET_VL_ONEXEC))
return -EINVAL;
@@ -897,21 +899,36 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
task->thread.fp_type = FP_STATE_FPSIMD;
}
- if (system_supports_sme() && type == ARM64_VEC_SME) {
- task->thread.svcr &= ~(SVCR_SM_MASK |
- SVCR_ZA_MASK);
- clear_thread_flag(TIF_SME);
+ if (system_supports_sme()) {
+ if (type == ARM64_VEC_SME ||
+ !(task->thread.svcr & (SVCR_SM_MASK | SVCR_ZA_MASK))) {
+ /*
+ * We are changing the SME VL or weren't using
+ * SME anyway, discard the state and force a
+ * reallocation.
+ */
+ task->thread.svcr &= ~(SVCR_SM_MASK |
+ SVCR_ZA_MASK);
+ clear_thread_flag(TIF_SME);
+ free_sme = true;
+ }
}
if (task == current)
put_cpu_fpsimd_context();
/*
- * Force reallocation of task SVE and SME state to the correct
- * size on next use:
+ * Free the changed states if they are not in use, SME will be
+ * reallocated to the correct size on next use and we just
+ * allocate SVE now in case it is needed for use in streaming
+ * mode.
*/
- sve_free(task);
- if (system_supports_sme() && type == ARM64_VEC_SME)
+ if (system_supports_sve()) {
+ sve_free(task);
+ sve_alloc(task, true);
+ }
+
+ if (free_sme)
sme_free(task);
task_set_vl(task, type, vl);
--
2.30.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/3] kselftest/arm64: Add a test case for SVE VL changes with SME active
2023-07-20 18:38 [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Mark Brown
2023-07-20 18:38 ` [PATCH v2 1/3] arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes Mark Brown
@ 2023-07-20 18:38 ` Mark Brown
2023-07-20 18:39 ` [PATCH v2 3/3] kselftest/arm64: Validate that changing one VL type does not affect another Mark Brown
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2023-07-20 18:38 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Shuah Khan
Cc: David Spickett, linux-arm-kernel, linux-kernel, linux-kselftest,
Mark Brown
We just fixed an issue where changing the SVE VL while SME was active could
result in us attempting to save the streaming mode SVE vectors without any
backing storage. Add a test case which provokes that issue, ideally we
should also verify that the contents of ZA are unaffected by any of what we
did.
Note that since we need to keep streaming mode enabled we can't use any
syscalls to trigger the issue, we have to sit in a loop in usersapce and
hope to be preempted. The chosen numbers trigger with defconfig on all the
virtual platforms for me, this won't be 100% on all systems but avoid an
overcomplicated test implementation.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
tools/testing/selftests/arm64/fp/vec-syscfg.c | 105 +++++++++++++++++++++++++-
1 file changed, 102 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/arm64/fp/vec-syscfg.c b/tools/testing/selftests/arm64/fp/vec-syscfg.c
index 9bcfcdc34ee9..58ea4bde5be7 100644
--- a/tools/testing/selftests/arm64/fp/vec-syscfg.c
+++ b/tools/testing/selftests/arm64/fp/vec-syscfg.c
@@ -6,6 +6,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -39,9 +40,11 @@ struct vec_data {
int max_vl;
};
+#define VEC_SVE 0
+#define VEC_SME 1
static struct vec_data vec_data[] = {
- {
+ [VEC_SVE] = {
.name = "SVE",
.hwcap_type = AT_HWCAP,
.hwcap = HWCAP_SVE,
@@ -51,7 +54,7 @@ static struct vec_data vec_data[] = {
.prctl_set = PR_SVE_SET_VL,
.default_vl_file = "/proc/sys/abi/sve_default_vector_length",
},
- {
+ [VEC_SME] = {
.name = "SME",
.hwcap_type = AT_HWCAP2,
.hwcap = HWCAP2_SME,
@@ -644,18 +647,107 @@ static const test_type tests[] = {
prctl_set_all_vqs,
};
+static inline void smstart(void)
+{
+ asm volatile("msr S0_3_C4_C7_3, xzr");
+}
+
+static inline void smstart_sm(void)
+{
+ asm volatile("msr S0_3_C4_C3_3, xzr");
+}
+
+static inline void smstop(void)
+{
+ asm volatile("msr S0_3_C4_C6_3, xzr");
+}
+
+
+/*
+ * Verify we can change the SVE vector length while SME is active and
+ * continue to use SME afterwards.
+ */
+static void change_sve_with_za(void)
+{
+ struct vec_data *sve_data = &vec_data[VEC_SVE];
+ bool pass = true;
+ int ret, i;
+
+ if (sve_data->min_vl == sve_data->max_vl) {
+ ksft_print_msg("Only one SVE VL supported, can't change\n");
+ ksft_test_result_skip("change_sve_while_sme\n");
+ return;
+ }
+
+ /* Ensure we will trigger a change when we set the maximum */
+ ret = prctl(sve_data->prctl_set, sve_data->min_vl);
+ if (ret != sve_data->min_vl) {
+ ksft_print_msg("Failed to set SVE VL %d: %d\n",
+ sve_data->min_vl, ret);
+ pass = false;
+ }
+
+ /* Enable SM and ZA */
+ smstart();
+
+ /* Trigger another VL change */
+ ret = prctl(sve_data->prctl_set, sve_data->max_vl);
+ if (ret != sve_data->max_vl) {
+ ksft_print_msg("Failed to set SVE VL %d: %d\n",
+ sve_data->max_vl, ret);
+ pass = false;
+ }
+
+ /*
+ * Spin for a bit with SM enabled to try to trigger another
+ * save/restore. We can't use syscalls without exiting
+ * streaming mode.
+ */
+ for (i = 0; i < 100000000; i++)
+ smstart_sm();
+
+ /*
+ * TODO: Verify that ZA was preserved over the VL change and
+ * spin.
+ */
+
+ /* Clean up after ourselves */
+ smstop();
+ ret = prctl(sve_data->prctl_set, sve_data->default_vl);
+ if (ret != sve_data->default_vl) {
+ ksft_print_msg("Failed to restore SVE VL %d: %d\n",
+ sve_data->default_vl, ret);
+ pass = false;
+ }
+
+ ksft_test_result(pass, "change_sve_with_za\n");
+}
+
+typedef void (*test_all_type)(void);
+
+static const struct {
+ const char *name;
+ test_all_type test;
+} all_types_tests[] = {
+ { "change_sve_with_za", change_sve_with_za },
+};
+
int main(void)
{
+ bool all_supported = true;
int i, j;
ksft_print_header();
- ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data));
+ ksft_set_plan(ARRAY_SIZE(tests) * ARRAY_SIZE(vec_data) +
+ ARRAY_SIZE(all_types_tests));
for (i = 0; i < ARRAY_SIZE(vec_data); i++) {
struct vec_data *data = &vec_data[i];
unsigned long supported;
supported = getauxval(data->hwcap_type) & data->hwcap;
+ if (!supported)
+ all_supported = false;
for (j = 0; j < ARRAY_SIZE(tests); j++) {
if (supported)
@@ -666,5 +758,12 @@ int main(void)
}
}
+ for (i = 0; i < ARRAY_SIZE(all_types_tests); i++) {
+ if (all_supported)
+ all_types_tests[i].test();
+ else
+ ksft_test_result_skip("%s\n", all_types_tests[i].name);
+ }
+
ksft_exit_pass();
}
--
2.30.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/3] kselftest/arm64: Validate that changing one VL type does not affect another
2023-07-20 18:38 [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Mark Brown
2023-07-20 18:38 ` [PATCH v2 1/3] arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes Mark Brown
2023-07-20 18:38 ` [PATCH v2 2/3] kselftest/arm64: Add a test case for SVE VL changes with SME active Mark Brown
@ 2023-07-20 18:39 ` Mark Brown
2023-07-21 10:53 ` [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Will Deacon
2023-07-27 16:09 ` Will Deacon
4 siblings, 0 replies; 6+ messages in thread
From: Mark Brown @ 2023-07-20 18:39 UTC (permalink / raw)
To: Catalin Marinas, Will Deacon, Shuah Khan
Cc: David Spickett, linux-arm-kernel, linux-kernel, linux-kselftest,
Mark Brown
On a system with both SVE and SME when we change one of the VLs this should
not result in a change in the other VL. Add a check that this is in fact
the case to vec-syscfg.
Signed-off-by: Mark Brown <broonie@kernel.org>
---
tools/testing/selftests/arm64/fp/vec-syscfg.c | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/arm64/fp/vec-syscfg.c b/tools/testing/selftests/arm64/fp/vec-syscfg.c
index 58ea4bde5be7..5f648b97a06f 100644
--- a/tools/testing/selftests/arm64/fp/vec-syscfg.c
+++ b/tools/testing/selftests/arm64/fp/vec-syscfg.c
@@ -554,7 +554,8 @@ static void prctl_set_onexec(struct vec_data *data)
/* For each VQ verify that setting via prctl() does the right thing */
static void prctl_set_all_vqs(struct vec_data *data)
{
- int ret, vq, vl, new_vl;
+ int ret, vq, vl, new_vl, i;
+ int orig_vls[ARRAY_SIZE(vec_data)];
int errors = 0;
if (!data->min_vl || !data->max_vl) {
@@ -563,6 +564,9 @@ static void prctl_set_all_vqs(struct vec_data *data)
return;
}
+ for (i = 0; i < ARRAY_SIZE(vec_data); i++)
+ orig_vls[i] = vec_data[i].rdvl();
+
for (vq = SVE_VQ_MIN; vq <= SVE_VQ_MAX; vq++) {
vl = sve_vl_from_vq(vq);
@@ -585,6 +589,22 @@ static void prctl_set_all_vqs(struct vec_data *data)
errors++;
}
+ /* Did any other VLs change? */
+ for (i = 0; i < ARRAY_SIZE(vec_data); i++) {
+ if (&vec_data[i] == data)
+ continue;
+
+ if (!(getauxval(vec_data[i].hwcap_type) & vec_data[i].hwcap))
+ continue;
+
+ if (vec_data[i].rdvl() != orig_vls[i]) {
+ ksft_print_msg("%s VL changed from %d to %d\n",
+ vec_data[i].name, orig_vls[i],
+ vec_data[i].rdvl());
+ errors++;
+ }
+ }
+
/* Was that the VL we asked for? */
if (new_vl == vl)
continue;
--
2.30.2
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL
2023-07-20 18:38 [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Mark Brown
` (2 preceding siblings ...)
2023-07-20 18:39 ` [PATCH v2 3/3] kselftest/arm64: Validate that changing one VL type does not affect another Mark Brown
@ 2023-07-21 10:53 ` Will Deacon
2023-07-27 16:09 ` Will Deacon
4 siblings, 0 replies; 6+ messages in thread
From: Will Deacon @ 2023-07-21 10:53 UTC (permalink / raw)
To: Catalin Marinas, Shuah Khan, Mark Brown
Cc: kernel-team, Will Deacon, linux-arm-kernel, David Spickett,
linux-kernel, stable, linux-kselftest
On Thu, 20 Jul 2023 19:38:57 +0100, Mark Brown wrote:
> This series fixes an issue which David Spickett found where if we change
> the SVE VL while SME is in use we can end up attempting to save state to
> an unallocated buffer and adds testing coverage for that plus a bit more
> coverage of VL changes, just for paranioa.
>
>
Applied first patch to arm64 (for-next/fixes), thanks!
[1/3] arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes
https://git.kernel.org/arm64/c/d4d5be94a878
I'll look at the selftests stuff for 6.6 when I get to that (probably
next week).
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL
2023-07-20 18:38 [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Mark Brown
` (3 preceding siblings ...)
2023-07-21 10:53 ` [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Will Deacon
@ 2023-07-27 16:09 ` Will Deacon
4 siblings, 0 replies; 6+ messages in thread
From: Will Deacon @ 2023-07-27 16:09 UTC (permalink / raw)
To: Mark Brown, Catalin Marinas, Shuah Khan
Cc: kernel-team, Will Deacon, stable, linux-arm-kernel,
David Spickett, linux-kselftest, linux-kernel
On Thu, 20 Jul 2023 19:38:57 +0100, Mark Brown wrote:
> This series fixes an issue which David Spickett found where if we change
> the SVE VL while SME is in use we can end up attempting to save state to
> an unallocated buffer and adds testing coverage for that plus a bit more
> coverage of VL changes, just for paranioa.
>
>
Applied to arm64 (for-next/selftests), thanks!
[1/3] arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes
https://git.kernel.org/arm64/c/d4d5be94a878
[2/3] kselftest/arm64: Add a test case for SVE VL changes with SME active
https://git.kernel.org/arm64/c/0c7c237b1c35
[3/3] kselftest/arm64: Validate that changing one VL type does not affect another
https://git.kernel.org/arm64/c/0aeead9bb240
Cheers,
--
Will
https://fixes.arm64.dev
https://next.arm64.dev
https://will.arm64.dev
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-07-27 16:09 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-20 18:38 [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Mark Brown
2023-07-20 18:38 ` [PATCH v2 1/3] arm64/fpsimd: Ensure SME storage is allocated after SVE VL changes Mark Brown
2023-07-20 18:38 ` [PATCH v2 2/3] kselftest/arm64: Add a test case for SVE VL changes with SME active Mark Brown
2023-07-20 18:39 ` [PATCH v2 3/3] kselftest/arm64: Validate that changing one VL type does not affect another Mark Brown
2023-07-21 10:53 ` [PATCH v2 0/3] arm64/fpsimd: Fix use after free in SME when changing SVE VL Will Deacon
2023-07-27 16:09 ` Will Deacon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).