#include <linux/lockdep.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/nospec.h>
 #include <linux/stddef.h>
 #include <linux/sysctl.h>
 #include <linux/unistd.h>
        current->mm->context.flags = is_compat_task() ? MMCF_AARCH32 : 0;
 
        ptrauth_thread_init_user(current);
+
+       if (task_spec_ssb_noexec(current)) {
+               arch_prctl_spec_ctrl_set(current, PR_SPEC_STORE_BYPASS,
+                                        PR_SPEC_ENABLE);
+       }
 }
 
 #ifdef CONFIG_ARM64_TAGGED_ADDR_ABI
 
  * prctl() may be necessary even when PSTATE.SSBS can be toggled directly
  * from userspace.
  */
+static void ssbd_prctl_enable_mitigation(struct task_struct *task)
+{
+       task_clear_spec_ssb_noexec(task);
+       task_set_spec_ssb_disable(task);
+       set_tsk_thread_flag(task, TIF_SSBD);
+}
+
+static void ssbd_prctl_disable_mitigation(struct task_struct *task)
+{
+       task_clear_spec_ssb_noexec(task);
+       task_clear_spec_ssb_disable(task);
+       clear_tsk_thread_flag(task, TIF_SSBD);
+}
+
 static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl)
 {
        switch (ctrl) {
                if (spectre_v4_mitigations_on())
                        return -EPERM;
 
-               task_clear_spec_ssb_disable(task);
-               clear_tsk_thread_flag(task, TIF_SSBD);
+               ssbd_prctl_disable_mitigation(task);
                break;
        case PR_SPEC_FORCE_DISABLE:
                /* Force disable speculation: force enable mitigation */
                if (spectre_v4_mitigations_off())
                        return -EPERM;
 
-               task_set_spec_ssb_disable(task);
-               set_tsk_thread_flag(task, TIF_SSBD);
+               ssbd_prctl_enable_mitigation(task);
+               break;
+       case PR_SPEC_DISABLE_NOEXEC:
+               /* Disable speculation until execve(): enable mitigation */
+               /*
+                * If the mitigation state is forced one way or the other, then
+                * we must fail now before we try to toggle it on execve().
+                */
+               if (task_spec_ssb_force_disable(task) ||
+                   spectre_v4_mitigations_off() ||
+                   spectre_v4_mitigations_on()) {
+                       return -EPERM;
+               }
+
+               ssbd_prctl_enable_mitigation(task);
+               task_set_spec_ssb_noexec(task);
                break;
        default:
                return -ERANGE;
        if (task_spec_ssb_force_disable(task))
                return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
 
+       if (task_spec_ssb_noexec(task))
+               return PR_SPEC_PRCTL | PR_SPEC_DISABLE_NOEXEC;
+
        if (task_spec_ssb_disable(task))
                return PR_SPEC_PRCTL | PR_SPEC_DISABLE;