lkml.org 
[lkml]   [2020]   [Jul]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.7 221/244] x86/ioperm: Fix io bitmap invalidation on Xen PV
    Date
    From: Andy Lutomirski <luto@kernel.org>

    commit cadfad870154e14f745ec845708bc17d166065f2 upstream.

    tss_invalidate_io_bitmap() wasn't wired up properly through the pvop
    machinery, so the TSS and Xen's io bitmap would get out of sync
    whenever disabling a valid io bitmap.

    Add a new pvop for tss_invalidate_io_bitmap() to fix it.

    This is XSA-329.

    Fixes: 22fe5b0439dd ("x86/ioperm: Move TSS bitmap update to exit to user work")
    Signed-off-by: Andy Lutomirski <luto@kernel.org>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Reviewed-by: Juergen Gross <jgross@suse.com>
    Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: stable@vger.kernel.org
    Link: https://lkml.kernel.org/r/d53075590e1f91c19f8af705059d3ff99424c020.1595030016.git.luto@kernel.org
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    arch/x86/include/asm/io_bitmap.h | 16 ++++++++++++++++
    arch/x86/include/asm/paravirt.h | 5 +++++
    arch/x86/include/asm/paravirt_types.h | 1 +
    arch/x86/kernel/paravirt.c | 3 ++-
    arch/x86/kernel/process.c | 18 ++----------------
    arch/x86/xen/enlighten_pv.c | 12 ++++++++++++
    6 files changed, 38 insertions(+), 17 deletions(-)

    --- a/arch/x86/include/asm/io_bitmap.h
    +++ b/arch/x86/include/asm/io_bitmap.h
    @@ -19,12 +19,28 @@ struct task_struct;
    void io_bitmap_share(struct task_struct *tsk);
    void io_bitmap_exit(struct task_struct *tsk);

    +static inline void native_tss_invalidate_io_bitmap(void)
    +{
    + /*
    + * Invalidate the I/O bitmap by moving io_bitmap_base outside the
    + * TSS limit so any subsequent I/O access from user space will
    + * trigger a #GP.
    + *
    + * This is correct even when VMEXIT rewrites the TSS limit
    + * to 0x67 as the only requirement is that the base points
    + * outside the limit.
    + */
    + this_cpu_write(cpu_tss_rw.x86_tss.io_bitmap_base,
    + IO_BITMAP_OFFSET_INVALID);
    +}
    +
    void native_tss_update_io_bitmap(void);

    #ifdef CONFIG_PARAVIRT_XXL
    #include <asm/paravirt.h>
    #else
    #define tss_update_io_bitmap native_tss_update_io_bitmap
    +#define tss_invalidate_io_bitmap native_tss_invalidate_io_bitmap
    #endif

    #else
    --- a/arch/x86/include/asm/paravirt.h
    +++ b/arch/x86/include/asm/paravirt.h
    @@ -296,6 +296,11 @@ static inline void write_idt_entry(gate_
    }

    #ifdef CONFIG_X86_IOPL_IOPERM
    +static inline void tss_invalidate_io_bitmap(void)
    +{
    + PVOP_VCALL0(cpu.invalidate_io_bitmap);
    +}
    +
    static inline void tss_update_io_bitmap(void)
    {
    PVOP_VCALL0(cpu.update_io_bitmap);
    --- a/arch/x86/include/asm/paravirt_types.h
    +++ b/arch/x86/include/asm/paravirt_types.h
    @@ -141,6 +141,7 @@ struct pv_cpu_ops {
    void (*load_sp0)(unsigned long sp0);

    #ifdef CONFIG_X86_IOPL_IOPERM
    + void (*invalidate_io_bitmap)(void);
    void (*update_io_bitmap)(void);
    #endif

    --- a/arch/x86/kernel/paravirt.c
    +++ b/arch/x86/kernel/paravirt.c
    @@ -343,7 +343,8 @@ struct paravirt_patch_template pv_ops =
    .cpu.swapgs = native_swapgs,

    #ifdef CONFIG_X86_IOPL_IOPERM
    - .cpu.update_io_bitmap = native_tss_update_io_bitmap,
    + .cpu.invalidate_io_bitmap = native_tss_invalidate_io_bitmap,
    + .cpu.update_io_bitmap = native_tss_update_io_bitmap,
    #endif

    .cpu.start_context_switch = paravirt_nop,
    --- a/arch/x86/kernel/process.c
    +++ b/arch/x86/kernel/process.c
    @@ -322,20 +322,6 @@ void arch_setup_new_exec(void)
    }

    #ifdef CONFIG_X86_IOPL_IOPERM
    -static inline void tss_invalidate_io_bitmap(struct tss_struct *tss)
    -{
    - /*
    - * Invalidate the I/O bitmap by moving io_bitmap_base outside the
    - * TSS limit so any subsequent I/O access from user space will
    - * trigger a #GP.
    - *
    - * This is correct even when VMEXIT rewrites the TSS limit
    - * to 0x67 as the only requirement is that the base points
    - * outside the limit.
    - */
    - tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET_INVALID;
    -}
    -
    static inline void switch_to_bitmap(unsigned long tifp)
    {
    /*
    @@ -346,7 +332,7 @@ static inline void switch_to_bitmap(unsi
    * user mode.
    */
    if (tifp & _TIF_IO_BITMAP)
    - tss_invalidate_io_bitmap(this_cpu_ptr(&cpu_tss_rw));
    + tss_invalidate_io_bitmap();
    }

    static void tss_copy_io_bitmap(struct tss_struct *tss, struct io_bitmap *iobm)
    @@ -380,7 +366,7 @@ void native_tss_update_io_bitmap(void)
    u16 *base = &tss->x86_tss.io_bitmap_base;

    if (!test_thread_flag(TIF_IO_BITMAP)) {
    - tss_invalidate_io_bitmap(tss);
    + native_tss_invalidate_io_bitmap();
    return;
    }

    --- a/arch/x86/xen/enlighten_pv.c
    +++ b/arch/x86/xen/enlighten_pv.c
    @@ -841,6 +841,17 @@ static void xen_load_sp0(unsigned long s
    }

    #ifdef CONFIG_X86_IOPL_IOPERM
    +static void xen_invalidate_io_bitmap(void)
    +{
    + struct physdev_set_iobitmap iobitmap = {
    + .bitmap = 0,
    + .nr_ports = 0,
    + };
    +
    + native_tss_invalidate_io_bitmap();
    + HYPERVISOR_physdev_op(PHYSDEVOP_set_iobitmap, &iobitmap);
    +}
    +
    static void xen_update_io_bitmap(void)
    {
    struct physdev_set_iobitmap iobitmap;
    @@ -1070,6 +1081,7 @@ static const struct pv_cpu_ops xen_cpu_o
    .load_sp0 = xen_load_sp0,

    #ifdef CONFIG_X86_IOPL_IOPERM
    + .invalidate_io_bitmap = xen_invalidate_io_bitmap,
    .update_io_bitmap = xen_update_io_bitmap,
    #endif
    .io_delay = xen_io_delay,

    \
     
     \ /
      Last update: 2020-07-20 18:18    [W:4.073 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site