seq_printf forwards __va_list into ksnprintf variadic parameter instead of using kvsnprintf
Summary
seq_printf() builds __va_list ap from variadic args then calls ksnprintf(m->buf m->size f ap) (linux_printf.c:37). ksnprintf is declared __printflike(3 4) variadic function. Passing __va_list to ... parameter does NOT forward original arguments: on x86-64 SysV __va_list is array of one struct decays to pointer-to-struct consumed by ksnprintf as FIRST variadic argument. Correct API is kvsnprintf(char* size_t const char* __va_list). ksnprintf own __va_start sees pointer-to-va_list struct as variadic slot 0 (lands in RCX after buf/size/fmt consume RDI/RSI/RDX). __va_arg calls read: 1st conversion pointer-to-va_list struct reinterpreted as T (char*/void*/int/long) 2nd+ conversions stale register/stack contents from seq_printf frame. None of caller actual variadic arguments ever reach ksnprintf. Fix is one token: kvsnprintf. Bug currently LATENT zero runtime reachability: CONFIG_DEBUG_FS undefined so all debugfs show callbacks compiled out under #ifdef CONFIG_DEBUG_FS. Only compiled-in callers gen8/gen6_dump_ppgtt (debug_dump function pointer never invoked) and drm_dp_downstream_debug (EXPORT_SYMBOL zero in-tree callers). If enabled: %p prints kernel-stack address (KASLR-defeating) %s walks bytes at &ap. No in-tree format literal attacker-controlled. Also seq_printf always writes from buf[0] discards ksnprintf return no append/cursor tracking (functional bug not memory-safety).
No comments yet.