ssbd.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018 ARM Ltd, All Rights Reserved.
  4. */
  5. #include <linux/compat.h>
  6. #include <linux/errno.h>
  7. #include <linux/prctl.h>
  8. #include <linux/sched.h>
  9. #include <linux/sched/task_stack.h>
  10. #include <linux/thread_info.h>
  11. #include <asm/compat.h>
  12. #include <asm/cpufeature.h>
  13. static void ssbd_ssbs_enable(struct task_struct *task)
  14. {
  15. u64 val = is_compat_thread(task_thread_info(task)) ?
  16. PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
  17. task_pt_regs(task)->pstate |= val;
  18. }
  19. static void ssbd_ssbs_disable(struct task_struct *task)
  20. {
  21. u64 val = is_compat_thread(task_thread_info(task)) ?
  22. PSR_AA32_SSBS_BIT : PSR_SSBS_BIT;
  23. task_pt_regs(task)->pstate &= ~val;
  24. }
  25. /*
  26. * prctl interface for SSBD
  27. */
  28. static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
  29. {
  30. int state = arm64_get_ssbd_state();
  31. /* Unsupported */
  32. if (state == ARM64_SSBD_UNKNOWN)
  33. return -EINVAL;
  34. /* Treat the unaffected/mitigated state separately */
  35. if (state == ARM64_SSBD_MITIGATED) {
  36. switch (ctrl) {
  37. case PR_SPEC_ENABLE:
  38. return -EPERM;
  39. case PR_SPEC_DISABLE:
  40. case PR_SPEC_FORCE_DISABLE:
  41. return 0;
  42. }
  43. }
  44. /*
  45. * Things are a bit backward here: the arm64 internal API
  46. * *enables the mitigation* when the userspace API *disables
  47. * speculation*. So much fun.
  48. */
  49. switch (ctrl) {
  50. case PR_SPEC_ENABLE:
  51. /* If speculation is force disabled, enable is not allowed */
  52. if (state == ARM64_SSBD_FORCE_ENABLE ||
  53. task_spec_ssb_force_disable(task))
  54. return -EPERM;
  55. task_clear_spec_ssb_disable(task);
  56. clear_tsk_thread_flag(task, TIF_SSBD);
  57. ssbd_ssbs_enable(task);
  58. break;
  59. case PR_SPEC_DISABLE:
  60. if (state == ARM64_SSBD_FORCE_DISABLE)
  61. return -EPERM;
  62. task_set_spec_ssb_disable(task);
  63. set_tsk_thread_flag(task, TIF_SSBD);
  64. ssbd_ssbs_disable(task);
  65. break;
  66. case PR_SPEC_FORCE_DISABLE:
  67. if (state == ARM64_SSBD_FORCE_DISABLE)
  68. return -EPERM;
  69. task_set_spec_ssb_disable(task);
  70. task_set_spec_ssb_force_disable(task);
  71. set_tsk_thread_flag(task, TIF_SSBD);
  72. ssbd_ssbs_disable(task);
  73. break;
  74. default:
  75. return -ERANGE;
  76. }
  77. return 0;
  78. }
  79. int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
  80. unsigned long ctrl)
  81. {
  82. switch (which) {
  83. case PR_SPEC_STORE_BYPASS:
  84. return ssbd_prctl_set(task, ctrl);
  85. default:
  86. return -ENODEV;
  87. }
  88. }
  89. static int ssbd_prctl_get(struct task_struct *task)
  90. {
  91. switch (arm64_get_ssbd_state()) {
  92. case ARM64_SSBD_UNKNOWN:
  93. return -EINVAL;
  94. case ARM64_SSBD_FORCE_ENABLE:
  95. return PR_SPEC_DISABLE;
  96. case ARM64_SSBD_KERNEL:
  97. if (task_spec_ssb_force_disable(task))
  98. return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
  99. if (task_spec_ssb_disable(task))
  100. return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
  101. return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
  102. case ARM64_SSBD_FORCE_DISABLE:
  103. return PR_SPEC_ENABLE;
  104. default:
  105. return PR_SPEC_NOT_AFFECTED;
  106. }
  107. }
  108. int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
  109. {
  110. switch (which) {
  111. case PR_SPEC_STORE_BYPASS:
  112. return ssbd_prctl_get(task);
  113. default:
  114. return -ENODEV;
  115. }
  116. }