lkml.org 
[lkml]   [2019]   [Jul]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v9 18/21] x86: mm: Convert ptdump_walk_pgd_level_core() to take an mm_struct
    Date
    An mm_struct is needed to enable x86 to use of the generic
    walk_page_range() function.

    In the case of walking the user page tables (when
    CONFIG_PAGE_TABLE_ISOLATION is enabled), it is necessary to create a
    fake_mm structure because there isn't an mm_struct with a pointer
    to the pgd of the user page tables. This fake_mm structure is
    initialised with the minimum necessary for the generic page walk code.

    Signed-off-by: Steven Price <steven.price@arm.com>
    ---
    arch/x86/mm/dump_pagetables.c | 36 ++++++++++++++++++++---------------
    1 file changed, 21 insertions(+), 15 deletions(-)

    diff --git a/arch/x86/mm/dump_pagetables.c b/arch/x86/mm/dump_pagetables.c
    index bcaf27b637e0..546e28a7785c 100644
    --- a/arch/x86/mm/dump_pagetables.c
    +++ b/arch/x86/mm/dump_pagetables.c
    @@ -107,8 +107,6 @@ static struct addr_marker address_markers[] = {
    [END_OF_SPACE_NR] = { -1, NULL }
    };

    -#define INIT_PGD ((pgd_t *) &init_top_pgt)
    -
    #else /* CONFIG_X86_64 */

    enum address_markers_idx {
    @@ -143,8 +141,6 @@ static struct addr_marker address_markers[] = {
    [END_OF_SPACE_NR] = { -1, NULL }
    };

    -#define INIT_PGD (swapper_pg_dir)
    -
    #endif /* !CONFIG_X86_64 */

    /* Multipliers for offsets within the PTEs */
    @@ -516,10 +512,10 @@ static inline bool is_hypervisor_range(int idx)
    #endif
    }

    -static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,
    +static void ptdump_walk_pgd_level_core(struct seq_file *m, struct mm_struct *mm,
    bool checkwx, bool dmesg)
    {
    - pgd_t *start = pgd;
    + pgd_t *start = mm->pgd;
    pgprotval_t prot, eff;
    int i;
    struct pg_state st = {};
    @@ -566,39 +562,49 @@ static void ptdump_walk_pgd_level_core(struct seq_file *m, pgd_t *pgd,

    void ptdump_walk_pgd_level(struct seq_file *m, struct mm_struct *mm)
    {
    - ptdump_walk_pgd_level_core(m, mm->pgd, false, true);
    + ptdump_walk_pgd_level_core(m, mm, false, true);
    }

    +#ifdef CONFIG_PAGE_TABLE_ISOLATION
    +static void ptdump_walk_pgd_level_user_core(struct seq_file *m,
    + struct mm_struct *mm,
    + bool checkwx, bool dmesg)
    +{
    + struct mm_struct fake_mm = {
    + .pgd = kernel_to_user_pgdp(mm->pgd)
    + };
    + init_rwsem(&fake_mm.mmap_sem);
    + ptdump_walk_pgd_level_core(m, &fake_mm, checkwx, dmesg);
    +}
    +#endif
    +
    void ptdump_walk_pgd_level_debugfs(struct seq_file *m, struct mm_struct *mm,
    bool user)
    {
    - pgd_t *pgd = mm->pgd;
    #ifdef CONFIG_PAGE_TABLE_ISOLATION
    if (user && boot_cpu_has(X86_FEATURE_PTI))
    - pgd = kernel_to_user_pgdp(pgd);
    + ptdump_walk_pgd_level_user_core(m, mm, false, false);
    + else
    #endif
    - ptdump_walk_pgd_level_core(m, pgd, false, false);
    + ptdump_walk_pgd_level_core(m, mm, false, false);
    }
    EXPORT_SYMBOL_GPL(ptdump_walk_pgd_level_debugfs);

    void ptdump_walk_user_pgd_level_checkwx(void)
    {
    #ifdef CONFIG_PAGE_TABLE_ISOLATION
    - pgd_t *pgd = INIT_PGD;
    -
    if (!(__supported_pte_mask & _PAGE_NX) ||
    !boot_cpu_has(X86_FEATURE_PTI))
    return;

    pr_info("x86/mm: Checking user space page tables\n");
    - pgd = kernel_to_user_pgdp(pgd);
    - ptdump_walk_pgd_level_core(NULL, pgd, true, false);
    + ptdump_walk_pgd_level_user_core(NULL, &init_mm, true, false);
    #endif
    }

    void ptdump_walk_pgd_level_checkwx(void)
    {
    - ptdump_walk_pgd_level_core(NULL, INIT_PGD, true, false);
    + ptdump_walk_pgd_level_core(NULL, &init_mm, true, false);
    }

    static int __init pt_dump_init(void)
    --
    2.20.1
    \
     
     \ /
      Last update: 2019-07-22 17:43    [W:3.463 / U:0.188 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site