|
|
Log in / Subscribe / Register

The future of GCC plugins in the kernel

April 1, 2021

This article was contributed by Marta Rybczyńska

The process of hardening the kernel can benefit in a number of ways from support by the compiler. In recent years, the Kernel Self Protection Project has brought this support from the grsecurity/PaX patch set into the kernel in the form of GCC plugins; LWN looked into that process back in 2017. A recent discussion has highlighted the fact that the use of GCC plugins brings disadvantages as well, and some developers would prefer to see those plugins replaced.

The discussion started when Josh Poimboeuf reported an issue he encountered when building out-of-tree modules with GCC plugins enabled. In his case, the compilation would fail when the GCC version used to compile the module was even slightly different from the one used to build the kernel. He included a patch to change the error he received into a warning and disable the affected plugin. Later in the thread, Justin Forbes explained how the problematic configuration came about; it happens within the Fedora continuous-integration system, which starts by building a current toolchain snapshot. Other jobs then compile out-of-tree modules with the new toolchain, without recompiling the kernel itself. Since GCC plugins were enabled, all jobs with out-of-tree modules have been failing.

The idea of changing the error into a warning was met with a negative response from the kernel build-system maintainer, Masahiro Yamada, who stated: "We are based on the assumption that we use the same compiler for in-tree and out-of-tree". Poimboeuf responded that what he sees in real-world configurations doesn't match that assumption. Other kernel developers agreed with Yamada, though; Greg Kroah-Hartman wrote:

Have you not noticed include/linux/compiler.h and all of the different changes/workarounds we do for different versions of gcc/clang/intel compilers? We have never guaranteed that a kernel module would work that was built with a different compiler than the main kernel, and I doubt we can start now.

In addition, Yamada pointed out that the use of the same compiler version for both the kernel and its modules has been accepted as an assumption in previous discussions. With clear disapproval from the kernel developers, the discussion seemed closed at that point.

The dislike for GCC plugins

It restarted, however, when Poimboeuf came back a few days later with another idea for solving his problem: recompiling all plugins when the GCC version changes. This was refused by Yamada, who noted that Ubuntu does not have the GCC mismatch problem, so the problem seemed to be specific to Fedora. Linus Torvalds also disagreed with the proposal, but for another reason. For him there is no technical reason to recompile everything when the GCC version changes, but he expressed his concern on the usage and design of the GCC plugins in general. In a followup message he explained his reasoning in strong words:

The kernel gcc plugins _will_ go away eventually. They are an unmitigated disaster. They always have been. I'm sorry I ever merged that support. It's not only a maintenance nightmare, it's just a horrible thing and interface in the first place. It's literally BAD TECHNOLOGY.

For Torvalds, the right way to implement such plugins is at the intermediate representation (IR) level, but GCC plugins were designed differently for non-technical reasons (out of fear for non-free plugins, which LWN covered back in 2008). People who are interested in plugins should use Clang, as it has a clean IR and easily allows adding similar checks at the IR level, he said.

GCC plugins and their Clang equivalents

However, the removal of the kernel's GCC plugins does not seem likely in the near future. Kees Cook commented on the current status of the GCC plugins, their Clang equivalents, and why there is a user community for at least some of them. A number of the capabilities provided by the GCC plugins are not yet available with Clang — which many distributors are not using to build the kernel anyway.

Currently the kernel supports the following plugins (located in scripts/gcc-plugins/):

  • cyc_complexity computes the cyclomatic complexity of a function; it is one of the two initial example plugins, and likely has no users.
  • latent_entropy adds entropy from the CPU execution. Cook sees no uses of it, especially since the addition of the the jitter entropy mechanism. There is no Clang support planned.
  • The per-task stack protector for arm32 provides stack protection for 32-bit ARM platforms; no Clang equivalent exists today even for 64-bit systems, Cook said.
  • randstruct randomly changes the order of fields in kernel data structures that contain only function pointers, or are explicitly marked with __randomize_layout. There are two versions of this plugin: one complete and one restricted. The restricted version only changes the order of elements contained within the same cache line, which reduces the performance cost, but also the protection level. A Clang version was submitted, but is stalled. Cook noted that security-conscious end users tend to enable this plugin, but distributors do not.
  • sancov (which Cook didn't mention) helps fuzzing coverage by inserting a call to __sanitizer_cov_trace_pc() at the start of each basic block; it is used to determine which code blocks are being exercised.
  • stackleak traces the kernel's stack depth so that it can overwrite the used stack with a pattern when returning to user space. There is no Clang support planned for now.
  • structleak initializes structures that could be passed to user space. Clang has it implemented as the -ftrivial-auto-var-init=zero option; GCC is likely to gain support for that option as well at some point.

The end result is that there is probably a reason to keep these plugins around for a while yet.

Meanwhile, there were a couple of positive outcomes from the discussion. Along the way, it was realized that the plugins, which are highly sensitive to the GCC version they were built for, were not being rebuilt when that version changes. That had evidently been the case since the plugins were first added; that problem was fixed by Yamada, despite his rejection of this idea earlier in the discussion. As a solution for Poimboeuf's original problem, the developers finally agreed to show a warning when there is a GCC version mismatch between the kernel and modules. It will be up to the user to decide if the difference is minor and safe, or if it is necessary to recompile the kernel.

The problem of the GCC version mismatch was not the only one noticed by Poimboeuf; he also pointed out the plugin build-system's dependency on the (optional) gcc-plugin-devel package. Even if the user has the same GCC version as used for the kernel compilation, but they do not have this package, plugins will be silently disabled, though the kernel compilation will succeed without any warning. This problem has not been addressed further.

Conclusions

The discussion covered a number of problems with the GCC plugins. It likely means that developers should be careful when enabling them. Poimboeuf's original problem got a solution of sorts in the form of a warning, which might start showing up in some systems. Users might be able to ignore the warning if the two GCC versions are close. When enabling plugins, developers should be careful to install gcc-plugin-devel first, otherwise their modules may be compiled in an unexpected way.

The future of GCC plugins in the kernel is not set in stone yet. Clang seems to be a preferred option for the hardening work, and this direction has been encouraged by Torvalds, but the existing GCC plugins (with one exception) do not have Clang equivalents. It seems that they will stay for at least some time.


Index entries for this article
KernelBuild system/GCC plugins
KernelGCC
GuestArticlesRybczynska, Marta


to post comments

The future of GCC plugins in the kernel

Posted Apr 1, 2021 22:30 UTC (Thu) by ndesaulniers (subscriber, #110768) [Link]

FWIW I think some of these can simply be implemented in both compilers proper rather than plugins. They just require careful thought to at least try to make them not too specific to the Linux kernel codebase. I plan to look into implementing some of the these in Clang proper soon (and not as plugins, but -f flags perhaps).


Copyright © 2021, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds