Presented by

Abstract

Trailing arrays at the end of a structure are a common code construct in the Linux kernel. While they are often dynamically-sized, trailing arrays can also be fixed in size, defined at compile-time and remaining constant throughout their lifetime. It's a little-known fact that compilers like GCC (and Clang) have historically treated all trailing arrays as if they were flexible in size. This approach becomes problematic if we want to rely on the compiler to detect out-of-bounds issues on these arrays, both at compile-time and run-time. To effectively address this, the compiler must first accurately differentiate between dynamically-sized and fixed-size trailing arrays. The introduction of the -fstrict-flex-arrays option in GCC 13 (and Clang 16) marks a significant step towards this goal. Concurrently, in Kernel Self-Protection Project, we have been converting trailing zero-length and one-element arrays --commonly known as fake flexible arrays-- into modern C99 flexible-array members for years. We will see how the combination of these efforts, along with the implementation of some crucial compiler attributes, is paving the way towards eliminating out-of-bounds vulnerabilities on trailing arrays in the upstream Linux kernel. Furthermore, we will explore how this work is closely related to and contributes to the latest efforts in hardening key APIs like memcpy(), and in globally enabling options like -Warray-bounds.