@@ -19,6 +19,8 @@
#include <linux/vmstat.h>
#include <linux/kernel.h>
#include <linux/pkeys.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
#include <asm/e820/api.h>
#include <asm/processor.h>
@@ -2703,6 +2705,45 @@ static void traverse_mm(struct mm_struct *mm, traverse_cb cb)
traverse_pgd(mm->pgd, cb, 0);
}
+#ifdef CONFIG_PKS_PG_TABLES_DEBUG
+static void check_table_protected(unsigned long pfn, void *vaddr, void *vend)
+{
+ if (is_dmap_protected((unsigned long)__va(pfn << PAGE_SHIFT)))
+ return;
+
+ pr_warn("Found unprotected page, pfn: %lx maps address:0x%p\n", pfn, vaddr);
+}
+
+static int table_scan_fn(void *data)
+{
+ while (1) {
+ msleep(MSEC_PER_SEC);
+ mmap_read_lock(current->active_mm);
+ traverse_mm(current->active_mm, &check_table_protected);
+ mmap_read_unlock(current->active_mm);
+ }
+ return 0;
+}
+
+static void __init init_pks_table_scan(void)
+{
+ struct task_struct *thread;
+ int cpu;
+
+ pr_info("Starting pks_table_debug thread on %d cpus\n", num_online_cpus());
+ for (cpu = 0; cpu < num_online_cpus(); cpu++) {
+ thread = kthread_create_on_cpu(table_scan_fn, NULL, cpu, "pks_table_debug");
+ if (IS_ERR(thread)) {
+ pr_err("Failed to create pks_table_debug threads\n");
+ break;
+ }
+ wake_up_process(thread);
+ }
+}
+#else
+static void __init init_pks_table_scan(void) { }
+#endif
+
static void free_maybe_reserved(struct page *page)
{
if (PageReserved(page))
@@ -2776,6 +2817,8 @@ static int __init init_pks_dmap_tables(void)
*/
traverse_mm(&init_mm, &ensure_table_protected);
+ init_pks_table_scan();
+
return 0;
out_err:
while ((cur = llist_del_first(&tables_to_covert))) {
@@ -863,6 +863,11 @@ config PKS_PG_TABLES_SOFT_ALWAYS
still like to get notifications of illegitimate attempts to modify
them.
+config PKS_PG_TABLES_DEBUG
+ def_bool y
+ depends on PKS_PG_TABLES
+
+
config PERCPU_STATS
bool "Collect percpu memory statistics"
help
Add a runtime checker that scans the currently used page tables to check that they are all protected on the direct map, in the case of PKS tables. Use the recently added page table traverser. There are many possible ways to modify and allocate page tables. In order to catch any missed cases, just traverse the active tables every second and check the direct map protection for each. This feature is intended for debugging only. Another way to do this without the awkward timers, is to check each page while contructing the PTE. It may be useful for enhance the protection as well. But this could miss any strange wrong page table modifications hidden away somewhere in the kernel. So for debug time, the scanner is a little more thorough. Signed-off-by: Rick Edgecombe <rick.p.edgecombe@intel.com> --- arch/x86/mm/pat/set_memory.c | 43 ++++++++++++++++++++++++++++++++++++ mm/Kconfig | 5 +++++ 2 files changed, 48 insertions(+)