From 046bc25b6b06e3ec059a3c643ea7e360a967bd1d Mon Sep 17 00:00:00 2001 From: Ciro Santilli Date: Thu, 5 Jul 2018 03:42:26 +0100 Subject: [PATCH] virt_to_phys: fix %p vs %px Move doc to README --- README.adoc | 52 ++++++++++++++++++++++++++++++++++- kernel_module/README.adoc | 1 - kernel_module/virt_to_phys.c | 53 ++++++++++++++---------------------- 3 files changed, 71 insertions(+), 35 deletions(-) diff --git a/README.adoc b/README.adoc index b07b148..92927d3 100644 --- a/README.adoc +++ b/README.adoc @@ -4127,7 +4127,9 @@ The module also shows which handlers are registered for each IRQ, as we have obs When in text mode, we can also observe interrupt line 4 with handler `ttyS0` increase continuously as IO goes through the UART. -=== Linux kernel utility functions +=== Kernel utility functions + +https://github.com/torvalds/linux/blob/v4.17/Documentation/core-api/kernel-api.rst ==== kstrto @@ -4151,6 +4153,54 @@ Sources: Bibliography: https://stackoverflow.com/questions/6139493/how-convert-char-to-int-in-linux-kernel/49811658#49811658 +==== virt_to_phys + +Convert a virtual address to physical: + +.... +insmod /virt_to_phys.ko +cat /sys/kernel/debug/lkmc_virt_to_phys +.... + +Source: link:kernel_module/virt_to_phys.c[] + +Sample output: + +.... +*kmalloc_ptr = 0x12345678 +kmalloc_ptr = ffff88000e169ae8 +virt_to_phys(kmalloc_ptr) = 0xe169ae8 +static_var = 0x12345678 +&static_var = ffffffffc0002308 +virt_to_phys(&static_var) = 0x40002308 +.... + +We can confirm that the `kmalloc_ptr` translation worked with: + +.... +./qemumonitor 'xp 0xe169ae8' +.... + +which reads four bytes from a given physical address, and gives the expected: + +.... +000000000e169ae8: 0x12345678 +.... + +TODO it only works for kmalloc however, for the static variable: + +.... +./qemumonitor 'xp 0x40002308' +.... + +it gave a wrong value of `00000000`. + +Bibliography: + +* https://stackoverflow.com/questions/5748492/is-there-any-api-for-determining-the-physical-address-from-virtual-address-in-li/45128487#45128487 +* https://stackoverflow.com/questions/39134990/mmap-of-dev-mem-fails-with-invalid-argument-for-virt-to-phys-address-but-addre/45127582#45127582 +* https://stackoverflow.com/questions/43325205/can-we-use-virt-to-phys-for-user-space-memory-in-kernel-module + === Linux kernel tracing Good overviews: diff --git a/kernel_module/README.adoc b/kernel_module/README.adoc index d2cb969..078176e 100644 --- a/kernel_module/README.adoc +++ b/kernel_module/README.adoc @@ -10,7 +10,6 @@ Our kernel modules! .. link:work_from_work.c[] .. link:workqueue_cheat.c[] . Misc -.. link:virt_to_phys.c[] .. link:netlink.c[] . Hardening .. link:strlen_overflow.c[] diff --git a/kernel_module/virt_to_phys.c b/kernel_module/virt_to_phys.c index 2cd5438..df194c4 100644 --- a/kernel_module/virt_to_phys.c +++ b/kernel_module/virt_to_phys.c @@ -1,16 +1,4 @@ -/* -Also try on QEMU monitor: - - xp 0x - -Only works for kmalloc. - -static inline phys_addr_t virt_to_phys(volatile void *address) - -- https://stackoverflow.com/questions/5748492/is-there-any-api-for-determining-the-physical-address-from-virtual-address-in-li -- https://stackoverflow.com/questions/43325205/can-we-use-virt-to-phys-for-user-space-memory-in-kernel-module -- https://stackoverflow.com/questions/39134990/mmap-of-dev-mem-fails-with-invalid-argument-but-address-is-page-aligned -*/ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#virt_to_phys */ #include /* virt_to_phys */ #include @@ -21,26 +9,26 @@ static inline phys_addr_t virt_to_phys(volatile void *address) #include /* single_open, single_release */ #include /* kmalloc, kfree */ -static volatile u32 *k; -static volatile u32 i; +static volatile u32 *kmalloc_ptr; +static volatile u32 static_var; static struct dentry *debugfs_file; static int show(struct seq_file *m, void *v) { seq_printf(m, - "k 0x%llx\n" - "addr_k %p\n" - "virt_to_phys_k 0x%llx\n" - "i 0x%llx\n" - "addr_i %p\n" - "virt_to_phys_i 0x%llx\n", - (unsigned long long)*k, - k, - (unsigned long long)virt_to_phys((void *)k), - (unsigned long long)i, - &i, - (unsigned long long)virt_to_phys((void *)&i) + "*kmalloc_ptr = 0x%llx\n" + "kmalloc_ptr = %px\n" + "virt_to_phys(kmalloc_ptr) = 0x%llx\n" + "static_var = 0x%llx\n" + "&static_var = %px\n" + "virt_to_phys(&static_var) = 0x%llx\n", + (unsigned long long)*kmalloc_ptr, + kmalloc_ptr, + (unsigned long long)virt_to_phys((void *)kmalloc_ptr), + (unsigned long long)static_var, + &static_var, + (unsigned long long)virt_to_phys((void *)&static_var) ); return 0; } @@ -60,18 +48,17 @@ static const struct file_operations fops = { static int myinit(void) { - k = kmalloc(sizeof(k), GFP_KERNEL); - *k = 0x12345678; - i = 0x12345678; - debugfs_file = debugfs_create_file( - "lkmc_virt_to_phys", S_IRUSR, NULL, NULL, &fops); + kmalloc_ptr = kmalloc(sizeof(kmalloc_ptr), GFP_KERNEL); + *kmalloc_ptr = 0x12345678; + static_var = 0x12345678; + debugfs_file = debugfs_create_file("lkmc_virt_to_phys", S_IRUSR, NULL, NULL, &fops); return 0; } static void myexit(void) { debugfs_remove(debugfs_file); - kfree((void *)k); + kfree((void *)kmalloc_ptr); } module_init(myinit)