lkml.org 
[lkml]   [2018]   [Nov]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 22/24] x86/speculation: Create PRCTL interface to restrict indirect branch speculation
    From: Tim Chen <tim.c.chen@linux.intel.com>

    Add the PR_SPEC_INDIR_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.

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

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

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

    Force disable indirect branch speculation with
    - prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIR_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>

    ---
    Documentation/userspace-api/spec_ctrl.rst | 9 +++
    arch/x86/include/asm/nospec-branch.h | 1
    arch/x86/kernel/cpu/bugs.c | 71 ++++++++++++++++++++++++++++++
    include/linux/sched.h | 9 +++
    include/uapi/linux/prctl.h | 1
    tools/include/uapi/linux/prctl.h | 1
    6 files changed, 92 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_INDIR_BRANCH, 0, 0, 0);
    + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIR_BRANCH, PR_SPEC_ENABLE, 0, 0);
    + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIR_BRANCH, PR_SPEC_DISABLE, 0, 0);
    + * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIR_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_app2app_mitigation {
    SPECTRE_V2_APP2APP_NONE,
    SPECTRE_V2_APP2APP_STRICT,
    + SPECTRE_V2_APP2APP_PRCTL,
    };

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

    mutex_unlock(&spec_ctrl_mutex);
    @@ -753,12 +755,56 @@ static int ssb_prctl_set(struct task_str
    return 0;
    }

    +static int indir_branch_prctl_set(struct task_struct *task, unsigned long ctrl)
    +{
    + switch (ctrl) {
    + case PR_SPEC_ENABLE:
    + if (spectre_v2_app2app == SPECTRE_V2_APP2APP_NONE)
    + return 0;
    + /*
    + * Indirect branch speculation is always disabled in strict
    + * mode.
    + */
    + if (spectre_v2_app2app == SPECTRE_V2_APP2APP_STRICT)
    + return -EPERM;
    + task_clear_spec_indir_branch_disable(task);
    + task_update_spec_tif(task, TIF_SPEC_IB, false);
    + break;
    + case PR_SPEC_DISABLE:
    + /*
    + * Indirect branch speculation is always allowed when
    + * mitigation is force disabled.
    + */
    + if (spectre_v2_app2app == SPECTRE_V2_APP2APP_NONE)
    + return -EPERM;
    + if (spectre_v2_app2app == SPECTRE_V2_APP2APP_STRICT)
    + return 0;
    + task_set_spec_indir_branch_disable(task);
    + task_update_spec_tif(task, TIF_SPEC_IB, true);
    + break;
    + case PR_SPEC_FORCE_DISABLE:
    + if (spectre_v2_app2app == SPECTRE_V2_APP2APP_NONE)
    + return -EPERM;
    + if (spectre_v2_app2app == SPECTRE_V2_APP2APP_STRICT)
    + return 0;
    + task_set_spec_indir_branch_disable(task);
    + task_set_spec_indir_branch_force_disable(task);
    + task_update_spec_tif(task, TIF_SPEC_IB, true);
    + 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_INDIR_BRANCH:
    + return indir_branch_prctl_set(task, ctrl);
    default:
    return -ENODEV;
    }
    @@ -791,11 +837,34 @@ static int ssb_prctl_get(struct task_str
    }
    }

    +static int indir_branch_prctl_get(struct task_struct *task)
    +{
    + if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
    + return PR_SPEC_NOT_AFFECTED;
    +
    + switch (spectre_v2_app2app) {
    + case SPECTRE_V2_APP2APP_NONE:
    + return PR_SPEC_ENABLE;
    + case SPECTRE_V2_APP2APP_PRCTL:
    + if (task_spec_indir_branch_force_disable(task))
    + return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
    + if (test_tsk_thread_flag(task, TIF_SPEC_IB))
    + return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
    + return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
    + case SPECTRE_V2_APP2APP_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_INDIR_BRANCH:
    + return indir_branch_prctl_get(task);
    default:
    return -ENODEV;
    }
    @@ -975,6 +1044,8 @@ static char *stibp_state(void)
    return ", STIBP: disabled";
    case SPECTRE_V2_APP2APP_STRICT:
    return ", STIBP: forced";
    + case SPECTRE_V2_APP2APP_PRCTL:
    + return "";
    }
    return "";
    }
    --- a/include/linux/sched.h
    +++ b/include/linux/sched.h
    @@ -1453,6 +1453,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_INDIR_BRANCH_DISABLE 5 /* Indirect branch speculation restricted */
    +#define PFA_SPEC_INDIR_BRANCH_FORCE_DISABLE 6 /* Indirect branch speculation permanentely restricted */

    #define TASK_PFA_TEST(name, func) \
    static inline bool task_##func(struct task_struct *p) \
    @@ -1484,6 +1486,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_INDIR_BRANCH_DISABLE, spec_indir_branch_disable)
    +TASK_PFA_SET(SPEC_INDIR_BRANCH_DISABLE, spec_indir_branch_disable)
    +TASK_PFA_CLEAR(SPEC_INDIR_BRANCH_DISABLE, spec_indir_branch_disable)
    +
    +TASK_PFA_TEST(SPEC_INDIR_BRANCH_FORCE_DISABLE, spec_indir_branch_force_disable)
    +TASK_PFA_SET(SPEC_INDIR_BRANCH_FORCE_DISABLE, spec_indir_branch_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_INDIR_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_INDIR_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-11-21 21:19    [W:2.701 / U:0.004 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site