How do I force an IBT trap in a demo kernel module?

From: Preble, Adam C
Date: Tue May 23 2023 - 15:29:11 EST


I am debugging why a kernel module of ours triggers the IBT (Indirect Branch Tracking) trap, and while doing that, I was trying to write a standalone demo that would forcefully trigger it on purpose. This has turned out to be much more difficult than I thought! What can I do to get a module to generate an indirect branch without an endbr64? Creating the indirect branch itself doesn't appear to be hard:

1. Set up a function call
2. Assign it to a function pointer
3. Call the function pointer
4. ...maybe add a compiler flag so it doesn't optimize the call to a direct branch.

I am primarily building in a Debian environment with gcc (Debian 10.2.1-6) 10.2.1 20210110. By default, the branch does get optimized away. I had to set the -mforce-indirect-call flag. The endbr64 instruction would still emit so I added a function attribute to suppress it:


__attribute__((nocf_check))
static void indirect_jump_to_me(void)
{
pr_info("Reached indirect jump\n");
}


I think that took care of my code generation, but objtool is offended by what I am doing:


/root/module/ibt_test.o: warning: objtool: init_ibt_test_module+0x11: relocation to !ENDBR: indirect_jump_to_me+0x0
MODPOST /root/module/Module.symvers
ERROR: modpost: "__x86_indirect_thunk_nt_rax" [/root/module/ibt_test.ko] undefined!
make[4]: *** [/usr/src/my-header-6.3.0/scripts/Makefile.modpost:136: /root/module/Module.symvers] Error 1


So what do I have to do to tell objtool to allow to me deliberately shoot myself in the foot here?