Kernel panic with `Missing ENDBR`

Solution Verified - Updated -

Environment

  • Red Hat Enterprise Linux 10
  • Intel x86 CPUs

Issue

Red Hat Enterprise Linux experienced a kernel panic and the serial console showed messages like the following;

[Tue Sep 16 11:21:41 UTC 2025] Missing ENDBR: kallsyms_lookup_name+0x4/0xd0
[Tue Sep 16 11:21:41 UTC 2025] ------------[ cut here ]------------
[Tue Sep 16 11:21:41 UTC 2025] kernel BUG at arch/x86/kernel/cet.c:102!

Resolution

Please engage the third-party module vendor or ebpf application vendor to further troubleshoot this matter.

Workaround

Set ibt=warn in the kernel parameters to show warning messages only and continue tracking. Or, set ibt=off to completely disable it;

Root Cause

Summary

A third-party module or ebpf program attempted an indirect function call to a location that does not contain the endbr instruction. This triggered the Indirect Branch Tracking (IBT) security feature of the CPU and kernel resulting in a kernel panic.

Details

Background

Function calls within programs can be direct or indirect. A direct function call executes the function associated with the name while an indirect function call will instead use a provided address to execute at where this address is typically referred to as a function pointer. Indirect function calls are useful in many ways, for example, when the function called to do some action can vary based on some additional information. System Calls (syscalls), for example, all call the same function directly with a syscall number. The number is used to identify which syscall to execute and which function pointer to use to execute. For example, the function pointer for sys_open will be different for sys_read.

Executing function pointers is found throughout most any software, operating system, and firmware. Malicious code could derive a calculated function pointer to execute arbitrary code. To greatly reduce this problem surface area, Intel introduced Indirect Branch Tracking (IBT) as part of its Control Flow Enforcement (CET). The general premise is to guarantee the address you start executing from a function pointer is safe to reach at that specific point.

Implementation

Intel introduced the endbr assembly instruction (or more precisely endbr32 and endbr64). The instruction just executes as a no-op, which more or less means an instruction to execute nothing for a cpu cycle. Indirect branches are expected to land on this endbr instruction. If so, execution continues as expected. If not, then the CPU throws a control-protection (CP) exception.

The Linux kernel handles the control-protection exception by first omitting an error Missing ENDBR: <function location>;

arch/x86/kernel/cet.c
 84 static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
 85 {    
...
 96     pr_err("Missing ENDBR: %pS\n", (void *)instruction_pointer(regs));
 97     if (!ibt_fatal) {
 98         printk(KERN_DEFAULT CUT_HERE);
 99         __warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
100         return;
101     }
102     BUG();
103 }    

For example,

Missing ENDBR: kallsyms_lookup_name+0x4/0xd0

The above indicates the caller attempted to start executing at kallsyms_lookup_name+0x4 using a function pointer and indirect function calling. However, that instruction is not endbr64;

crash> dis kallsyms_lookup_name | head -3
0xffffffffaaffe380 <kallsyms_lookup_name>:  nopw   (%rax)
0xffffffffaaffe384 <kallsyms_lookup_name+0x4>:  nopl   0x0(%rax,%rax,1)     <---
0xffffffffaaffe389 <kallsyms_lookup_name+0x9>:  push   %rbx

That function pointer points to a nopl instruction instead. As such, the cpu threw the control-protection exception resulting in a kernel panic.

In contrast;

crash> dis -r ffffffffc1701015 | tail -5
0xffffffffc170100e <_MODULE_INIT_TEXT_START_traps+0xe>: nop
0xffffffffc170100f <_MODULE_INIT_TEXT_START_traps+0xf>: nop
0xffffffffc1701010 <_MODULE_INIT_TEXT_START_traps+0x10>:    endbr64          <---
0xffffffffc1701014 <_MODULE_INIT_TEXT_START_traps+0x14>:    nopl   0x0(%rax,%rax,1)
0xffffffffc1701019 <_MODULE_INIT_TEXT_START_traps+0x19>:    push   %rbp

An indirect function call landing at 0xffffffffc1701010 would succeed because such a call would land on endbr64. The assembly instruction indicates there is an expectation to call to that location elsewhere and doing so is safe.

Diagnostic Steps

Pre-requisites

  1. Deploy kdump in order to collect a vmcore:

    • A vmcore is a snapshot of system memory at the time of its collection either via a kernel crash or virtual machine snapshot/memory dump. This is conceptually similar to an application core but for the entire system.
    • Vmcore analysis is required to determine if the system is affected by the aforementioned issue, and requires a vmcore successfully captured at the time of the issue.
    • If the kexec-tools package is absent or the kdump service is inactive, please reference the following article to install, enable, start, and configure kdump:
    • How to troubleshoot kernel crashes, hangs, or reboots with kdump on Red Hat Enterprise Linux
  2. Prepare a crash environment for vmcore analysis:

Vmcore Analysis

  1. Check the panic location to confirm if it panicked at arch/x86/kernel/cet.c:102

    crash> sys
          KERNEL: /filpath/usr/lib/debug/lib/modules/6.12.0-55.32.1.el10_0.x86_64/vmlinux  [TAINTED]
        DUMPFILE: /filepath/vmcore  [PARTIAL DUMP]
            CPUS: 480
            DATE: Tue Sep 16 11:21:37 UTC 2025
          UPTIME: 4 days, 17:40:03
    LOAD AVERAGE: 1.17, 1.04, 1.01
          TASKS: 5253
        NODENAME: localhost
        RELEASE: 6.12.0-55.32.1.el10_0.x86_64
        VERSION: #1 SMP PREEMPT_DYNAMIC Tue Sep  9 02:57:23 EDT 2025
        MACHINE: x86_64  (1900 Mhz)
          MEMORY: 2047.5 GB
          PANIC: "kernel BUG at arch/x86/kernel/cet.c:102!"            <---
    
  2. Check the kernel ring buffer with dmesg to see if the noted log line is observed;

    crash> dmesg -T 
    ...
    [Thu Sep 11 20:50:58 UTC 2025] XFS (dm-5): Ending clean mount
    [Tue Sep 16 11:21:41 UTC 2025] traps: loading out-of-tree module taints kernel.
    [Tue Sep 16 11:21:41 UTC 2025] traps: module verification failed: signature and/or required key missing - tainting kernel
    [Tue Sep 16 11:21:41 UTC 2025] TRAPS: --- starting ---
    [Tue Sep 16 11:21:41 UTC 2025] Missing ENDBR: kallsyms_lookup_name+0x4/0xd0        <---
    [Tue Sep 16 11:21:41 UTC 2025] ------------[ cut here ]------------
    [Tue Sep 16 11:21:41 UTC 2025] kernel BUG at arch/x86/kernel/cet.c:102!
    [Tue Sep 16 11:21:41 UTC 2025] Oops: invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
    ...
    

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.

Comments