lkml.org 
[lkml]   [2020]   [Dec]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v16 3/7] x86/cet/ibt: Handle signals for Indirect Branch Tracking
    Date
    When an indirect CALL/JMP instruction is executed and before it reaches
    the target, it is in 'WAIT_ENDBR' status, which can be read from
    MSR_IA32_U_CET. The status is part of a task's status before a signal is
    raised and preserved in the signal frame. It is restored for sigreturn.

    IBT state machine is described in Intel SDM Vol. 1, Sec. 18.3.

    Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
    ---
    arch/x86/kernel/cet.c | 27 +++++++++++++++++++++++++--
    arch/x86/kernel/fpu/signal.c | 8 +++++---
    2 files changed, 30 insertions(+), 5 deletions(-)

    diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c
    index e8871bccce65..d23f68074ab6 100644
    --- a/arch/x86/kernel/cet.c
    +++ b/arch/x86/kernel/cet.c
    @@ -295,6 +295,13 @@ void cet_restore_signal(struct sc_ext *sc_ext)
    msr_val |= CET_SHSTK_EN;
    }

    + if (cet->ibt_enabled) {
    + msr_val |= (CET_ENDBR_EN | CET_NO_TRACK_EN);
    +
    + if (sc_ext->wait_endbr)
    + msr_val |= CET_WAIT_ENDBR;
    + }
    +
    if (test_thread_flag(TIF_NEED_FPU_LOAD))
    cet_user_state->user_cet = msr_val;
    else
    @@ -335,9 +342,25 @@ int cet_setup_signal(bool ia32, unsigned long rstor_addr, struct sc_ext *sc_ext)
    sc_ext->ssp = new_ssp;
    }

    - if (ssp) {
    + if (ssp || cet->ibt_enabled) {
    +
    start_update_msrs();
    - wrmsrl(MSR_IA32_PL3_SSP, ssp);
    +
    + if (ssp)
    + wrmsrl(MSR_IA32_PL3_SSP, ssp);
    +
    + if (cet->ibt_enabled) {
    + u64 r;
    +
    + rdmsrl(MSR_IA32_U_CET, r);
    +
    + if (r & CET_WAIT_ENDBR) {
    + sc_ext->wait_endbr = 1;
    + r &= ~CET_WAIT_ENDBR;
    + wrmsrl(MSR_IA32_U_CET, r);
    + }
    + }
    +
    end_update_msrs();
    }

    diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
    index d5d02b34f516..50f28b37e093 100644
    --- a/arch/x86/kernel/fpu/signal.c
    +++ b/arch/x86/kernel/fpu/signal.c
    @@ -57,7 +57,8 @@ int save_cet_to_sigframe(int ia32, void __user *fp, unsigned long restorer)
    {
    int err = 0;

    - if (!current->thread.cet.shstk_size)
    + if (!current->thread.cet.shstk_size &&
    + !current->thread.cet.ibt_enabled)
    return 0;

    if (fp) {
    @@ -89,7 +90,8 @@ static int get_cet_from_sigframe(int ia32, void __user *fp, struct sc_ext *ext)

    memset(ext, 0, sizeof(*ext));

    - if (!current->thread.cet.shstk_size)
    + if (!current->thread.cet.shstk_size &&
    + !current->thread.cet.ibt_enabled)
    return 0;

    if (fp) {
    @@ -577,7 +579,7 @@ static unsigned long fpu__alloc_sigcontext_ext(unsigned long sp)
    * sigcontext_ext is at: fpu + fpu_user_xstate_size +
    * FP_XSTATE_MAGIC2_SIZE, then aligned to 8.
    */
    - if (cet->shstk_size)
    + if (cet->shstk_size || cet->ibt_enabled)
    sp -= (sizeof(struct sc_ext) + 8);

    return sp;
    --
    2.21.0
    \
     
     \ /
      Last update: 2020-12-09 23:32    [W:2.508 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site