Mark Brown broonie@kernel.org writes:
+#ifdef CONFIG_ARM64_GCS +static int gcs_restore_signal(void) +{
- u64 gcspr_el0, cap;
- int ret;
- if (!system_supports_gcs())
return 0;
- if (!(current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE))
return 0;
- gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0);
- /*
* GCSPR_EL0 should be pointing at a capped GCS, read the cap...
*/
- gcsb_dsync();
- ret = copy_from_user(&cap, (__user void*)gcspr_el0, sizeof(cap));
- if (ret)
return -EFAULT;
- /*
* ...then check that the cap is the actual GCS before
* restoring it.
*/
- if (!gcs_signal_cap_valid(gcspr_el0, cap))
return -EINVAL;
- /* Invalidate the token to prevent reuse */
- put_user_gcs(0, (__user void*)gcspr_el0, &ret);
- if (ret != 0)
return -EFAULT;
You had mentioned that "ideally we'd be doing a compare and exchange here to substitute in a zero". Is a compare and exchange not necessary anymore, or is it just being left for later? In the latter case, a TODO or FIXME comment mentioning it would be useful here.
- current->thread.gcspr_el0 = gcspr_el0 + sizeof(cap);
- write_sysreg_s(current->thread.gcspr_el0, SYS_GCSPR_EL0);
- return 0;
+}