lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1471890809-4383-4-git-send-email-mikko.rapeli@iki.fi>
Date:   Mon, 22 Aug 2016 20:32:20 +0200
From:   Mikko Rapeli <mikko.rapeli@....fi>
To:     linux-kernel@...r.kernel.org
Cc:     Mikko Rapeli <mikko.rapeli@....fi>
Subject: [PATCH v05 03/72] headers_compile_test.sh: add GNU libc compatibility test

The test is to compile all kernel uapi headers against the
non-conflicting set of all GNU libc headers. The test covers
variants where kernel header is included before libc header
and libc header before kernel header.

Tested in Debian unstable with libc6 version 2.22-4.

Example execution:

$ make headers_install && \
  cd usr/include && \
  ../../scripts/headers_compile_test.sh -lk
Testing that /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l
/libc_headers.h compiles
cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i
686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co
mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes
t_include.rwDf0l/i686-linux-gnu -o /dev/null ./drm/i810_drm.h
PASSED: ./drm/i810_drm.h
cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i
686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co
mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes
t_include.rwDf0l/i686-linux-gnu -o /dev/null ./drm/i810_drm.h_libc_before_kernel
.h
PASSED libc before kernel test: ./drm/i810_drm.h
...
cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i
686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co
mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes
t_include.rwDf0l/i686-linux-gnu -o /dev/null ./linux/coda.h
PASSED: ./linux/coda.h
cc -Wall -c -nostdinc -I /usr/lib/gcc/i686-linux-gnu/6/include -I /usr/lib/gcc/i
686-linux-gnu/6/include-fixed -I . -I /home/mcfrisk/src/linux-2.6/usr/headers_co
mpile_test_include.rwDf0l -I /home/mcfrisk/src/linux-2.6/usr/headers_compile_tes
t_include.rwDf0l/i686-linux-gnu -o /dev/null ./linux/coda.h_libc_before_kernel.h
In file included from ./linux/coda.h_libc_before_kernel.h:2:0:
./linux/coda.h:108:16: error: conflicting types for ‘dev_t’
 typedef u_long dev_t;
                ^~~~~
In file included from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_inclu
de.rwDf0l/aio.h:26:0,
                 from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_inclu
de.rwDf0l/libc_headers.h:1,
                 from ./linux/coda.h_libc_before_kernel.h:1:
/home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/sys/types.h:
60:17: note: previous declaration of ‘dev_t’ was here
 typedef __dev_t dev_t;
                 ^~~~~
In file included from ./linux/coda.h_libc_before_kernel.h:2:0:
./linux/coda.h:109:16: error: conflicting types for ‘caddr_t’
 typedef void * caddr_t;
                ^~~~~~~
In file included from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/aio.h:26:0,
                 from /home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/libc_headers.h:1,
                 from ./linux/coda.h_libc_before_kernel.h:1:
/home/mcfrisk/src/linux-2.6/usr/headers_compile_test_include.rwDf0l/sys/types.h:116:19: note: previous declaration of ‘caddr_t’ was here
 typedef __caddr_t caddr_t;
                   ^~~~~~~
FAILED libc before kernel test: ./linux/coda.h
...
Kernel header compile test statistics:

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

libc and kernel header compatibility test statistics:
39 files failed libc before kernel include test.
745 files passed libc before kernel include test.

Signed-off-by: Mikko Rapeli <mikko.rapeli@....fi>
---
 scripts/headers_compile_test.sh | 329 ++++++++++++++++++++++++++++++++++++++--
 1 file changed, 319 insertions(+), 10 deletions(-)

diff --git a/scripts/headers_compile_test.sh b/scripts/headers_compile_test.sh
index e13f533..94021b6 100755
--- a/scripts/headers_compile_test.sh
+++ b/scripts/headers_compile_test.sh
@@ -15,14 +15,19 @@ Execute in root directory of exported kernel headers in Linux kernel source
 tree. Sets up gcc and libc headers without existing kernel headers to
 a temporary environment and tries to compile all exported header files
 from current directory against them. Return value is zero if all tests pass,
-non-zero if something goes wrong during execution, or the amount of files
-which failed the compile test.
+non-zero if something goes wrong during execution or if any file failed
+the compile tests.
 
 Supported arguments:
 
-    -h|--help       print help
-    -k|--keep       don't cleanup temporary header files and directories
-    -v|--verbose    print more verbose output
+    -h|--help          print help
+    -k|--keep          don't cleanup temporary header files and directories
+    -lk|--libc-kernel  test for conflicts between kernel and libc headers
+                       when libc headers are included before kernel headers
+    -kl|--kernel-libc  test for conflicts between kernel and libc headers
+                       when kernel headers are included before libc headers
+    -l|--libc          test both -lk and -kl
+    -v|--verbose       print more verbose output
 
 Example in Linux kernel source tree:
 
