diff mbox

Fix linux/stddef.h coordination with glibc (Bug 20215)

Message ID 575699F9.6080903@redhat.com
State New
Headers show

Commit Message

Carlos O'Donell June 7, 2016, 9:55 a.m. UTC
Denys,

In recent linux 4.6.0 headers we have this:

git blame include/uapi/linux/stddef.h
~~~
607ca46e (David Howells  2012-10-13 10:46:48 +0100 1) #include <linux/compiler.h>
283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 2) 
283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 3) #ifndef __always_inline
283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 4) #define __always_inline inline
283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 5) #endif
~~~

The definition of __always_inline breaks certain header include
ordering between glibc and linux headers.

Mikko,

I'm curious if your header include fuzzing script caught this failure?

I am adding a source compile testing framework into glibc's test
framework to add regression tests for these failures, rather than
fuzz the whole set of headers. This way we can cover the problem
from both sides glibc and linux:
https://www.sourceware.org/ml/libc-alpha/2016-06/msg00162.html

Test case:
~~~
#include <linux/in6.h>
#include <netinet/in.h>

int
main (void)
{
  return 0;
}
~~~
In file included from ../include/sys/cdefs.h:3:0,
                 from ../include/features.h:368,
                 from ../inet/netinet/in.h:21,
                 from ../include/netinet/in.h:3,
                 from ../sysdeps/unix/sysv/linux/tst-ipv6-compat2.c:2:
../misc/sys/cdefs.h:307:0: error: "__always_inline" redefined [-Werror]
 # define __always_inline __inline __attribute__ ((__always_inline__))
 ^
In file included from /home/carlos/build/glibc-headers/include/linux/posix_types.h:4:0,
                 from /home/carlos/build/glibc-headers/include/linux/types.h:8,
                 from /home/carlos/build/glibc-headers/include/linux/in6.h:24,
                 from ../sysdeps/unix/sysv/linux/tst-ipv6-compat2.c:1:
/home/carlos/build/glibc-headers/include/linux/stddef.h:4:0: note: this is the location of the previous definition
 #define __always_inline __inline__
 ^
cc1: all warnings being treated as errors
~~~

The glibc definition, particularly the "__always_inline__" attribute needs
to win out, or we need to use a different name e.g. __glibc_always_inline
or __linux_always_inline. Despite both linux and glibc being part of the
"implementation" we can still run into this kind of namespace conflict.

Right now I've chosen to undefine the kernel version and use the glibc one.

I need to check if the glibc version is sufficient (for linux/swab.h) in the
case of a conflict and the glibc definition is the one that is used.

Regression tested with linux 4.6.0 headers using glibc tests-compile framework.

Thoughts?

Comments

Mikko Rapeli June 7, 2016, 10:14 a.m. UTC | #1
On Tue, Jun 07, 2016 at 05:55:05AM -0400, Carlos O'Donell wrote:
> Denys,
> 
> In recent linux 4.6.0 headers we have this:
> 
> git blame include/uapi/linux/stddef.h
> ~~~
> 607ca46e (David Howells  2012-10-13 10:46:48 +0100 1) #include <linux/compiler.h>
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 2) 
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 3) #ifndef __always_inline
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 4) #define __always_inline inline
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 5) #endif
> ~~~
> 
> The definition of __always_inline breaks certain header include
> ordering between glibc and linux headers.
> 
> Mikko,
> 
> I'm curious if your header include fuzzing script caught this failure?

I've seen this, but by default it is only a warning. I have not dared to
run my kernel headers tests with warnings-as-errors since there are so many of
them, and there are plenty of simple errors to fix first.

-Mikko
Mikko Rapeli June 7, 2016, 3:29 p.m. UTC | #2
On Tue, Jun 07, 2016 at 01:14:40PM +0300, Mikko Rapeli wrote:
> On Tue, Jun 07, 2016 at 05:55:05AM -0400, Carlos O'Donell wrote:
> > Denys,
> > 
> > In recent linux 4.6.0 headers we have this:
> > 
> > git blame include/uapi/linux/stddef.h
> > ~~~
> > 607ca46e (David Howells  2012-10-13 10:46:48 +0100 1) #include <linux/compiler.h>
> > 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 2) 
> > 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 3) #ifndef __always_inline
> > 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 4) #define __always_inline inline
> > 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 5) #endif
> > ~~~
> > 
> > The definition of __always_inline breaks certain header include
> > ordering between glibc and linux headers.
> > 
> > Mikko,
> > 
> > I'm curious if your header include fuzzing script caught this failure?
> 
> I've seen this, but by default it is only a warning. I have not dared to
> run my kernel headers tests with warnings-as-errors since there are so many of
> them, and there are plenty of simple errors to fix first.

