diff --git a/kernel_module/mmap.c b/kernel_module/mmap.c index 68325dd0..188355ca 100644 --- a/kernel_module/mmap.c +++ b/kernel_module/mmap.c @@ -74,6 +74,7 @@ static int open(struct inode *inode, struct file *filp) pr_info("open\n"); info = kmalloc(sizeof(struct mmap_info), GFP_KERNEL); + pr_info("virt_to_phys = 0x%llx\n", (unsigned long long)virt_to_phys((void *)info->data)); info->data = (char *)get_zeroed_page(GFP_KERNEL); memcpy(info->data, "asdf", BUFFER_SIZE); filp->private_data = info; diff --git a/kernel_module/user/pagemap_dump.c b/kernel_module/user/pagemap_dump.c index 6e015316..b5b1c241 100644 --- a/kernel_module/user/pagemap_dump.c +++ b/kernel_module/user/pagemap_dump.c @@ -3,19 +3,48 @@ Only tested in x86_64. Adapted from: https://github.com/dwks/pagemap/blob/8a25747bc79d6080c8b94eac80807a4dceeda57a/pagemap2.c +https://stackoverflow.com/questions/17021214/how-to-decode-proc-pid-pagemap-entries-in-linux/45126141#45126141 + Dump the page map of a given process PID. Data sources: /proc/PIC/{map,pagemap} */ #define _POSIX_C_SOURCE 200809L +#include +#include +#include #include #include -#include -#include -#include #include -#define PAGE_SIZE 0x1000 +#include + +typedef struct { + uint64_t phys : 54; + int soft_dirty : 1; + int padding : 4; + int padding : 1; + + * Bit 61 page is file-page or shared-anon (since 3.5) + * Bit 62 page swapped + * Bit 63 page present +} PagemapEntry; + + +int parse_pagemap(PagemapEntry &entry, int fd, size_t offset) +{ + if (pread(pagemap, &data, ) != sizeof(data)) { + perror("pread"); + break; + } + + data & 0x7fffffffffffff, + (data >> 55) & 1, + (data >> 61) & 1, + (data >> 62) & 1, + (data >> 63) & 1, + +} int main(int argc, char **argv) { char buffer[BUFSIZ]; @@ -24,6 +53,7 @@ int main(int argc, char **argv) { int maps; int offset = 0; int pagemap; + long page_size; if (argc < 2) { printf("Usage: %s pid\n", argv[0]); @@ -42,6 +72,7 @@ int main(int argc, char **argv) { perror("open pagemap"); return EXIT_FAILURE; } + page_size = sysconf(_SC_PAGE_SIZE); printf("addr pfn soft-dirty file/shared swapped present library\n"); for (;;) { ssize_t length = read(maps, buffer + offset, sizeof buffer - offset); @@ -66,8 +97,9 @@ int main(int argc, char **argv) { } else if (c >= 'a' && c <= 'f') { low += c - 'a' + 10; + } else { + break; } - else break; } while(buffer[x] != '-' && x < sizeof buffer) x++; if (buffer[x] == '-') x++; @@ -96,12 +128,10 @@ int main(int argc, char **argv) { /* Get info about all pages in this page range with pagemap. */ { unsigned long data; - for (unsigned long i = low; i < high; i += PAGE_SIZE) { - unsigned long index = (i / PAGE_SIZE) * sizeof(data); - if (pread(pagemap, &data, sizeof(data), index) != sizeof(data)) { - if (errno) perror("pread"); - break; - } + PagemapEntry entry; + for (unsigned long i = low; i < high; i += page_size) { + unsigned long index = (i / page_size) * sizeof(data); + parse_pagemap(&entry, pagemap, sizeof(data) * index); printf("%lx %lx %d %d %d %d %s\n", i, data & 0x7fffffffffffff,