September 24, 2022

COSFONE

Networking, PBX, IT, DIY Solution

The 30-year-old Linux kernel C language will be upgraded to C11

4 min read

The father of Linux was finally persuaded: the 30-year-old Linux kernel C language will be upgraded to C11



The father of Linux was finally persuaded: the 30-year-old Linux kernel C language will be upgraded to C11

Still using the ’89 version of the C Linux kernel, it’s finally time to make a change.

Today, the Linux open source community announced that the kernel C language version will be upgraded to C11 in the future, which is expected to take effect after version 5.18, which is May this year.

The decision was abrupt, and it’s only been a week since the question was raised to the official announcement, and it’s no easy task to convince the stubborn Linux father Linus Torvalds.

The reason for the matter is that there is still a little accidental factor.

A bug’s chain reaction

The origin of the problem came from a Linux community discussion last week.

A Ph.D. student named Jakob Koschel discovered such a problem while researching a speculative execution vulnerability related to kernel linked list primitives.

The Linux kernel makes extensive use of doubly linked lists defined by struct list_head:

The father of Linux was finally persuaded: the 30-year-old Linux kernel C language will be upgraded to C11

Such structures are often embedded in other structures. In this way, a linked list can be made using any relevant struct type.

In addition to this, the kernel provides a large number of functions and macros that can be used to traverse and manipulate linked lists. One of them is list_for_each_entry(), a macro disguised as a control structure.

The problem is with this macro.

Suppose the kernel contains the following structure:

The father of Linux was finally persuaded: the 30-year-old Linux kernel C language will be upgraded to C11

The elements in list can be used to create a doubly linked list of foo structures.

Assuming there is a struct declaration called foo_list as the head of such a linked list, this linked list can be traversed using the following code:

The father of Linux was finally persuaded: the 30-year-old Linux kernel C language will be upgraded to C11

The list parameter tells the macro the name of the list_head structure in the foo structure. This loop will be executed once for each element in the list to which the iterator points.

This leads to a bug in the USB subsystem: the iterator passed to this macro can still be used after exiting the macro.

This was a dangerous thing to do, so Koschel submitted a patch to fix the bug by stopping using iterators after the loop.

Convince Linus

But Linus Torvalds himself didn’t really like the patch, and didn’t see how it was related to the speculative execution vulnerability. After Koschel explained in detail, Linus admitted that it was just a common bug.

It wasn’t that simple, however, and Linus realized the real source soon after:

The iterator passed to the linked list traversal macro must be declared in scope outside the loop itself.

The reason this unpredictable bug occurs is that there is no “declare variables in loops” in C89.

Macros like list_for_each_entry() fundamentally always leak the last HEAD entry out of the loop, simply because we can’t declare iterator variables in the loop itself.

If it was possible to write an iterator list traversal macro that could declare itself, the iterator would not be visible outside the loop and no such problems would arise.

However, since the kernel is stuck on the C89 standard, it is not possible to declare variables in loops.

Linus decided, let’s just upgrade, maybe it’s time to move to the C99 standard.

While it’s also over 20 years old, it’s at least newer than C89 and can declare variables in loops.

Since C89 is so outdated, why hasn’t it changed for so many years? That’s because we had some weird issues with some old gcc compiler versions that couldn’t be upgraded casually, Linus said.

However, now that the Linux kernel has raised the minimum requirements for gcc to version 5.1, those weird bugs in the past should be gone.

Another core developer, Arnd Bergmann, believes that we can upgrade to C11 or even higher versions. But upgrading to C17 or C2x breaks gcc-5/6/7 support, so upgrading to C11 is easier to achieve.

Ultimately, Torvalds favored the idea: “Okay, please remind me, let’s try it out in the early days of the 5.18 merge window.”

Moving to C11 next may lead to some unexpected bugs, but if all goes well, the next Linus kernel release will officially move to C11.



You may have missed