Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CFI: Add a compiler built-in that returns the actual address of a function #1353

Closed
samitolvanen opened this issue Apr 20, 2021 · 4 comments
Closed
Assignees
Labels
[FEATURE] CFI Related to building the kernel with Clang Control Flow Integrity feature-request Not a bug per-se [FIXED][LLVM] 14 This bug was fixed in LLVM 14.x

Comments

@samitolvanen
Copy link
Member

With -fno-sanitize-cfi-canonical-jump-tables, the compiler replaces function references with references to the CFI jump table. This is problematic when we want to initialize global variables with actual function addresses, such as in arch/x86/kernel/idt.c. Currently, the only solution is to disable CFI for the entire translation unit. Elsewhere in code, we can alternatively use inline assembly to take the function address (see function_nocfi()), but kernel maintainers aren't too thrilled about that approach either.

Solution: Add a compiler built-in, similar to __builtin_addressof(), to LLVM that always returns a pointer to the actual function. Peter suggests this might require a new constant expression type, similar to DSOLocalEquivalent.

cc @nickdesaulniers @kees @pcc

@samitolvanen samitolvanen added feature-request Not a bug per-se [FEATURE] CFI Related to building the kernel with Clang Control Flow Integrity non-canonical jump tables Issue related to the use of non-canonical jump tables in CFI labels Apr 20, 2021
@kees
Copy link

kees commented Apr 20, 2021

Yeah, this would likely clear the way for x86 CFI. Right now, it's a hard blocker. :(
https://lore.kernel.org/lkml/CALCETrWUS52tzLNiWL5sAVVB5-ko1EW73-TEiO=eZ5jF_QyGPQ@mail.gmail.com/

samitolvanen added a commit to samitolvanen/linux that referenced this issue May 20, 2021
Clang 13 will support CONFIG_STACKPROTECTOR_PER_TASK, but we need to
also pass the command line arguments to the linker to use it together
with CONFIG_LTO_CLANG.

Link: ClangBuiltLinux#1353
Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
@samitolvanen
Copy link
Member Author

@nickdesaulniers nickdesaulniers added the [PATCH] Submitted A patch has been submitted for review label Sep 8, 2021
samitolvanen added a commit to samitolvanen/llvm-project that referenced this issue Dec 20, 2021
With Control-Flow Integrity (CFI), the LowerTypeTests pass replaces
function references with CFI jump table references, which is a problem
for low-level code that needs the address of the actual function body.

For example, in the Linux kernel, the code that sets up interrupt
handlers needs to take the address of the interrupt handler function
instead of the CFI jump table, as the jump table may not even be mapped
into memory when an interrupt is triggered.

This change adds the no_cfi constant type, which wraps function
references in a value that LowerTypeTestsModule::replaceCfiUses does not
replace.

Link: ClangBuiltLinux/linux#1353

Reviewed By: nickdesaulniers, pcc

Differential Revision: https://reviews.llvm.org/D108478
samitolvanen added a commit to samitolvanen/llvm-project that referenced this issue Dec 20, 2021
Control-Flow Integrity (CFI) replaces references to address-taken
functions with pointers to the CFI jump table. This is a problem
for low-level code, such as operating system kernels, which may
need the address of an actual function body without the jump table
indirection.

This change adds the __builtin_function_start() builtin, which
accepts an argument that can be constant-evaluated to a function,
and returns the address of the function body.

Link: ClangBuiltLinux/linux#1353

Depends on D108478

Reviewed By: pcc, rjmccall

Differential Revision: https://reviews.llvm.org/D108479
@samitolvanen
Copy link
Member Author

@samitolvanen samitolvanen added [PATCH] Accepted A submitted patch has been accepted upstream and removed [PATCH] Submitted A patch has been submitted for review non-canonical jump tables Issue related to the use of non-canonical jump tables in CFI labels Dec 21, 2021
@nickdesaulniers nickdesaulniers added [FIXED][LLVM] 14 This bug was fixed in LLVM 14.x and removed [PATCH] Accepted A submitted patch has been accepted upstream labels Dec 21, 2021
@nickdesaulniers
Copy link
Member

samitolvanen added a commit to samitolvanen/linux that referenced this issue Apr 5, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
intel-lab-lkp pushed a commit to intel-lab-lkp/linux that referenced this issue Apr 6, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue Apr 7, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
roxell pushed a commit to roxell/linux that referenced this issue Apr 14, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20220405221618.633743-1-samitolvanen@google.com
samitolvanen added a commit to samitolvanen/linux that referenced this issue Apr 21, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue Apr 27, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue Apr 29, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue May 3, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue May 6, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue May 9, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue May 10, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
samitolvanen added a commit to samitolvanen/linux that referenced this issue May 13, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
ptr1337 pushed a commit to CachyOS/linux that referenced this issue Jun 4, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20220405221618.633743-1-samitolvanen@google.com
ptr1337 pushed a commit to CachyOS/linux that referenced this issue Jun 9, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20220405221618.633743-1-samitolvanen@google.com
github-actions bot pushed a commit to ararslan/llvm.vim that referenced this issue Sep 9, 2022
With Control-Flow Integrity (CFI), the LowerTypeTests pass replaces
function references with CFI jump table references, which is a problem
for low-level code that needs the address of the actual function body.

For example, in the Linux kernel, the code that sets up interrupt
handlers needs to take the address of the interrupt handler function
instead of the CFI jump table, as the jump table may not even be mapped
into memory when an interrupt is triggered.

This change adds the no_cfi constant type, which wraps function
references in a value that LowerTypeTestsModule::replaceCfiUses does not
replace.

Link: ClangBuiltLinux/linux#1353

Reviewed By: nickdesaulniers, pcc

Differential Revision: https://reviews.llvm.org/D108478
xairy pushed a commit to xairy/linux that referenced this issue Dec 16, 2022
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>

Bug: 244543039
Bug: 244373730
Link: https://lore.kernel.org/r/20220405221618.633743-1-samitolvanen@google.com
(cherry picked from commit e6f3b3c)
Change-Id: I71d0e805fc66123107ff51f6e30d689948d64fa1
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
bzy-080408 pushed a commit to bzy-080408/android_pkvm_kernel that referenced this issue Jan 15, 2023
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux/linux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>

Bug: 244543039
Bug: 244373730
Link: https://lore.kernel.org/r/20220405221618.633743-1-samitolvanen@google.com
(cherry picked from commit e6f3b3c)
Change-Id: I71d0e805fc66123107ff51f6e30d689948d64fa1
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
bzy-080408 pushed a commit to bzy-080408/android_pkvm_kernel that referenced this issue Jan 15, 2023
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux/linux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20220405221618.633743-1-samitolvanen@google.com
bzy-080408 pushed a commit to bzy-080408/android_pkvm_kernel that referenced this issue Jan 15, 2023
Clang 14 added support for the __builtin_function_start function,
which allows us to implement the function_nocfi macro without
architecture-specific inline assembly and in a way that also works
with static initializers.

Change CONFIG_CFI_CLANG to depend on Clang >= 14, define
function_nocfi using __builtin_function_start, and remove the arm64
inline assembly implementation.

Link: llvm/llvm-project@ec2e26e
Link: ClangBuiltLinux/linux#1353
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Tested-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Will Deacon <will@kernel.org> # arm64
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Kees Cook <keescook@chromium.org>

Bug: 244543039
Bug: 244373730
Link: https://lore.kernel.org/r/20220405221618.633743-1-samitolvanen@google.com
(cherry picked from commit e6f3b3c)
Change-Id: I71d0e805fc66123107ff51f6e30d689948d64fa1
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
cuviper pushed a commit to cuviper/llvm.vim that referenced this issue Mar 1, 2023
With Control-Flow Integrity (CFI), the LowerTypeTests pass replaces
function references with CFI jump table references, which is a problem
for low-level code that needs the address of the actual function body.

For example, in the Linux kernel, the code that sets up interrupt
handlers needs to take the address of the interrupt handler function
instead of the CFI jump table, as the jump table may not even be mapped
into memory when an interrupt is triggered.

This change adds the no_cfi constant type, which wraps function
references in a value that LowerTypeTestsModule::replaceCfiUses does not
replace.

Link: ClangBuiltLinux/linux#1353

Reviewed By: nickdesaulniers, pcc

Differential Revision: https://reviews.llvm.org/D108478
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[FEATURE] CFI Related to building the kernel with Clang Control Flow Integrity feature-request Not a bug per-se [FIXED][LLVM] 14 This bug was fixed in LLVM 14.x
Projects
None yet
Development

No branches or pull requests

3 participants