CVE Candidate: KDB Format String Vulnerability via PROMPT Environment Variable

File

kernel/debug/kdb/kdb_main.c, line 1271

Severity

Critical — Kernel arbitrary memory write (format string attack with %n)

Vulnerability

// kdb_local(), line 1271
snprintf(kdb_prompt_str, CMD_BUFLEN, kdbgetenv("PROMPT"),
         raw_smp_processor_id());

The value of the PROMPT environment variable is passed directly as the format string argument to snprintf. An attacker with KDB console access can write a malicious format string into PROMPT via the set command, which is then evaluated as a format string every time the prompt is displayed.

Root Cause

kdbgetenv("PROMPT") returns a user-controlled string. Using it as the second argument to snprintf — the format string position — turns any %-specifiers embedded in PROMPT into active format directives, not literal text.

The only argument passed after the format string is raw_smp_processor_id() (an integer). The snprintf call therefore has a fixed, narrow argument list while the format string is fully attacker-controlled.

Attack Scenario

  1. Attacker reaches the KDB prompt (physical console, crash, or breakpoint).
  2. Issues: set PROMPT %65535d%18$n
    • %65535d consumes the one integer argument and pads output to 65535 characters.
    • %18$n writes the character count (an attacker-chosen value) to the address held in the 18th argument slot on the kernel stack, which the attacker can tune by adjusting the format string.
  3. On the very next prompt redraw, snprintf executes the format string with kernel privileges, writing an arbitrary 4-byte value to an arbitrary kernel address.
  4. This can overwrite a function pointer, security hook, or modprobe_path to achieve arbitrary code execution at ring 0.

%s and %p specifiers can additionally leak kernel stack/heap addresses, defeating KASLR before the write step.

Impact

Property Detail
Primitives Arbitrary kernel memory read (%s/%p) and write (%n)
Privilege required KDB console access (physical or via kgdb)
Effect Full kernel compromise / privilege escalation to ring 0
KASLR bypass Yes — stack address leak via %p

Proof-of-Concept (Outline)

# Step 1 — leak a kernel stack address
set PROMPT %p%p%p%p%p%p%p%p
# (read address from next prompt display)

# Step 2 — compute target offset (e.g., modprobe_path or security hook)

# Step 3 — write lower 16 bits of target with %<val>d%<offset>$hn
set PROMPT %<lo_val>d%<offset>$hn
# Step 4 — write upper 16 bits similarly (two-write technique)

Never use user-controlled data as a format string. Pass the PROMPT value as a %s argument:

// SAFE: PROMPT value treated as data, not as a format string
snprintf(kdb_prompt_str, CMD_BUFLEN, "%s",
         kdbgetenv("PROMPT") ?: "kdb> ");

If CPU-number substitution is still required, implement it with an explicit parser that only recognises the %d specifier for the CPU number, rejecting all other percent sequences.

References

  • CWE-134: Use of Externally-Controlled Format String
  • The comment on line 1270 (/* PROMPT can only be set if we have MEM_READ permission. */) acknowledges the sensitivity of this path but does not prevent format string injection.