A Linux SVM hypervisor for emulating cpuid and sgdt/sidt results per-process by simply loading a Linux kernel module.
C
1
6 commits
updated Sep 21, 2026
Alcor is a Blue Pill-style SVM hypervisor for Linux, but unlike Blue Pill, it's a compatibility tool: it emulates the results of cpuid and gdtr/idtr reads for processors that don't natively support UMIP or CPUID faulting.
After loading, the module exposes a misc device at /dev/alcor_ctrl, which allows every process to change the cpuid and descriptor view of itself or, with CAP_SYS_PTRACE, any other process. See Usage for the exposed API.
This is extremely experimental, but it is completely stable on everything I could test it on; however, I still strongly suggest saving your existing work before attempting to load this for the first time.
This is also the first time I've written a kernel module, so security and stability are not guaranteed.
While I really wanted to list the exact tested hardware in this section, unfortunately I can't offer anything more than "It works on my machine" at the moment. If you encounter a crash, please create an issue with the oops message or anything else you think could be useful to help diagnose it.
Ensure that you have an AMD machine with SVM support, and that SVM is enabled in the BIOS/UEFI.
grep -m1 -o 'svm' /proc/cpuinfo # should print `svm`
Then make sure the kernel headers and GCC are installed. Recent kernel versions are supported (tested on 6.12-7.2). If you encounter a compile error, please open an issue.
For example, under Arch Linux (assuming you're using linux for the kernel):
pacman -S base-devel linux-headers
Ensure lockdown/Secure Boot config allows loading modules, then run:
make load
Note for doas users: make load ends up running sudo insmod alcor.ko, which requires sudo. Use a shim, edit it out, or just run insmod manually. The same also applies to make unload.
You can then check dmesg to see if all cores are virtualized properly.
The module is expected to handle rmmod normally. Every core is devirtualized upon unloading, and the kernel resumes in host mode.
To unload using the provided Makefile, simply do:
make unload
See api.h for the full exposed API. Here's an example:
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include "api.h"
struct ac_hook_data hook = { 0 };
// spoof the CPUID brand string (leaves 0x80000002-0x80000004)
const char *brand = "Navi (R) 2nd model 69420 @ 69420GHz ";
for (int i = 0; i < 3; i++) {
// You can add up to 16 overrides
struct ac_cpuid_entry *e = &hook.cpuid_overrides[hook.cpuid_count++];
e->flags = AC_CPUID_PRESET_MASK;
e->leaf = 0x80000002 + i;
memcpy(e->regs, brand + i * 16, 16);
}
// spoof sgdt/sidt results
hook.segment_flags = AC_GDTR_HOOK_MASK | AC_IDTR_HOOK_MASK;
hook.segments_overrides[AC_GDTR_HOOK] = (struct ac_desc_ptr){ .address = 0x6969, .size = 0x420 };
hook.segments_overrides[AC_IDTR_HOOK] = (struct ac_desc_ptr){ .address = 0x420, .size = 0x6969 };
hook.log_cpuid = true; // log every intercepted cpuid to dmesg
int fd = open("/dev/alcor_ctrl", O_RDWR);
hook.pid = 0; // 0 = calling process, or any pid if you have CAP_SYS_PTRACE
ioctl(fd, AC_IOCTL_HOOK, &hook); // takes effect immediately
int pid = 0;
// remove the hooks again: UNHOOK only takes a pid
ioctl(fd, AC_IOCTL_UNHOOK, &pid);
gdtr and idtr reads are currently supported.lsmod, and rmmod should cleanly devirtualize.cpuid takes a vmexit (measurable latency), and the hypervisor bit is set on leaf 1. A determined program can detect it. The goal is to emulate cpuid and descriptor reads. Not stealth.Is this a rootkit? No. Nothing is hidden from the kernel. Only unprivileged code is affected by the emulation. See What This Is Not.
Can software detect it?
Yes. Local software can easily check for the module or the existence of /dev/alcor_ctrl.
Does it work under KVM? Yes, but with strong emphasis on the word under. You can use this in KVM guests with nested SVM enabled. There's also support for forwarding CPL0 hypercalls to upstream KVM; however, you cannot run KVM guests while this module is loaded.
Why does it disable UMIP? Because, while loaded, it replaces UMIP with a softer version that returns a constant value for every read by default. This also lets the hypervisor control the emulated values on a per-process basis when an override is active.
Is this vibe-coded? No. LLMs were involved in the initial research phase; however most of the code was written by hand over the course of a week.
GPL-2.0 or later
6 commits
C
94.5%
Assembly
4.4%
Makefile
1.1%
A Linux SVM hypervisor for emulating cpuid and sgdt/sidt results per-process by simply loading a Linux kernel module.
C
1
6 commits
updated Sep 21, 2026
Alcor is a Blue Pill-style SVM hypervisor for Linux, but unlike Blue Pill, it's a compatibility tool: it emulates the results of cpuid and gdtr/idtr reads for processors that don't natively support UMIP or CPUID faulting.
After loading, the module exposes a misc device at /dev/alcor_ctrl, which allows every process to change the cpuid and descriptor view of itself or, with CAP_SYS_PTRACE, any other process. See Usage for the exposed API.
This is extremely experimental, but it is completely stable on everything I could test it on; however, I still strongly suggest saving your existing work before attempting to load this for the first time.
This is also the first time I've written a kernel module, so security and stability are not guaranteed.
While I really wanted to list the exact tested hardware in this section, unfortunately I can't offer anything more than "It works on my machine" at the moment. If you encounter a crash, please create an issue with the oops message or anything else you think could be useful to help diagnose it.
Ensure that you have an AMD machine with SVM support, and that SVM is enabled in the BIOS/UEFI.
grep -m1 -o 'svm' /proc/cpuinfo # should print `svm`
Then make sure the kernel headers and GCC are installed. Recent kernel versions are supported (tested on 6.12-7.2). If you encounter a compile error, please open an issue.
For example, under Arch Linux (assuming you're using linux for the kernel):
pacman -S base-devel linux-headers
Ensure lockdown/Secure Boot config allows loading modules, then run:
make load
Note for doas users: make load ends up running sudo insmod alcor.ko, which requires sudo. Use a shim, edit it out, or just run insmod manually. The same also applies to make unload.
You can then check dmesg to see if all cores are virtualized properly.
The module is expected to handle rmmod normally. Every core is devirtualized upon unloading, and the kernel resumes in host mode.
To unload using the provided Makefile, simply do:
make unload
See api.h for the full exposed API. Here's an example:
#include <fcntl.h>
#include <string.h>
#include <sys/ioctl.h>
#include "api.h"
struct ac_hook_data hook = { 0 };
// spoof the CPUID brand string (leaves 0x80000002-0x80000004)
const char *brand = "Navi (R) 2nd model 69420 @ 69420GHz ";
for (int i = 0; i < 3; i++) {
// You can add up to 16 overrides
struct ac_cpuid_entry *e = &hook.cpuid_overrides[hook.cpuid_count++];
e->flags = AC_CPUID_PRESET_MASK;
e->leaf = 0x80000002 + i;
memcpy(e->regs, brand + i * 16, 16);
}
// spoof sgdt/sidt results
hook.segment_flags = AC_GDTR_HOOK_MASK | AC_IDTR_HOOK_MASK;
hook.segments_overrides[AC_GDTR_HOOK] = (struct ac_desc_ptr){ .address = 0x6969, .size = 0x420 };
hook.segments_overrides[AC_IDTR_HOOK] = (struct ac_desc_ptr){ .address = 0x420, .size = 0x6969 };
hook.log_cpuid = true; // log every intercepted cpuid to dmesg
int fd = open("/dev/alcor_ctrl", O_RDWR);
hook.pid = 0; // 0 = calling process, or any pid if you have CAP_SYS_PTRACE
ioctl(fd, AC_IOCTL_HOOK, &hook); // takes effect immediately
int pid = 0;
// remove the hooks again: UNHOOK only takes a pid
ioctl(fd, AC_IOCTL_UNHOOK, &pid);
gdtr and idtr reads are currently supported.lsmod, and rmmod should cleanly devirtualize.cpuid takes a vmexit (measurable latency), and the hypervisor bit is set on leaf 1. A determined program can detect it. The goal is to emulate cpuid and descriptor reads. Not stealth.Is this a rootkit? No. Nothing is hidden from the kernel. Only unprivileged code is affected by the emulation. See What This Is Not.
Can software detect it?
Yes. Local software can easily check for the module or the existence of /dev/alcor_ctrl.
Does it work under KVM? Yes, but with strong emphasis on the word under. You can use this in KVM guests with nested SVM enabled. There's also support for forwarding CPL0 hypercalls to upstream KVM; however, you cannot run KVM guests while this module is loaded.
Why does it disable UMIP? Because, while loaded, it replaces UMIP with a softer version that returns a constant value for every read by default. This also lets the hypervisor control the emulated values on a per-process basis when an override is active.
Is this vibe-coded? No. LLMs were involved in the initial research phase; however most of the code was written by hand over the course of a week.
GPL-2.0 or later
6 commits
C
94.5%
Assembly
4.4%
Makefile
1.1%