Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full M1 Support #45

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions demos/m1_memmap.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <stdio.h>

#include "../ptedit_header.h"

int is_present(size_t entry) {
return (entry & 3) == 3;
}

void dump(int do_dump, size_t entry, char *type) {
if (do_dump) {
for (int i = 0; i < 4; i++) {
printf("%s", type);
ptedit_print_entry_line(entry, i);
}
}
}

int main(int argc, char *argv[]) {
if (ptedit_init()) {
printf("Error: Could not initalize PTEditor, did you load the kernel module?\n");
return 1;
}

int dump_entry = 1;
size_t pid = 0;
if (argc >= 2) {
pid = atoi(argv[1]);
}

printf("Dumping PID %zd\n", pid);

size_t root = ptedit_get_paging_root(pid);
size_t pagesize = ptedit_get_pagesize();
size_t pml4[pagesize / sizeof(size_t)], pdpt[pagesize / sizeof(size_t)],
pd[pagesize / sizeof(size_t)], pt[pagesize / sizeof(size_t)];

ptedit_read_physical_page((root / pagesize)*4, (char *)pml4);

int pml4i, pdpti, pdi, pti;
size_t mem_usage = 0;

/* Iterate through PML4 entries */
for (pml4i = 0; pml4i < 2048; pml4i++) {
size_t pml4_entry = pml4[pml4i];
if (!is_present(pml4_entry))
continue;
dump(dump_entry, pml4_entry, "");

/* Iterate through PDPT entries */
ptedit_read_physical_page(ptedit_get_pfn(pml4_entry), (char *)pdpt);
for (pdpti = 0; pdpti < 2048; pdpti++) {
size_t pdpt_entry = pdpt[pdpti];
if (!is_present(pdpt_entry))
continue;
dump(dump_entry, pdpt_entry, "PDPT");

/* Iterate through PD entries */
ptedit_read_physical_page(ptedit_get_pfn(pdpt_entry), (char *)pd);
for (pdi = 0; pdi < 2048; pdi++) {
size_t pd_entry = pd[pdi];
if (!is_present(pd_entry))
continue;
dump(dump_entry, pd_entry, " PD ");

/* Iterate through PT entries */
ptedit_read_physical_page(ptedit_get_pfn(pd_entry), (char *)pt);
for (pti = 0; pti < 2048; pti++) {
size_t pt_entry = pt[pti];
if (!is_present(pt_entry))
continue;
dump(dump_entry, pt_entry, " PT ");
// only certain entries are addressable on m1 and it depends on the page directory root
mem_usage += 16384;
}
}
}
}

printf("Used memory: %zd KB\n", mem_usage / 1024);

ptedit_cleanup();
}
10 changes: 0 additions & 10 deletions module/pteditor.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,16 +537,6 @@ static long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned lon
(void)from_user(&paging, (void*)ioctl_param, sizeof(paging));
mm = get_mm(paging.pid);

#if defined(__aarch64__)
if(!mm || (mm && !mm->pgd)) {
// M1 Asahi Linux workaround with the limitation that it only works for the current process
asm volatile("mrs %0, ttbr0_el1" : "=r" (paging.root));
paging.root &= ~1;
(void)to_user((void*)ioctl_param, &paging, sizeof(paging));
return 0;
}
#endif

if(!mm) return 1;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
if(!mm_is_locked) mmap_read_lock(mm);
Expand Down
20 changes: 12 additions & 8 deletions ptedit.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ typedef struct {
int has_pgd, has_p4d, has_pud, has_pmd, has_pt;
int pgd_entries, p4d_entries, pud_entries, pmd_entries, pt_entries;
int page_offset;
int pfn_offset;
} ptedit_paging_definition_t;