@@ -38,6 +43,9 @@ set -euo pipefail
 
 KEEP=0
 HELP=0
+LIBC_TEST=0
+LIBC_KERNEL_TEST=0
+KERNEL_LIBC_TEST=0
 
 # command line arguments
 for p in "$@"; do
@@ -45,6 +53,19 @@ for p in "$@"; do
 		-k|--keep)
 			KEEP=1
 		;;
+		-l|--libc)
+			LIBC_TEST=1
+			LIBC_KERNEL_TEST=1
+			KERNEL_LIBC_TEST=1
+		;;
+		-lk|--libc-kernel)
+			LIBC_TEST=1
+			LIBC_KERNEL_TEST=1
+		;;
+		-kl|--kernel-libc)
+			LIBC_TEST=1
+			KERNEL_LIBC_TEST=1
+		;;
 		-h|--help)
 			HELP=1
 		;;
@@ -138,6 +159,164 @@ for d in $LIBC; do
 	fi
 done
 
+# A single header with all non-conflicting libc headers to test kernel
+# headers against libc headers for conflicts.
+if [ "$LIBC_TEST" != 0 ]; then
+	# List taken from Debian unstable libc6 version 2.21-9.
+	# Some glibc headers conflict with each other so they
+	# are filtered out. Not perfect but better than nothing.
+        #
+	# $ for f in $( egrep "\.h$" /var/lib/dpkg/info/libc6-dev\:i386.list | sed -e 's|/usr/include/||'| sort | grep -v arpa | grep -v linux-gnu | grep -v rpcsvc | grep -v regexp.h | grep -v rpc | grep -v scsi | grep -v talkd ); do echo "#include <$f>"; done > libc_headers.h
+
+	cat > "$COMPILE_TEST_INC/libc_headers.h" << EOF_LIBC_HEADERS
+#include <aio.h>
+#include <aliases.h>
+#include <alloca.h>
+#include <argp.h>
+#include <argz.h>
+#include <ar.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <complex.h>
+#include <cpio.h>
+#include <crypt.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <elf.h>
+#include <endian.h>
+#include <envz.h>
+#include <err.h>
+#include <errno.h>
+#include <error.h>
+#include <execinfo.h>
+#include <fcntl.h>
+#include <features.h>
+#include <fenv.h>
+#include <fmtmsg.h>
+#include <fnmatch.h>
+#include <fstab.h>
+#include <fts.h>
+#include <ftw.h>
+#include <_G_config.h>
+#include <gconv.h>
+#include <getopt.h>
+#include <glob.h>
+#include <gnu-versions.h>
+#include <grp.h>
+#include <gshadow.h>
+#include <iconv.h>
+#include <ifaddrs.h>
+#include <inttypes.h>
+#include <langinfo.h>
+#include <lastlog.h>
+#include <libgen.h>
+#include <libintl.h>
+#include <libio.h>
+#include <limits.h>
+#include <link.h>
+#include <locale.h>
+#include <malloc.h>
+#include <math.h>
+#include <mcheck.h>
+#include <memory.h>
+#include <mntent.h>
+#include <monetary.h>
+#include <mqueue.h>
+#include <netash/ash.h>
+#include <netatalk/at.h>
+#include <netax25/ax25.h>
+#include <netdb.h>
+#include <neteconet/ec.h>
+#include <net/ethernet.h>
+#include <net/if_arp.h>
+#include <net/if.h>
+#include <net/if_packet.h>
+#include <net/if_ppp.h>
+#include <net/if_shaper.h>
+#include <net/if_slip.h>
+#include <netinet/ether.h>
+#include <netinet/icmp6.h>
+#include <netinet/if_ether.h>
+#include <netinet/if_fddi.h>
+#include <netinet/if_tr.h>
+#include <netinet/igmp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip6.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <netipx/ipx.h>
+#include <netiucv/iucv.h>
+#include <netpacket/packet.h>
+#include <net/ppp-comp.h>
+#include <net/ppp_defs.h>
+#include <netrom/netrom.h>
+#include <netrose/rose.h>
+#include <net/route.h>
+#include <nfs/nfs.h>
+#include <nl_types.h>
+#include <nss.h>
+#include <obstack.h>
+#include <paths.h>
+#include <poll.h>
+#include <printf.h>
+#include <protocols/routed.h>
+#include <protocols/rwhod.h>
+#include <protocols/timed.h>
+#include <pthread.h>
+#include <pty.h>
+#include <pwd.h>
+#include <re_comp.h>
+#include <regex.h>
+#include <resolv.h>
+#include <sched.h>
+#include <search.h>
+#include <semaphore.h>
+#include <setjmp.h>
+#include <sgtty.h>
+#include <shadow.h>
+#include <signal.h>
+#include <spawn.h>
+#include <stab.h>
+#include <stdc-predef.h>
+#include <stdint.h>
+#include <stdio_ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stropts.h>
+#include <syscall.h>
+#include <sysexits.h>
+#include <syslog.h>
+#include <tar.h>
+#include <termio.h>
+#include <termios.h>
+#include <tgmath.h>
+#include <thread_db.h>
+#include <time.h>
+#include <ttyent.h>
+#include <uchar.h>
+#include <ucontext.h>
+#include <ulimit.h>
+#include <unistd.h>
+#include <ustat.h>
+#include <utime.h>
+#include <utmp.h>
+#include <utmpx.h>
+#include <values.h>
+#include <wait.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <wordexp.h>
+#include <xlocale.h>
+EOF_LIBC_HEADERS
+
+fi # LIBC_TEST
+
 # Simulate libc headers without kernel headers by removing
 # all known kernel header dirs from the copied libc ones.
 # This seems to magically work.
@@ -170,11 +349,32 @@ if [ "$GCC_INC"foobar == "foobar" ]; then
 fi
 set -u
 
-# For each header file, try to compile it using the headers we prepared.
+# sanity check: test that plain libc headers compile
+if [ "$LIBC_TEST" != 0 ]; then
+	echo "Testing that $COMPILE_TEST_INC/libc_headers.h compiles"
+	$CC -Wall -c -nostdinc $GCC_INC -I . \
+		-I "$COMPILE_TEST_INC" \
+		-I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \
+		-o /dev/null \
+		"$COMPILE_TEST_INC/libc_headers.h"
+fi
+
+# Summary counters:
 _FAILED=0
 _PASSED=0
+_LIBC_FAILED=0
+_LIBC_PASSED=0
+_LIBC_BEFORE_KERNEL_FAILED=0
+_LIBC_BEFORE_KERNEL_PASSED=0
+_KERNEL_BEFORE_LIBC_FAILED=0
+_KERNEL_BEFORE_LIBC_PASSED=0
+
+# For each header file, try to compile it using the headers we prepared.
 for f in $( find . -name "*\.h" | xargs ); do
 	_FAIL=0
+	_FAIL_LIBC=0
+	_FAIL_LIBC_BEFORE_KERNEL=0
+	_FAIL_KERNEL_BEFORE_LIBC=0
 
 	# compile test, CC not quoted to support ccache
 	echo $CC -Wall -c -nostdinc $GCC_INC -I . -I "$COMPILE_TEST_INC" -I "$COMPILE_TEST_INC/$ARCH_TRIPLET" -o /dev/null "$f"
@@ -189,10 +389,119 @@ for f in $( find . -name "*\.h" | xargs ); do
 		echo "PASSED: $f"
 		_PASSED="$(( _PASSED + 1))"
 	fi
+
+	# libc header conflict tests
+	if [ "$LIBC_TEST" != 0 ]; then
+		_LIBC_BEFORE_KERNEL="$f"_libc_before_kernel.h
+		_KERNEL_BEFORE_LIBC="$f"_kernel_before_libc.h
+
+		# libc header included before kernel header
+		if [ "$LIBC_KERNEL_TEST" != 0 ]; then
+			cat > "$_LIBC_BEFORE_KERNEL" << EOF_LIBC_BEFORE_KERNEL
+#include <libc_headers.h>
+#include <$( echo "$f" | cut -c3- )>
+EOF_LIBC_BEFORE_KERNEL
+			echo \
+				$CC -Wall -c -nostdinc $GCC_INC \
+				-I . -I "$COMPILE_TEST_INC" \
+				-I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \
+				-o /dev/null "$_LIBC_BEFORE_KERNEL"
+			$CC -Wall -c -nostdinc $GCC_INC \
+				-I . -I "$COMPILE_TEST_INC" \
+				-I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \
+				-o /dev/null "$_LIBC_BEFORE_KERNEL" \
+				|| _FAIL_LIBC_BEFORE_KERNEL=1
+
+			# report errors
+			if [ "$_FAIL_LIBC_BEFORE_KERNEL" -gt 0 ]; then
+				echo "FAILED libc before kernel test: $f"
+				_LIBC_BEFORE_KERNEL_FAILED="$(( _LIBC_BEFORE_KERNEL_FAILED + 1 ))"
+			else
+				echo "PASSED libc before kernel test: $f"
+				_LIBC_BEFORE_KERNEL_PASSED="$(( _LIBC_BEFORE_KERNEL_PASSED + 1))"
+			fi
+		fi
+
+		# kernel header included before libc
+		if [ "$KERNEL_LIBC_TEST" != 0 ]; then
+			cat > "$_KERNEL_BEFORE_LIBC" << EOF_KERNEL_BEFORE_LIBC
+#include <$( echo "$f" | cut -c3- )>
+#include <libc_headers.h>
+EOF_KERNEL_BEFORE_LIBC
+			echo \
+				$CC -Wall -c -nostdinc $GCC_INC \
+				-I . -I "$COMPILE_TEST_INC" \
+				-I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \
+				-o /dev/null "$_KERNEL_BEFORE_LIBC"
+			$CC -Wall -c -nostdinc $GCC_INC \
+				-I . -I "$COMPILE_TEST_INC" \
+				-I "$COMPILE_TEST_INC/$ARCH_TRIPLET" \
+				-o /dev/null "$_KERNEL_BEFORE_LIBC" \
+				|| _FAIL_KERNEL_BEFORE_LIBC=1
+
+			# report errors
+			if [ "$_FAIL_KERNEL_BEFORE_LIBC" -gt 0 ]; then
+				echo "FAILED kernel before libc test: $f"
+				_KERNEL_BEFORE_LIBC_FAILED="$(( _KERNEL_BEFORE_LIBC_FAILED + 1 ))"
+			else
+				echo "PASSED kernel before libc test: $f"
+				_KERNEL_BEFORE_LIBC_PASSED="$(( _KERNEL_BEFORE_LIBC_PASSED + 1))"
+			fi
+		fi
+
+		# libc summary
+		if [ "$_FAIL_LIBC_BEFORE_KERNEL" -gt 0 -o "$_FAIL_KERNEL_BEFORE_LIBC" -gt 0 ]; then
+			_LIBC_FAILED="$(( _LIBC_FAILED + 1))"
+		else
+			_LIBC_PASSED="$(( _LIBC_PASSED + 1))"
+		fi
+
+		if [ "$KEEP" = "0" ]; then
+			rm -f "$_LIBC_BEFORE_KERNEL" "$_KERNEL_BEFORE_LIBC"
+		fi
+	fi # LIBC_TEST
 done
 
-echo Statistics:
-echo "$_FAILED files failed the compile test."
-echo "$_PASSED files passed the compile test."
+cat << EOF_STATS
+
+Kernel header compile test statistics:
+
+$_FAILED files failed the kernel header compile test.
+$_PASSED files passed the kernel header compile test.
+
+EOF_STATS
+
+if [ "$LIBC_TEST" != 0 ]; then
+	cat << EOF_LIBC_STATS
+libc and kernel header compatibility test statistics:
+EOF_LIBC_STATS
+
+if [ "$LIBC_KERNEL_TEST" != 0 ] && [ "$KERNEL_LIBC_TEST" != 0 ]; then
+	cat << EOF_LIBC_COMBINED
+$_LIBC_FAILED files failed the libc compatibility test.
+$_LIBC_PASSED files passed the libc compatibility test.
+EOF_LIBC_COMBINED
+fi
+
+if [ "$LIBC_KERNEL_TEST" != 0 ]; then
+	cat << EOF_LIBC_KERNEL
+$_LIBC_BEFORE_KERNEL_FAILED files failed libc before kernel include test.
+$_LIBC_BEFORE_KERNEL_PASSED files passed libc before kernel include test.
+EOF_LIBC_KERNEL
+fi
+
+if [ "$KERNEL_LIBC_TEST" != 0 ]; then
+	cat << EOF_KERNEL_LIBC
+$_KERNEL_BEFORE_LIBC_FAILED files failed kernel before libc include test.
+$_KERNEL_BEFORE_LIBC_PASSED files passed kernel before libc include test.
+EOF_KERNEL_LIBC
+fi
 
-exit "$_FAILED"
+fi # LIBC_TEST
+
+# return value, summary of all failures.
+if [ "$(( $_FAILED + $_LIBC_BEFORE_KERNEL_FAILED + $_KERNEL_BEFORE_LIBC_FAILED ))" != 0 ]; then
+	exit 1
+else
+	exit 0
+fi
-- 
2.8.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