ssbd.c 2.4 KB

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