lkml.org 
[lkml]   [2018]   [Apr]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 34/37] x86/ldt: Enable LDT user-mapping for PAE
    Date
    From: Joerg Roedel <jroedel@suse.de>

    This adds the needed special case for PAE to get the LDT
    mapped into the user page-table when PTI is enabled. The big
    difference to the other paging modes is that we don't have a
    full top-level PGD entry available for the LDT, but only PMD
    entry.

    Signed-off-by: Joerg Roedel <jroedel@suse.de>
    ---
    arch/x86/include/asm/mmu_context.h | 5 ----
    arch/x86/kernel/ldt.c | 53 ++++++++++++++++++++++++++++++++++++++
    2 files changed, 53 insertions(+), 5 deletions(-)

    diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
    index 57e3785..28b2376 100644
    --- a/arch/x86/include/asm/mmu_context.h
    +++ b/arch/x86/include/asm/mmu_context.h
    @@ -71,12 +71,7 @@ struct ldt_struct {

    static inline void *ldt_slot_va(int slot)
    {
    -#ifdef CONFIG_X86_64
    return (void *)(LDT_BASE_ADDR + LDT_SLOT_STRIDE * slot);
    -#else
    - BUG();
    - return (void *)fix_to_virt(FIX_HOLE);
    -#endif
    }

    /*
    diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
    index 69af9a0..733e6ac 100644
    --- a/arch/x86/kernel/ldt.c
    +++ b/arch/x86/kernel/ldt.c
    @@ -126,6 +126,57 @@ static void do_sanity_check(struct mm_struct *mm,
    }
    }

    +#ifdef CONFIG_X86_PAE
    +
    +static pmd_t *pgd_to_pmd_walk(pgd_t *pgd, unsigned long va)
    +{
    + p4d_t *p4d;
    + pud_t *pud;
    +
    + if (pgd->pgd == 0)
    + return NULL;
    +
    + p4d = p4d_offset(pgd, va);
    + if (p4d_none(*p4d))
    + return NULL;
    +
    + pud = pud_offset(p4d, va);
    + if (pud_none(*pud))
    + return NULL;
    +
    + return pmd_offset(pud, va);
    +}
    +
    +static void map_ldt_struct_to_user(struct mm_struct *mm)
    +{
    + pgd_t *k_pgd = pgd_offset(mm, LDT_BASE_ADDR);
    + pgd_t *u_pgd = kernel_to_user_pgdp(k_pgd);
    + pmd_t *k_pmd, *u_pmd;
    +
    + k_pmd = pgd_to_pmd_walk(k_pgd, LDT_BASE_ADDR);
    + u_pmd = pgd_to_pmd_walk(u_pgd, LDT_BASE_ADDR);
    +
    + if (static_cpu_has(X86_FEATURE_PTI) && !mm->context.ldt)
    + set_pmd(u_pmd, *k_pmd);
    +}
    +
    +static void sanity_check_ldt_mapping(struct mm_struct *mm)
    +{
    + pgd_t *k_pgd = pgd_offset(mm, LDT_BASE_ADDR);
    + pgd_t *u_pgd = kernel_to_user_pgdp(k_pgd);
    + bool had_kernel, had_user;
    + pmd_t *k_pmd, *u_pmd;
    +
    + k_pmd = pgd_to_pmd_walk(k_pgd, LDT_BASE_ADDR);
    + u_pmd = pgd_to_pmd_walk(u_pgd, LDT_BASE_ADDR);
    + had_kernel = (k_pmd->pmd != 0);
    + had_user = (u_pmd->pmd != 0);
    +
    + do_sanity_check(mm, had_kernel, had_user);
    +}
    +
    +#else /* !CONFIG_X86_PAE */
    +
    static void map_ldt_struct_to_user(struct mm_struct *mm)
    {
    pgd_t *pgd = pgd_offset(mm, LDT_BASE_ADDR);
    @@ -143,6 +194,8 @@ static void sanity_check_ldt_mapping(struct mm_struct *mm)
    do_sanity_check(mm, had_kernel, had_user);
    }

    +#endif /* CONFIG_X86_PAE */
    +
    /*
    * If PTI is enabled, this maps the LDT into the kernelmode and
    * usermode tables for the given mm.
    --
    2.7.4
    \
     
     \ /
      Last update: 2018-04-23 17:49    [W:4.182 / U:0.208 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site