According to news on the Linux kernel mailing list, the community recently discussed whether to adopt the modern C language standard for the kernel.

While the Linux kernel is evolving rapidly, it also relies on some very old tools, one of which is that the kernel code is still using the 1989 version of the C language standard - a standard that was written more than 30 years ago before the kernel project was started. As a result of the discussion, this is expected to change in kernel version 5.18.

Jakob Koschel has fixed a predictive execution vulnerability related to kernel chaining tables in a patch (Proposal for speculative safe list iterator) submitted to Linus Torvalds.

Proposal for speculative safe list iterator

The reason for this is that Jakob discovered a problem with the Linux kernel’s extensive use of bidirectional double linked lists defined by struct list_head :

1
2
3
struct list_head {
    struct list_head *next, *prev;
};

Such structures are usually embedded in other structures, and in this way developers can make a linked table using any structure type of interest. In addition to this, the kernel provides a large number of functions and macros that can be used to traverse and manipulate chained tables. One of these is list_for_each_entry(), a macro that masquerades as a control structure. To see how to use this macro, assume that the kernel contains the following structure.

1
2
3
4
struct foo {
    int fooness;
    struct list_head list;
};

The list member can be used to create a two-way chain of foo structures. Assuming we have a structure declaration called foo_list as the head of such a chain, the following code can be used to iterate through this list.

1
2
3
4
5
6
struct foo *iterator;

list_for_each_entry(iterator, &foo_list, list) {
    do_something_with(iterator);
}
/* Shoul

The list argument tells the macro the name of the list_head structure in the foo structure. This loop will execute once for each element in the list, with the iterator pointing to that element. This led to a bug in the USB subsystem: the iterator passed to the macro could be used after exiting the macro.

Koschel fixed the problem by rewriting the faulty code to stop using the iterator after the loop.

Linus, however, was puzzled by the patch fix and did not see how it related to the predictive execution vulnerability.

Koschel further explained this, to which Linus thought it was just a common bug, but shortly afterwards Linus discovered the root of the problem: the iterator passed to the list traversal macro had to be declared outside of the loop itself.

Subsequently, Linus thought it might be possible to use more straightforward fixes such as block-level variable declarations. But C89 doesn’t support it, and the C99 standard, released in 1999, does. So it may be time for the Linux kernel to move to the C99 standard.

Linus says that one of the reasons the kernel code has been stuck at C89 is that older versions of the compiler gcc have strange problems that break initialization routines. But now that the minimum version of GCC required by the kernel has been increased to v5.1, those bugs may no longer be relevant.

Arnd Bergmann, another kernel developer who follows architectural compiler issues closely, has proposed a direct upgrade to C11 or even C2x, although he is not sure if C11 will bring anything new to the kernel that will be useful. However, upgrading to C17 or C2x would break support for gcc-5/6/7, so upgrading to C11 would be easier to implement and may not be acceptable to the kernel community if the leap is too large.

Linus favored the idea, and in Bergmann confirmed that it should be possible to do so, Linus announced that the next kernel release v5.18 will try to use the C11 standard. If all goes well, the C language standard used in the next kernel release is expected to be upgraded to C11.