mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 10:15:57 +01:00
move doc of userland physical address tests to README
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
https://github.com/cirosantilli/linux-kernel-module-cheat#rootfs_overlay
|
||||
|
||||
. link:sched_getaffinity.c[]
|
||||
. link:usermem.c[]
|
||||
.. link:pagemap_dump.c[]
|
||||
. link:uio_read.c[]
|
||||
|
||||
@@ -1,29 +1,4 @@
|
||||
/*
|
||||
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
|
||||
- https://stackoverflow.com/questions/5748492/is-there-any-api-for-determining-the-physical-address-from-virtual-address-in-li
|
||||
- https://stackoverflow.com/questions/6284810/proc-pid-pagemaps-and-proc-pid-maps-linux/45500208#45500208
|
||||
|
||||
Dump the page map of a given process PID.
|
||||
|
||||
Data sources: /proc/PIC/{map,pagemap}
|
||||
|
||||
This program works in two steps:
|
||||
|
||||
- parse the human readable lines lines from `/proc/<pid>/maps`. This files contains lines of form:
|
||||
|
||||
7ffff7b6d000-7ffff7bdd000 r-xp 00000000 fe:00 658 /lib/libuClibc-1.0.22.so
|
||||
|
||||
which gives us:
|
||||
|
||||
- `7f8af99f8000-7f8af99ff000`: a virtual address range that belong to the process, possibly containing multiple pages.
|
||||
- `/lib/libuClibc-1.0.22.so` the name of the library that owns that memory.
|
||||
|
||||
- loop over each page of each address range, and ask `/proc/<pid>/pagemap` for more information about that page, including the physical address.
|
||||
*/
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#pagemap_dump-out */
|
||||
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <errno.h>
|
||||
@@ -63,7 +38,7 @@ int main(int argc, char **argv)
|
||||
perror("open pagemap");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("addr pfn soft-dirty file/shared swapped present library\n");
|
||||
printf("vaddr pfn soft-dirty file/shared swapped present library\n");
|
||||
for (;;) {
|
||||
ssize_t length = read(maps_fd, buffer + offset, sizeof buffer - offset);
|
||||
if (length <= 0) break;
|
||||
@@ -116,11 +91,11 @@ int main(int argc, char **argv)
|
||||
/* Get info about all pages in this page range with pagemap. */
|
||||
{
|
||||
PagemapEntry entry;
|
||||
for (uintptr_t addr = low; addr < high; addr += sysconf(_SC_PAGE_SIZE)) {
|
||||
for (uintptr_t vaddr = low; vaddr < high; vaddr += sysconf(_SC_PAGE_SIZE)) {
|
||||
/* TODO always fails for the last page (vsyscall), why? pread returns 0. */
|
||||
if (!pagemap_get_entry(&entry, pagemap_fd, addr)) {
|
||||
if (!pagemap_get_entry(&entry, pagemap_fd, vaddr)) {
|
||||
printf("%jx %jx %u %u %u %u %s\n",
|
||||
(uintmax_t)addr,
|
||||
(uintmax_t)vaddr,
|
||||
(uintmax_t)entry.pfn,
|
||||
entry.soft_dirty,
|
||||
entry.file_page,
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
Only tested in x86_64.
|
||||
|
||||
Provide an allocated userland memory for us to test out kernel memory APIs, including:
|
||||
|
||||
- /proc/pid/maps
|
||||
- /proc/pid/pagemap. See also: https://stackoverflow.com/questions/17021214/decode-proc-pid-pagemap-entry/45126141#45126141
|
||||
- /dev/mem
|
||||
|
||||
Usage:
|
||||
|
||||
/usermem.out &
|
||||
|
||||
Outputs the virtual address and pid, e.g.:
|
||||
|
||||
vaddr 0x600800
|
||||
pid 110
|
||||
|
||||
Translate the virtual address to physical for the given PID:
|
||||
|
||||
/virt_to_phys_user.out 110 0x600800
|
||||
|
||||
Sample output physical address:
|
||||
|
||||
0x7c7b800
|
||||
|
||||
## QEMU monitor xp
|
||||
|
||||
Examine the physical memory from the QEMU monitor: on host:
|
||||
|
||||
./qemumonitor
|
||||
xp 0x7c7b800
|
||||
|
||||
Output:
|
||||
|
||||
0000000007c7b800: 0x12345678
|
||||
|
||||
Yes!!! We read the correct value from the physical address.
|
||||
|
||||
## /dev/mem
|
||||
|
||||
Firt up, this requires:
|
||||
|
||||
- CONFIG_STRICT_DEVMEM is not set.
|
||||
- nopat on kernel parameters
|
||||
|
||||
see: https://stackoverflow.com/questions/11891979/how-to-access-mmaped-dev-mem-without-crashing-the-linux-kernel
|
||||
|
||||
Then:
|
||||
|
||||
devmem 0x7c7b800
|
||||
|
||||
Possible output:
|
||||
|
||||
Memory mapped at address 0x7ff7dbe01000.
|
||||
Value at address 0X7C7B800 (0x7ff7dbe01800): 0x12345678
|
||||
|
||||
where 0x7ff7dbe01000 is a new virtual address that was mapped
|
||||
to our physical address and given to the process that mapped /dev/mem.
|
||||
|
||||
And finally, let's change the value!
|
||||
|
||||
devmem 0x7c7b800 w 0x9abcdef0
|
||||
|
||||
After one second, we see on the screen:
|
||||
|
||||
i 9abcdef0
|
||||
[1]+ Done /usermem.out
|
||||
|
||||
so the while loop was exited!
|
||||
*/
|
||||
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
enum { I0 = 0x12345678 };
|
||||
|
||||
static volatile uint32_t i = I0;
|
||||
|
||||
int main(void) {
|
||||
printf("vaddr %p\n", (void *)&i);
|
||||
printf("pid %ju\n", (uintmax_t)getpid());
|
||||
while (i == I0) {
|
||||
sleep(1);
|
||||
}
|
||||
printf("i %jx\n", (uintmax_t)i);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
21
kernel_module/user/virt_to_phys_test.c
Normal file
21
kernel_module/user/virt_to_phys_test.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-physical-address-experiments */
|
||||
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
enum { I0 = 0x12345678 };
|
||||
|
||||
static volatile uint32_t i = I0;
|
||||
|
||||
int main(void) {
|
||||
printf("vaddr %p\n", (void *)&i);
|
||||
printf("pid %ju\n", (uintmax_t)getpid());
|
||||
while (i == I0) {
|
||||
sleep(1);
|
||||
}
|
||||
printf("i %jx\n", (uintmax_t)i);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -1,10 +1,4 @@
|
||||
/*
|
||||
Convert a virtual address to physical for a given process PID using /proc/PID/pagemap.
|
||||
|
||||
https://stackoverflow.com/questions/5748492/is-there-any-api-for-determining-the-physical-address-from-virtual-address-in-li/45128487#45128487
|
||||
|
||||
Test this out with usermem.c.
|
||||
*/
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-physical-address-experiments */
|
||||
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <stdio.h> /* printf */
|
||||
|
||||
Reference in New Issue
Block a user