Skip to content

Instantly share code, notes, and snippets.

@diekmann
Created June 9, 2017 15:04
Show Gist options
  • Save diekmann/74fbb137517588d210ce73c8ed7cc422 to your computer and use it in GitHub Desktop.
Save diekmann/74fbb137517588d210ce73c8ed7cc422 to your computer and use it in GitHub Desktop.
[draft] dump outermost page table in with 4 level paging (Linux x64 default)
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
#ifndef __x86_64__
#error "wrong arch"
#endif
struct page_table{
void* entry[512];
};
static int __init test_module_init(void)
{
/* https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf pp.2783
* March 2017, version 062 */
/*Chap 3.2.1 64-Bit Mode Execution Environment. Control registers expand to 64 bits*/
u64 cr0, cr3, cr4 = 0;
u64 ia32_efer = 0;
BUILD_BUG_ON(sizeof(struct page_table) != 4096);
BUILD_BUG_ON(sizeof(void *) != 8);
BUILD_BUG_ON(PAGE_SIZE != 4096);
pr_warn("Hello, world\n");
printk("(%s) x86_phys_bits %hu\n", boot_cpu_data.x86_vendor_id, boot_cpu_data.x86_phys_bits);
__asm__ __volatile__ ("mov %%cr0, %%rax \n mov %%rax,%0": "=m" (cr0) : /*InputOperands*/ : "rax");
__asm__ __volatile__ ("mov %%cr3, %%rax \n mov %%rax,%0": "=m" (cr3) : /*InputOperands*/ : "rax");
__asm__ __volatile__ ("mov %%cr4, %%rax \n mov %%rax,%0": "=m" (cr4) : /*InputOperands*/ : "rax");
if(rdmsrl_safe(MSR_EFER, &ia32_efer)){
printk("Error reading MSR\n");
return 1;
}
printk("cr3: 0x%llx\n", cr3);
if(cr3 & 0xfe7 /*ignored*/
|| (cr3 & (0xffffffffffffffffLL << boot_cpu_data.x86_phys_bits) /*reserved*/)){
printk("cr3 looks shady\n");
}
if(cr3 & X86_CR3_PWT || cr3 & X86_CR3_PCD){
printk("unexpected options in cr3\n");
}
if(cr0 & X86_CR0_PG && cr4 & X86_CR4_PAE && ia32_efer & EFER_LME && !(cr4 & X86_CR4_PCIDE)){
printk("paging according to Tab 4-12 p. 2783 intel dev manual (March 2017)\n");
}else{
printk("unknown paging setup\n");
return -EPERM; /*I'm afraid I can't do that*/
}
if(!(cr4 & X86_CR4_PKE)){
printk("No protection keys enabled (this is normal)\n");
}
struct page_table *pml4 = phys_to_virt(cr3);
printk("page table in virtual memory at %p\n", pml4);
if(!virt_addr_valid(pml4) || !IS_ALIGNED(cr3, 4096)){
printk("invalid addr!\n");
return 1; /*error*/
}
int i;
u64 addr, addr_max;
//walk the outermost page table
for(i = 0; i < 512; ++i){
u64 e = (u64)pml4->entry[i];
if(!(e & 0x1LL) /*present*/){
WARN_ON(e);
continue;
}
printk("entry %p\n", pml4->entry[i]);
//TODO check calculation sanity with /proc/self/maps and /proc/vmallocinfo
addr = i;
addr <<= 39; //bits 39:47 (inclusive)
addr_max = 0x7fffffffffLL; //2**39-1
if(addr & (1LL << 47) /*highest bit set*/){
addr |= (0xffffLL << 48);
}
addr_max |= addr;
printk("v %p %p\n", (void*)addr, (void*)addr_max);
}
return 0;
}
module_init(test_module_init);
static void __exit test_module_exit(void)
{
pr_warn("Goodbye\n");
}
module_exit(test_module_exit);
MODULE_AUTHOR("Cornelius Diekmann);
MODULE_LICENSE("GPL");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment