Closed thestinger closed 7 months ago
@thestinger, I agree. I'll think and return with the solution.
Hello @thestinger,
I've found the solution.
1) Dropped the CONFIG_GCC_PLUGINS
check. This check is not security-relevant and it's not needed in case of building the kernel with clang
.
2) Added the CONFIG_CC_IS_GCC
dependency for gcc
plugins, that don't have analogues in clang
.
Let's see the output of kernel-hardening-checker
for a kernel config created with clang
.
[+] Special report mode: verbose
[+] Kconfig file to check: my/arm64_full_hardened_6.6_clang.config
[+] Detected microarchitecture: ARM64
[+] Detected kernel version: (6, 6, 7)
[+] Detected compiler: CLANG 150006
clang
and gcc
support CONFIG_INIT_STACK_ALL_ZERO
as alternative to CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
:
-------------------------------------------------------------------------------------------------------------------------
<<< OR >>> | OK
CONFIG_INIT_STACK_ALL_ZERO |kconfig| y |defconfig | self_protection | OK
CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL |kconfig| y | kspp | self_protection | None
-------------------------------------------------------------------------------------------------------------------------
Clang will support CONFIG_RANDSTRUCT_FULL
starting from version 16:
-------------------------------------------------------------------------------------------------------------------------
<<< OR >>> | FAIL: is not found
CONFIG_RANDSTRUCT_FULL |kconfig| y | kspp | self_protection | FAIL: is not found
CONFIG_GCC_PLUGIN_RANDSTRUCT |kconfig| y | kspp | self_protection | FAIL: is not found
-------------------------------------------------------------------------------------------------------------------------
<<< AND >>> | FAIL: CONFIG_RANDSTRUCT_FULL is not "y"
CONFIG_RANDSTRUCT_PERFORMANCE |kconfig| is not set | kspp | self_protection | None
CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE|kconfig| is not set | kspp | self_protection | None
<<< OR >>> | FAIL: is not found
CONFIG_RANDSTRUCT_FULL |kconfig| y | kspp | self_protection | FAIL: is not found
CONFIG_GCC_PLUGIN_RANDSTRUCT |kconfig| y | kspp | self_protection | FAIL: is not found
-------------------------------------------------------------------------------------------------------------------------
The CONFIG_GCC_PLUGIN_LATENT_ENTROPY
check gives FAIL: CONFIG_CC_IS_GCC is not "y"
:
-------------------------------------------------------------------------------------------------------------------------
<<< AND >>> | FAIL: CONFIG_CC_IS_GCC is not "y"
CONFIG_GCC_PLUGIN_LATENT_ENTROPY |kconfig| y | kspp | self_protection | None
CONFIG_CC_IS_GCC |kconfig| y | - | - | FAIL: is not found
-------------------------------------------------------------------------------------------------------------------------
The CONFIG_GCC_PLUGIN_STACKLEAK
check gives the same:
-------------------------------------------------------------------------------------------------------------------------
<<< AND >>> | FAIL: CONFIG_CC_IS_GCC is not "y"
CONFIG_GCC_PLUGIN_STACKLEAK |kconfig| y | kspp | self_protection | None
CONFIG_CC_IS_GCC |kconfig| y | - | - | FAIL: is not found
-------------------------------------------------------------------------------------------------------------------------
I decided not to remove the gcc
-specific checks for clang
builds and vice-versa.
I think users should see the options they miss when they choose a compiler for the kernel.
The example with the CONFIG_CFI_CLANG
check for the gcc
kernel build:
-------------------------------------------------------------------------------------------------------------------------
<<< AND >>> | FAIL: CONFIG_CC_IS_CLANG is not "y"
CONFIG_CFI_CLANG |kconfig| y | kspp | self_protection | None
CONFIG_CC_IS_CLANG |kconfig| y | - | - | FAIL: is not found
-------------------------------------------------------------------------------------------------------------------------
<<< AND >>> | FAIL: CONFIG_CC_IS_CLANG is not "y"
CONFIG_CFI_PERMISSIVE |kconfig| is not set | kspp | self_protection | None
CONFIG_CFI_CLANG |kconfig| y | kspp | self_protection | None
CONFIG_CC_IS_CLANG |kconfig| y | - | - | FAIL: is not found
-------------------------------------------------------------------------------------------------------------------------
What do you think?
@a13xp0p0v Yes, that makes perfect sense. Some features are GCC exclusive and some are Clang exclusive. PaX and grsecurity still exist where features going beyond what Clang provides for CFI exist for GCC but that's not available upstream where Clang has a big advantage until GCC provides kCFI.
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107048
The main thing missing upstream for Clang is STACKLEAK. Latent entropy really doesn't matter on any decent hardware but would still be quite useful in problematic environments.
It makes sense to check for the functionality provided by the plugins if there's no Clang alternative, but it doesn't make sense to fail from an irrelevant dependency for those features being unavailable. For example, using CONFIG_INIT_STACK_ALL_ZERO is more secure than the STRUCTLEAK plugin anyway, and has insignificant performance overhead. There are already checks for the latent entropy, RANDSTRUCT and STACKLEAK plugins, but there could be alternatives to those for Clang, and not having GCC_PLUGINS enabled is irrelevant.