Okay, so Today I’ll need the CR3 value given a PID. The Linux kernel does not give this information out to the userspace, so I’ll be building my own module to take care of this. The code is available on my Gitlab.
Two awesome references I’ll be using for this task:
- Building kernel modules
- Getting CR3 given PID (also part of a module)
- Using sysfs kernel objects to communicate with the module
Making the basic module
We need to the actual module that is loadable into the kernel. This can be done by using the tutorial from the first reference. The main module source code needs to have the proper headers (to call proper module MACROs), the proper calls to the macros (description, author, license), and finally actually define which functions of the module are the entry and exit points.
#include
#include
#include
MODULE_DESCRIPTION("Kernel module to translate given PID to CR3 physical address");
MODULE_AUTHOR("Chang Hyun Park");
MODULE_LICENSE("GPL");
static int pid2cr3_init(void)
{
printk("%s\n", __func__);
return 0;
}
static void pid2cr3_exit(void)
{
printk("%s\n", __func__);
}
module_init(pid2cr3_init);
module_exit(pid2cr3_exit);
The Makefile and the Kbuild files are identical to the first reference, except the filename of the code above (pid2cr3.c, add the object as pid2cr3.o).
The full code can be found at Gitlab here
Actually doing the intended work
Now, given a PID we want to retrieve the CR3 Value! There are a few ways to pass on the PID value to the module.
- Register the module to listen on a system call [here]
- Pass on parameters when loading the module (and dynamically change the parameter at runtime) [here]
- Open a pseudo-file to communicate with the module (sysfs, procfs).
We take the final approach, where we create a new sysfs directory and file which we program to act differently for reads and writes.
For a write to the file, we receive the PID from the userspace, and for the write, we return the CR3 for the priorly received PID.
The code is available here.
That’s it!