|
@@ -7,6 +7,7 @@
|
|
#include <linux/export.h>
|
|
#include <linux/export.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/cpu.h>
|
|
#include <linux/debugfs.h>
|
|
#include <linux/debugfs.h>
|
|
|
|
+#include <linux/ptrace.h>
|
|
|
|
|
|
#include <asm/tlbflush.h>
|
|
#include <asm/tlbflush.h>
|
|
#include <asm/mmu_context.h>
|
|
#include <asm/mmu_context.h>
|
|
@@ -180,6 +181,19 @@ static void sync_current_stack_to_mm(struct mm_struct *mm)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static bool ibpb_needed(struct task_struct *tsk, u64 last_ctx_id)
|
|
|
|
+{
|
|
|
|
+ /*
|
|
|
|
+ * Check if the current (previous) task has access to the memory
|
|
|
|
+ * of the @tsk (next) task. If access is denied, make sure to
|
|
|
|
+ * issue a IBPB to stop user->user Spectre-v2 attacks.
|
|
|
|
+ *
|
|
|
|
+ * Note: __ptrace_may_access() returns 0 or -ERRNO.
|
|
|
|
+ */
|
|
|
|
+ return (tsk && tsk->mm && tsk->mm->context.ctx_id != last_ctx_id &&
|
|
|
|
+ ptrace_may_access_sched(tsk, PTRACE_MODE_SPEC_IBPB));
|
|
|
|
+}
|
|
|
|
+
|
|
void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
|
void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
|
struct task_struct *tsk)
|
|
struct task_struct *tsk)
|
|
{
|
|
{
|
|
@@ -262,18 +276,13 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
|
|
* one process from doing Spectre-v2 attacks on another.
|
|
* one process from doing Spectre-v2 attacks on another.
|
|
*
|
|
*
|
|
* As an optimization, flush indirect branches only when
|
|
* As an optimization, flush indirect branches only when
|
|
- * switching into processes that disable dumping. This
|
|
|
|
- * protects high value processes like gpg, without having
|
|
|
|
- * too high performance overhead. IBPB is *expensive*!
|
|
|
|
- *
|
|
|
|
- * This will not flush branches when switching into kernel
|
|
|
|
- * threads. It will also not flush if we switch to idle
|
|
|
|
- * thread and back to the same process. It will flush if we
|
|
|
|
- * switch to a different non-dumpable process.
|
|
|
|
|
|
+ * switching into a processes that can't be ptrace by the
|
|
|
|
+ * current one (as in such case, attacker has much more
|
|
|
|
+ * convenient way how to tamper with the next process than
|
|
|
|
+ * branch buffer poisoning).
|
|
*/
|
|
*/
|
|
- if (tsk && tsk->mm &&
|
|
|
|
- tsk->mm->context.ctx_id != last_ctx_id &&
|
|
|
|
- get_dumpable(tsk->mm) != SUID_DUMP_USER)
|
|
|
|
|
|
+ if (static_cpu_has(X86_FEATURE_USE_IBPB) &&
|
|
|
|
+ ibpb_needed(tsk, last_ctx_id))
|
|
indirect_branch_prediction_barrier();
|
|
indirect_branch_prediction_barrier();
|
|
|
|
|
|
if (IS_ENABLED(CONFIG_VMAP_STACK)) {
|
|
if (IS_ENABLED(CONFIG_VMAP_STACK)) {
|