[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <15D39DFE-C110-442E-BF34-A850680767BE@oracle.com>
Date: Thu, 21 Aug 2025 18:09:08 +0000
From: Qing Zhao <qing.zhao@...cle.com>
To: Peter Zijlstra <peterz@...radead.org>
CC: Richard Biener <rguenther@...e.de>,
Andrew Pinski
<andrew.pinski@....qualcomm.com>,
Kees Cook <kees@...nel.org>,
"gcc-patches@....gnu.org" <gcc-patches@....gnu.org>,
Joseph Myers
<josmyers@...hat.com>, Jan Hubicka <hubicka@....cz>,
Richard Earnshaw
<richard.earnshaw@....com>,
Richard Sandiford <richard.sandiford@....com>,
Marcus Shawcroft <marcus.shawcroft@....com>,
Kyrylo Tkachov
<kyrylo.tkachov@....com>,
Kito Cheng <kito.cheng@...il.com>,
Palmer Dabbelt
<palmer@...belt.com>,
Andrew Waterman <andrew@...ive.com>,
Jim Wilson
<jim.wilson.gcc@...il.com>,
Dan Li <ashimida.1990@...il.com>,
"linux-hardening@...r.kernel.org" <linux-hardening@...r.kernel.org>
Subject: Re: [RFC PATCH 3/7] kcfi: Add core Kernel Control Flow Integrity
infrastructure
> On Aug 21, 2025, at 10:25, Peter Zijlstra <peterz@...radead.org> wrote:
>
> On Thu, Aug 21, 2025 at 01:01:37PM +0200, Richard Biener wrote:
>> On Thu, 21 Aug 2025, Peter Zijlstra wrote:
>>
>>> On Thu, Aug 21, 2025 at 01:16:56AM -0700, Andrew Pinski wrote:
>>>
>>>>> +/* Compute KCFI type ID for a function declaration or function type
>>>>> (internal) */
>>>>> +static uint32_t
>>>>> +compute_kcfi_type_id (tree fntype_or_fndecl)
>>>>> +{
>>>>> + if (!fntype_or_fndecl)
>>>>> + return 0;
>>>>> +
>>>>> + const char *canonical_name = mangle_function_type (fntype_or_fndecl);
>>>>> + uint32_t base_type_id = kcfi_hash_string (canonical_name);
>>>>>
>>>>
>>>> Now I am curious why this needs to be a mangled function name? Since the
>>>> function in C the symbol is just its name.
>>>> Is there documentation that says the hash needs to be based on all of the
>>>> function arguments types?
>>>
>>> The whole point of kCFI is to limit the targets of indirect calls to
>>> functions of the same signature. The actual function name is immaterial.
>>
>> What's the attack vector and how does kCFI achieve mitigating it?
>
> Any of the attacks that can result in scribbling a function pointer.
> Typically a buffer overflow I suppose.
>
>
> The way kCFI works is by changing the indirect call ABI. Traditionally
> the indirect call is simply:
>
> load-pointer-into-reg
> call *%reg
>
> kCFI changes every function to have a preamble like (with IBT and
> retpolines and all the modern crap on):
Does “every function” mean all the function in the compilation? Not only the function whose address is taken?
Qing
>
> __cfi_\func:
> movl $0x12345678, %eax
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> nop
> \func:
> endbr64
> ...
>
> And every indirect call site to:
>
> load-pointer-into-r11
> movl $(-0x12345678), %r10d
> addl $-15(%r11), %r10d
> je 2f
> 1:ud2
> .pushsection .kcfi_traps
> .long 1b - .
> .popsection
> 2:cs call __x86_indirect_thunk_r11
>
> Where 0x12345678 is the appropriate signature hash.
>
>
> So if the loaded pointer is scribbled somehow, the hash embedded at the
> callsite no longer matches the hash in the function preamble and #UD.
>
> The kernel is also going to rewrite this if the hardware supports IBT,
> into a FineIBT sequence (with too many variants :-/), but I'll spare you
> those details.
>
> Those people interested can find it here:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/kernel/alternative.c#n1298
>
>
>
Powered by blists - more mailing lists