lkml.org 
[lkml]   [2018]   [Dec]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 058/139] x86/speculation: Add prctl() control for indirect branch speculation
    Date
    4.19-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Thomas Gleixner tglx@linutronix.de

    commit 9137bb27e60e554dab694eafa4cca241fa3a694f upstream

    Add the PR_SPEC_INDIRECT_BRANCH option for the PR_GET_SPECULATION_CTRL and
    PR_SET_SPECULATION_CTRL prctls to allow fine grained per task control of
    indirect branch speculation via STIBP and IBPB.

    Invocations:
    Check indirect branch speculation status with
    - prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0);

    Enable indirect branch speculation with
    - prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);

    Disable indirect branch speculation with
    - prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0);

    Force disable indirect branch speculation with
    - prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);

    See Documentation/userspace-api/spec_ctrl.rst.

    Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Reviewed-by: Ingo Molnar <mingo@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Jiri Kosina <jkosina@suse.cz>
    Cc: Tom Lendacky <thomas.lendacky@amd.com>
    Cc: Josh Poimboeuf <jpoimboe@redhat.com>
    Cc: Andrea Arcangeli <aarcange@redhat.com>
    Cc: David Woodhouse <dwmw@amazon.co.uk>
    Cc: Andi Kleen <ak@linux.intel.com>
    Cc: Dave Hansen <dave.hansen@intel.com>
    Cc: Casey Schaufler <casey.schaufler@intel.com>
    Cc: Asit Mallick <asit.k.mallick@intel.com>
    Cc: Arjan van de Ven <arjan@linux.intel.com>
    Cc: Jon Masters <jcm@redhat.com>
    Cc: Waiman Long <longman9394@gmail.com>
    Cc: Greg KH <gregkh@linuxfoundation.org>
    Cc: Dave Stewart <david.c.stewart@intel.com>
    Cc: Kees Cook <keescook@chromium.org>
    Cc: stable@vger.kernel.org
    Link: https://lkml.kernel.org/r/20181125185005.866780996@linutronix.de
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    Documentation/userspace-api/spec_ctrl.rst | 9 ++++
    arch/x86/include/asm/nospec-branch.h | 1
    arch/x86/kernel/cpu/bugs.c | 67 ++++++++++++++++++++++++++++++
    arch/x86/kernel/process.c | 5 ++
    include/linux/sched.h | 9 ++++
    include/uapi/linux/prctl.h | 1
    tools/include/uapi/linux/prctl.h | 1
    7 files changed, 93 insertions(+)

    --- a/Documentation/userspace-api/spec_ctrl.rst
    +++ b/Documentation/userspace-api/spec_ctrl.rst
    @@ -92,3 +92,12 @@ Speculation misfeature controls
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
    +
    +- PR_SPEC_INDIR_BRANCH: Indirect Branch Speculation in User Processes
    + (Mitigate Spectre V2 style attacks against user processes)
    +
    + Invocations:
    + * prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0);
    + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);
    + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0);
    + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);
    --- a/arch/x86/include/asm/nospec-branch.h
    +++ b/arch/x86/include/asm/nospec-branch.h
    @@ -232,6 +232,7 @@ enum spectre_v2_mitigation {
    enum spectre_v2_user_mitigation {
    SPECTRE_V2_USER_NONE,
    SPECTRE_V2_USER_STRICT,
    + SPECTRE_V2_USER_PRCTL,
    };

    /* The Speculative Store Bypass disable variants */
    --- a/arch/x86/kernel/cpu/bugs.c
    +++ b/arch/x86/kernel/cpu/bugs.c
    @@ -564,6 +564,8 @@ void arch_smt_update(void)
    case SPECTRE_V2_USER_STRICT:
    update_stibp_strict();
    break;
    + case SPECTRE_V2_USER_PRCTL:
    + break;
    }

    mutex_unlock(&spec_ctrl_mutex);
    @@ -750,12 +752,50 @@ static int ssb_prctl_set(struct task_str
    return 0;
    }

    +static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
    +{
    + switch (ctrl) {
    + case PR_SPEC_ENABLE:
    + if (spectre_v2_user == SPECTRE_V2_USER_NONE)
    + return 0;
    + /*
    + * Indirect branch speculation is always disabled in strict
    + * mode.
    + */
    + if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
    + return -EPERM;
    + task_clear_spec_ib_disable(task);
    + task_update_spec_tif(task);
    + break;
    + case PR_SPEC_DISABLE:
    + case PR_SPEC_FORCE_DISABLE:
    + /*
    + * Indirect branch speculation is always allowed when
    + * mitigation is force disabled.
    + */
    + if (spectre_v2_user == SPECTRE_V2_USER_NONE)
    + return -EPERM;
    + if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
    + return 0;
    + task_set_spec_ib_disable(task);
    + if (ctrl == PR_SPEC_FORCE_DISABLE)
    + task_set_spec_ib_force_disable(task);
    + task_update_spec_tif(task);
    + break;
    + default:
    + return -ERANGE;
    + }
    + return 0;
    +}
    +
    int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
    unsigned long ctrl)
    {
    switch (which) {
    case PR_SPEC_STORE_BYPASS:
    return ssb_prctl_set(task, ctrl);
    + case PR_SPEC_INDIRECT_BRANCH:
    + return ib_prctl_set(task, ctrl);
    default:
    return -ENODEV;
    }
    @@ -788,11 +828,34 @@ static int ssb_prctl_get(struct task_str
    }
    }

    +static int ib_prctl_get(struct task_struct *task)
    +{
    + if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
    + return PR_SPEC_NOT_AFFECTED;
    +
    + switch (spectre_v2_user) {
    + case SPECTRE_V2_USER_NONE:
    + return PR_SPEC_ENABLE;
    + case SPECTRE_V2_USER_PRCTL:
    + if (task_spec_ib_force_disable(task))
    + return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
    + if (task_spec_ib_disable(task))
    + return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
    + return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
    + case SPECTRE_V2_USER_STRICT:
    + return PR_SPEC_DISABLE;
    + default:
    + return PR_SPEC_NOT_AFFECTED;
    + }
    +}
    +
    int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
    {
    switch (which) {
    case PR_SPEC_STORE_BYPASS:
    return ssb_prctl_get(task);
    + case PR_SPEC_INDIRECT_BRANCH:
    + return ib_prctl_get(task);
    default:
    return -ENODEV;
    }
    @@ -972,6 +1035,8 @@ static char *stibp_state(void)
    return ", STIBP: disabled";
    case SPECTRE_V2_USER_STRICT:
    return ", STIBP: forced";
    + case SPECTRE_V2_USER_PRCTL:
    + return "";
    }
    return "";
    }
    @@ -984,6 +1049,8 @@ static char *ibpb_state(void)
    return ", IBPB: disabled";
    case SPECTRE_V2_USER_STRICT:
    return ", IBPB: always-on";
    + case SPECTRE_V2_USER_PRCTL:
    + return "";
    }
    }
    return "";
    --- a/arch/x86/kernel/process.c
    +++ b/arch/x86/kernel/process.c
    @@ -450,6 +450,11 @@ static unsigned long speculation_ctrl_up
    set_tsk_thread_flag(tsk, TIF_SSBD);
    else
    clear_tsk_thread_flag(tsk, TIF_SSBD);
    +
    + if (task_spec_ib_disable(tsk))
    + set_tsk_thread_flag(tsk, TIF_SPEC_IB);
    + else
    + clear_tsk_thread_flag(tsk, TIF_SPEC_IB);
    }
    /* Return the updated threadinfo flags*/
    return task_thread_info(tsk)->flags;
    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -1439,6 +1439,8 @@ static inline bool is_percpu_thread(void
    #define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */
    #define PFA_SPEC_SSB_DISABLE 3 /* Speculative Store Bypass disabled */
    #define PFA_SPEC_SSB_FORCE_DISABLE 4 /* Speculative Store Bypass force disabled*/
    +#define PFA_SPEC_IB_DISABLE 5 /* Indirect branch speculation restricted */
    +#define PFA_SPEC_IB_FORCE_DISABLE 6 /* Indirect branch speculation permanently restricted */

    #define TASK_PFA_TEST(name, func) \
    static inline bool task_##func(struct task_struct *p) \
    @@ -1470,6 +1472,13 @@ TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ss
    TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
    TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)

    +TASK_PFA_TEST(SPEC_IB_DISABLE, spec_ib_disable)
    +TASK_PFA_SET(SPEC_IB_DISABLE, spec_ib_disable)
    +TASK_PFA_CLEAR(SPEC_IB_DISABLE, spec_ib_disable)
    +
    +TASK_PFA_TEST(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
    +TASK_PFA_SET(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
    +
    static inline void
    current_restore_flags(unsigned long orig_flags, unsigned long flags)
    {
    --- a/include/uapi/linux/prctl.h
    +++ b/include/uapi/linux/prctl.h
    @@ -212,6 +212,7 @@ struct prctl_mm_map {
    #define PR_SET_SPECULATION_CTRL 53
    /* Speculation control variants */
    # define PR_SPEC_STORE_BYPASS 0
    +# define PR_SPEC_INDIRECT_BRANCH 1
    /* Return and control values for PR_SET/GET_SPECULATION_CTRL */
    # define PR_SPEC_NOT_AFFECTED 0
    # define PR_SPEC_PRCTL (1UL << 0)
    --- a/tools/include/uapi/linux/prctl.h
    +++ b/tools/include/uapi/linux/prctl.h
    @@ -212,6 +212,7 @@ struct prctl_mm_map {
    #define PR_SET_SPECULATION_CTRL 53
    /* Speculation control variants */
    # define PR_SPEC_STORE_BYPASS 0
    +# define PR_SPEC_INDIRECT_BRANCH 1
    /* Return and control values for PR_SET/GET_SPECULATION_CTRL */
    # define PR_SPEC_NOT_AFFECTED 0
    # define PR_SPEC_PRCTL (1UL << 0)

    \
     
     \ /
      Last update: 2018-12-04 11:58    [W:4.106 / U:0.568 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site