static ptedit_paging_definition_t ptedit_paging_definition;
Expand Down Expand Up @@ -364,10 +365,10 @@ ptedit_fnc void ptedit_print_entry_line(size_t entry, int line) {
}
#elif defined(__aarch64__)
if (line == 0 || line == 3) {
printf("+--+--+--+---+-+--+------------------+--+-+-+-+--+---+-+\n");
printf("+--+--+--+---+-+---+--+------------------+--+-+-+-+--+---+-+\n");
}
if (line == 1) {
printf("| ?| ?|XN|PXN|C| ?| PFN |NG|A|S|P|NS|MAI|T|\n");
printf("| ?| ?|XN|PXN|C|DBM| ?| PFN |NG|A|S|P|NS|MAI|T|\n");
}
if (line == 2) {
printf("|");
Expand All @@ -376,7 +377,8 @@ ptedit_fnc void ptedit_print_entry_line(size_t entry, int line) {
PEDIT_PRINT_B(" %d", PTEDIT_B(entry, 54));
PEDIT_PRINT_B(" %d ", PTEDIT_B(entry, 53));
PEDIT_PRINT_B("%d", PTEDIT_B(entry, 52));
PEDIT_PRINT_B("%2d", (PTEDIT_B(entry, 51) << 3) | (PTEDIT_B(entry, 50) << 2) | (PTEDIT_B(entry, 49) << 1) | PTEDIT_B(entry, 48));
PEDIT_PRINT_B(" %d ", PTEDIT_B(entry, 51));
PEDIT_PRINT_B("%2d", (PTEDIT_B(entry, 50) << 2) | (PTEDIT_B(entry, 49) << 1) | PTEDIT_B(entry, 48));
printf(" %16p |", (void*)((entry >> 12) & ((1ull << 36) - 1)));
PEDIT_PRINT_B(" %d", PTEDIT_B(entry, 11));
PEDIT_PRINT_B("%d", PTEDIT_B(entry, 10));
Expand Down Expand Up @@ -468,6 +470,7 @@ ptedit_fnc int ptedit_init() {
ptedit_paging_definition.pmd_entries = 9;
ptedit_paging_definition.pt_entries = 9;
ptedit_paging_definition.page_offset = 12;
ptedit_paging_definition.pfn_offset = 0;
#elif defined(__aarch64__)
if(ptedit_get_pagesize() == 16384) {
ptedit_paging_definition.has_pgd = 1;
Expand All @@ -481,7 +484,7 @@ ptedit_fnc int ptedit_init() {
ptedit_paging_definition.pmd_entries = 11;
ptedit_paging_definition.pt_entries = 11;
ptedit_paging_definition.page_offset = 14;
ptedit_use_implementation(PTEDIT_IMPL_USER_PREAD); // M1 workaround
ptedit_paging_definition.pfn_offset = 2;
} else {
ptedit_paging_definition.has_pgd = 1;
ptedit_paging_definition.has_p4d = 0;
Expand All @@ -494,6 +497,7 @@ ptedit_fnc int ptedit_init() {
ptedit_paging_definition.pmd_entries = 9;
ptedit_paging_definition.pt_entries = 9;
ptedit_paging_definition.page_offset = 12;
ptedit_paging_definition.pfn_offset = 0;
}
#endif
return 0;
Expand Down Expand Up @@ -565,14 +569,14 @@ ptedit_fnc int ptedit_get_pagesize() {
ptedit_fnc void ptedit_read_physical_page(size_t pfn, char* buffer) {
#if defined(LINUX)
if (ptedit_umem > 0) {
if (pread(ptedit_umem, buffer, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {
if (pread(ptedit_umem, buffer, ptedit_pagesize, (pfn >> ptedit_paging_definition.pfn_offset) * ptedit_pagesize) == -1) {
return;
}
}
else {
ptedit_page_t page;
page.buffer = (unsigned char*)buffer;
page.pfn = pfn;
page.pfn = pfn >> ptedit_paging_definition.pfn_offset;
ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_READ_PAGE, (size_t)&page);
}
#else
Expand All @@ -587,14 +591,14 @@ ptedit_fnc void ptedit_read_physical_page(size_t pfn, char* buffer) {
ptedit_fnc void ptedit_write_physical_page(size_t pfn, char* content) {
#if defined(LINUX)
if (ptedit_umem > 0) {
if (pwrite(ptedit_umem, content, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {
if (pwrite(ptedit_umem, content, ptedit_pagesize, (pfn >> ptedit_paging_definition.pfn_offset) * ptedit_pagesize) == -1) {
return;
}
}
else {
ptedit_page_t page;
page.buffer = (unsigned char*)content;
page.pfn = pfn;
page.pfn = pfn >> ptedit_paging_definition.pfn_offset;
ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_WRITE_PAGE, (size_t)&page);
}
#else
Expand Down
22 changes: 14 additions & 8 deletions ptedit_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#undef LINUX
#endif

#include <sys/types.h>


#if defined(LINUX)
#define PTEDITOR_DEVICE_NAME "pteditor"
Expand Down Expand Up @@ -1041,6 +1043,7 @@ typedef struct {
int has_pgd, has_p4d, has_pud, has_pmd, has_pt;
int pgd_entries, p4d_entries, pud_entries, pmd_entries, pt_entries;
int page_offset;
int pfn_offset;
} ptedit_paging_definition_t;

static ptedit_paging_definition_t ptedit_paging_definition;
Expand Down Expand Up @@ -1363,10 +1366,10 @@ ptedit_fnc void ptedit_print_entry_line(size_t entry, int line) {
}
#elif defined(__aarch64__)
if (line == 0 || line == 3) {
printf("+--+--+--+---+-+--+------------------+--+-+-+-+--+---+-+\n");
printf("+--+--+--+---+-+---+--+------------------+--+-+-+-+--+---+-+\n");
}
if (line == 1) {
printf("| ?| ?|XN|PXN|C| ?| PFN |NG|A|S|P|NS|MAI|T|\n");
printf("| ?| ?|XN|PXN|C|DBM| ?| PFN |NG|A|S|P|NS|MAI|T|\n");
}
if (line == 2) {
printf("|");
Expand All @@ -1375,7 +1378,8 @@ ptedit_fnc void ptedit_print_entry_line(size_t entry, int line) {
PEDIT_PRINT_B(" %d", PTEDIT_B(entry, 54));
PEDIT_PRINT_B(" %d ", PTEDIT_B(entry, 53));
PEDIT_PRINT_B("%d", PTEDIT_B(entry, 52));
PEDIT_PRINT_B("%2d", (PTEDIT_B(entry, 51) << 3) | (PTEDIT_B(entry, 50) << 2) | (PTEDIT_B(entry, 49) << 1) | PTEDIT_B(entry, 48));
PEDIT_PRINT_B(" %d ", PTEDIT_B(entry, 51));
PEDIT_PRINT_B("%2d", (PTEDIT_B(entry, 50) << 2) | (PTEDIT_B(entry, 49) << 1) | PTEDIT_B(entry, 48));
printf(" %16p |", (void*)((entry >> 12) & ((1ull << 36) - 1)));
PEDIT_PRINT_B(" %d", PTEDIT_B(entry, 11));
PEDIT_PRINT_B("%d", PTEDIT_B(entry, 10));
Expand Down Expand Up @@ -1467,6 +1471,7 @@ ptedit_fnc int ptedit_init() {
ptedit_paging_definition.pmd_entries = 9;
ptedit_paging_definition.pt_entries = 9;
ptedit_paging_definition.page_offset = 12;
ptedit_paging_definition.pfn_offset = 0;
#elif defined(__aarch64__)
if(ptedit_get_pagesize() == 16384) {
ptedit_paging_definition.has_pgd = 1;
Expand All @@ -1480,7 +1485,7 @@ ptedit_fnc int ptedit_init() {
ptedit_paging_definition.pmd_entries = 11;
ptedit_paging_definition.pt_entries = 11;
ptedit_paging_definition.page_offset = 14;
ptedit_use_implementation(PTEDIT_IMPL_USER_PREAD); // M1 workaround
ptedit_paging_definition.pfn_offset = 2;
} else {
ptedit_paging_definition.has_pgd = 1;
ptedit_paging_definition.has_p4d = 0;
Expand All @@ -1493,6 +1498,7 @@ ptedit_fnc int ptedit_init() {
ptedit_paging_definition.pmd_entries = 9;
ptedit_paging_definition.pt_entries = 9;
ptedit_paging_definition.page_offset = 12;
ptedit_paging_definition.pfn_offset = 0;
}
#endif
return 0;
Expand Down Expand Up @@ -1564,14 +1570,14 @@ ptedit_fnc int ptedit_get_pagesize() {
ptedit_fnc void ptedit_read_physical_page(size_t pfn, char* buffer) {
#if defined(LINUX)
if (ptedit_umem > 0) {
if (pread(ptedit_umem, buffer, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {
if (pread(ptedit_umem, buffer, ptedit_pagesize, (pfn >> ptedit_paging_definition.pfn_offset) * ptedit_pagesize) == -1) {
return;
}
}
else {
ptedit_page_t page;
page.buffer = (unsigned char*)buffer;
page.pfn = pfn;
page.pfn = pfn >> ptedit_paging_definition.pfn_offset;
ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_READ_PAGE, (size_t)&page);
}
#else
Expand All @@ -1586,14 +1592,14 @@ ptedit_fnc void ptedit_read_physical_page(size_t pfn, char* buffer) {
ptedit_fnc void ptedit_write_physical_page(size_t pfn, char* content) {
#if defined(LINUX)
if (ptedit_umem > 0) {
if (pwrite(ptedit_umem, content, ptedit_pagesize, pfn * ptedit_pagesize) == -1) {
if (pwrite(ptedit_umem, content, ptedit_pagesize, (pfn >> ptedit_paging_definition.pfn_offset) * ptedit_pagesize) == -1) {
return;
}
}
else {
ptedit_page_t page;
page.buffer = (unsigned char*)content;
page.pfn = pfn;
page.pfn = pfn >> ptedit_paging_definition.pfn_offset;
ioctl(ptedit_fd, PTEDITOR_IOCTL_CMD_WRITE_PAGE, (size_t)&page);
}
#else
Expand Down
7 changes: 5 additions & 2 deletions test/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
all: tests
all: tests m1_tests

tests: tests.c utest.h ../ptedit_header.h
gcc -Os tests.c -std=gnu99 -o tests -fsanitize=address

m1: tests.c utest.h ../ptedit_header.h
gcc -Os m1_tests.c -std=gnu99 -o m1_tests -fsanitize=address

clean:
rm -f tests
rm -f tests m1_tests

Loading