|
@@ -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.
|