Here is a sample Linux kernel headers compile test log

https://mcfrisk.kapsi.fi/temp/log_headers_test_v05.txt.gz

from my header fix branch

https://github.com/mcfrisk/linux/tree/headers_test_v05

Command executed in kernel source tree is:

~/src/linux-2.6$ make headers_install && cd usr/include && \
                 ../../scripts/headers_compile_test.sh -l -k

Error summary is:

Kernel header compile test statistics:

0 files failed the kernel header compile test.
774 files passed the kernel header compile test.

libc and kernel header compatibility test statistics:

113 files failed the libc compatibility test.
661 files passed the libc compatibility test.

39 files failed libc before kernel include test.
735 files passed libc before kernel include test.

112 files failed kernel before libc include test.
662 files passed kernel before libc include test.

-Mikko
Denys Vlasenko June 7, 2016, 7:13 p.m. UTC | #3
On 06/07/2016 11:55 AM, Carlos O'Donell wrote:
> Denys,
>
> In recent linux 4.6.0 headers we have this:
>
> git blame include/uapi/linux/stddef.h
> ~~~
> 607ca46e (David Howells  2012-10-13 10:46:48 +0100 1) #include <linux/compiler.h>
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 2)
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 3) #ifndef __always_inline
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 4) #define __always_inline inline
> 283d7573 (Denys Vlasenko 2016-03-30 00:14:57 +0200 5) #endif
> ~~~
>
> The definition of __always_inline breaks certain header include
> ordering between glibc and linux headers.
>
> Mikko,
>
> I'm curious if your header include fuzzing script caught this failure?
>
> I am adding a source compile testing framework into glibc's test
> framework to add regression tests for these failures, rather than
> fuzz the whole set of headers. This way we can cover the problem
> from both sides glibc and linux:
> https://www.sourceware.org/ml/libc-alpha/2016-06/msg00162.html
>
> Test case:
> ~~~
> #include <linux/in6.h>
> #include <netinet/in.h>
>
> int
> main (void)
> {
>   return 0;
> }
> ~~~
> In file included from ../include/sys/cdefs.h:3:0,
>                  from ../include/features.h:368,
>                  from ../inet/netinet/in.h:21,
>                  from ../include/netinet/in.h:3,
>                  from ../sysdeps/unix/sysv/linux/tst-ipv6-compat2.c:2:
> ../misc/sys/cdefs.h:307:0: error: "__always_inline" redefined [-Werror]
>  # define __always_inline __inline __attribute__ ((__always_inline__))
>  ^
> In file included from /home/carlos/build/glibc-headers/include/linux/posix_types.h:4:0,
>                  from /home/carlos/build/glibc-headers/include/linux/types.h:8,
>                  from /home/carlos/build/glibc-headers/include/linux/in6.h:24,
>                  from ../sysdeps/unix/sysv/linux/tst-ipv6-compat2.c:1:
> /home/carlos/build/glibc-headers/include/linux/stddef.h:4:0: note: this is the location of the previous definition
>  #define __always_inline __inline__
>  ^
> cc1: all warnings being treated as errors
> ~~~
>
> The glibc definition, particularly the "__always_inline__" attribute needs
> to win out

Then an "#undef __always_inline" needs to be added before glibc #define.
Carlos O'Donell June 9, 2016, 4 p.m. UTC | #4
On 06/07/2016 03:13 PM, Denys Vlasenko wrote:
> Then an "#undef __always_inline" needs to be added before glibc #define.

Is the glibc version sufficient for all the kernel header uses?

I see ~400 uses of __always_inline in kernel headers.

Is '__inline __attribute__((always_inline))' OK?
Denys Vlasenko June 9, 2016, 4:25 p.m. UTC | #5
On 06/09/2016 06:00 PM, Carlos O'Donell wrote:
> On 06/07/2016 03:13 PM, Denys Vlasenko wrote:
>> Then an "#undef __always_inline" needs to be added before glibc #define.
>
> Is the glibc version sufficient for all the kernel header uses?
>
> I see ~400 uses of __always_inline in kernel headers.
>
> Is '__inline __attribute__((always_inline))' OK?

Should be ok.
diff mbox

Patch

diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index 7fd4154..0b4607b 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -304,8 +304,13 @@ 
 
 /* Forces a function to be always inlined.  */
 #if __GNUC_PREREQ (3,2)
+/* The Linux kernel defines __always_inline in stddef.h (283d7573), and
+   it conflicts with this definition.  Therefore undefine it first to
+   allow either header to be included first.  */
+# undef __always_inline
 # define __always_inline __inline __attribute__ ((__always_inline__))
 #else
+# undef __always_inline
 # define __always_inline __inline
 #endif