Skip to content

Instantly share code, notes, and snippets.

@eddyb

eddyb/Kbuild Secret

Last active January 25, 2021 15:59
Show Gist options
  • Save eddyb/b888bb87988ca97ead9abcf96aa49e15 to your computer and use it in GitHub Desktop.
Save eddyb/b888bb87988ca97ead9abcf96aa49e15 to your computer and use it in GitHub Desktop.
derone (undo "permanent" read-only kernel protections)
#include <linux/module.h>
#include <linux/kallsyms.h>
#define MODULE_NAME "derone"
static int __init derone_init(void)
{
printk(KERN_INFO "derone_init\n");
typedef int set_memory_fn_t(u64, int);
set_memory_fn_t *set_memory_ro =
(set_memory_fn_t *)kallsyms_lookup_name("set_memory_ro");
set_memory_fn_t *set_memory_rw =
(set_memory_fn_t *)kallsyms_lookup_name("set_memory_rw");
printk(KERN_INFO "derone: set_memory_ro=0x%llx set_memory_rw=0x%llx\n",
(u64)set_memory_ro, (u64)set_memory_rw);
void *kaslr = (void *)set_memory_ro - SYSTEM_MAP_set_memory_ro;
_Atomic u64 *
x86_amd_ls_cfg_base_ptr = // kallsyms_lookup_name("x86_amd_ls_cfg_base");
kaslr + SYSTEM_MAP_x86_amd_ls_cfg_base;
_Atomic int *
kernel_set_to_readonly_ptr = // kallsyms_lookup_name("kernel_set_to_readonly");
kaslr + SYSTEM_MAP_kernel_set_to_readonly;
printk(KERN_INFO
"derone: x86_amd_ls_cfg_base addr=0x%llx value=0x%llx\n",
(u64)x86_amd_ls_cfg_base_ptr, *x86_amd_ls_cfg_base_ptr);
printk(KERN_INFO
"derone: kernel_set_to_readonly addr=0x%llx value=%d\n",
(u64)kernel_set_to_readonly_ptr, *kernel_set_to_readonly_ptr);
printk(KERN_INFO
"derone: attempting to unprotect x86_amd_ls_cfg_base\n");
*kernel_set_to_readonly_ptr = 0;
int result = set_memory_rw((u64)x86_amd_ls_cfg_base_ptr, 1);
*kernel_set_to_readonly_ptr = 1;
printk(KERN_INFO "derone: set_memory_rw(0x%llx, 1) = %d\n",
(u64)x86_amd_ls_cfg_base_ptr, result);
*x86_amd_ls_cfg_base_ptr |= 0x40000000000000;
printk(KERN_INFO "derone: set_memory_ro(0x%llx, 1) = %d\n",
(u64)x86_amd_ls_cfg_base_ptr,
set_memory_ro((u64)x86_amd_ls_cfg_base_ptr, 1));
printk(KERN_INFO
"derone: x86_amd_ls_cfg_base addr=0x%llx value=0x%llx\n",
(u64)x86_amd_ls_cfg_base_ptr, *x86_amd_ls_cfg_base_ptr);
printk(KERN_INFO "derone_init: done\n");
return 0;
}
static void __exit derone_cleanup(void)
{
printk(KERN_INFO "derone_cleanup\n");
}
module_init(derone_init);
module_exit(derone_cleanup);
MODULE_LICENSE("GPL");
SYSTEM_MAP ?= /run/booted-system/kernel-modules/System.map
CFLAGS_derone.o = \
-D SYSTEM_MAP_set_memory_ro=0x$(shell grep set_memory_ro $(SYSTEM_MAP) | sed 's/ .*//') \
-D SYSTEM_MAP_x86_amd_ls_cfg_base=0x$(shell grep x86_amd_ls_cfg_base $(SYSTEM_MAP) | sed 's/ .*//') \
-D SYSTEM_MAP_kernel_set_to_readonly=0x$(shell grep kernel_set_to_readonly $(SYSTEM_MAP) | sed 's/ .*//')
obj-m += derone.o
@eddyb
Copy link
Author

eddyb commented Sep 13, 2020

cd $(mktemp -d)
curl -LO https://gist.githubusercontent.com/eddyb/b888bb87988ca97ead9abcf96aa49e15/raw/derone.c
curl -LO https://gist.githubusercontent.com/eddyb/b888bb87988ca97ead9abcf96aa49e15/raw/Kbuild
nix build -f channel:nixos-unstable linux.dev -o linux-dev
make -C linux-dev/lib/modules/*/build M=$(pwd) modules
sudo insmod ./derone.ko
sudo rmmod derone

EDIT: DO NOT USE THIS, https://gist.github.com/glandium/01d54cefdb70561b5f6675e08f2990f2 is better.

@glandium
Copy link

Why are the kallsyms_lookup_name commented for x86_amd_ls_cfg_base and kernel_set_to_readonly? They do appear in /proc/kallsyms here, I'd expect kallsyms_lookup_name to work. As far as I can tell, it works here.

@glandium
Copy link

@eddyb
Copy link
Author

eddyb commented Sep 19, 2020

I didn't see your comments here, sorry. /proc/kallsyms doesn't contain global variables on my 5.4.49, maybe it's a NixOS thing?
Ah it seems to be CONFIG_KALLSYMS_ALL that's missing, and which would enable global variables as well:

$ zgrep KALLSYMS /proc/config.gz
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y
CONFIG_KALLSYMS_BASE_RELATIVE=y

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment