^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/usr/bin/env perl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # headers_check.pl execute a number of trivial consistency checks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) # Usage: headers_check.pl dir arch [files...]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) # dir: dir to look for included files
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) # arch: architecture
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) # files: list of files to check
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) # The script reads the supplied files line by line and:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) # 1) for each include statement it checks if the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) # included file actually exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) # Only include files located in asm* and linux* are checked.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) # The rest are assumed to be system include files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) # 2) It is checked that prototypes does not use "extern"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) # 3) Check for leaked CONFIG_ symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) use warnings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) use strict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) use File::Basename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) my ($dir, $arch, @files) = @ARGV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) my $ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) my $line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) my $lineno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) my $filename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) foreach my $file (@files) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) $filename = $file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) open(my $fh, '<', $filename)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) or die "$filename: $!\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) $lineno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) while ($line = <$fh>) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) $lineno++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) &check_include();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) &check_asm_types();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) &check_sizetypes();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) &check_declarations();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) # Dropped for now. Too much noise &check_config();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) close $fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) exit $ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) sub check_include
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if ($line =~ m/^\s*#\s*include\s+<((asm|linux).*)>/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) my $inc = $1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) my $found;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) $found = stat($dir . "/" . $inc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!$found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) $inc =~ s#asm/#asm-$arch/#;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) $found = stat($dir . "/" . $inc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (!$found) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) printf STDERR "$filename:$lineno: included file '$inc' is not exported\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) $ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) sub check_declarations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) # soundcard.h is what it is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if ($line =~ m/^void seqbuf_dump\(void\);/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) # drm headers are being C++ friendly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) if ($line =~ m/^extern "C"/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if ($line =~ m/^(\s*extern|unsigned|char|short|int|long|void)\b/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) printf STDERR "$filename:$lineno: " .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) "userspace cannot reference function or " .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) "variable defined in the kernel\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) sub check_config
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if ($line =~ m/[^a-zA-Z0-9_]+CONFIG_([a-zA-Z0-9_]+)[^a-zA-Z0-9_]/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) printf STDERR "$filename:$lineno: leaks CONFIG_$1 to userspace where it is not valid\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) my $linux_asm_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) sub check_asm_types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if ($lineno == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) $linux_asm_types = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) } elsif ($linux_asm_types >= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if ($line =~ m/^\s*#\s*include\s+<asm\/types.h>/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) $linux_asm_types = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) printf STDERR "$filename:$lineno: " .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) "include of <linux/types.h> is preferred over <asm/types.h>\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) # Warn until headers are all fixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #$ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) my $linux_types;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) my %import_stack = ();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) sub check_include_typesh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) my $path = $_[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) my $import_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) my $fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) my @file_paths = ($path, $dir . "/" . $path, dirname($filename) . "/" . $path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) for my $possible ( @file_paths ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (not $import_stack{$possible} and open($fh, '<', $possible)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) $import_path = $possible;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) $import_stack{$import_path} = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (eof $fh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) my $line;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) while ($line = <$fh>) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) $linux_types = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) last;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) check_include_typesh($included);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) close $fh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) delete $import_stack{$import_path};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) sub check_sizetypes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if ($filename =~ /types.h|int-l64.h|int-ll64.h/o) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) if ($lineno == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) $linux_types = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) } elsif ($linux_types >= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if ($line =~ m/^\s*#\s*include\s+<linux\/types.h>/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) $linux_types = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (my $included = ($line =~ /^\s*#\s*include\s+[<"](\S+)[>"]/)[0]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) check_include_typesh($included);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if ($line =~ m/__[us](8|16|32|64)\b/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) printf STDERR "$filename:$lineno: " .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) "found __[us]{8,16,32,64} type " .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) "without #include <linux/types.h>\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) $linux_types = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) # Warn until headers are all fixed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) #$ret = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }