]> sourceware.org Git - annobin.git/commitdiff
Update scripts to work with v3 notes
authorNick Clifton <nickc@redhat.com>
Wed, 3 Jan 2018 14:08:04 +0000 (14:08 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 3 Jan 2018 14:08:04 +0000 (14:08 +0000)
doc/annotation.proposal.txt
scripts/built-by.sh
scripts/check-abi.sh
scripts/hardened.sh

index 24264f3eae15f0b0776f423db34cb8d573b2b846..eeaae16a6bea52adb64cd290b4638d29a85730cf 100644 (file)
@@ -42,7 +42,7 @@ ChangeLog:
     section using this proposal.
 
 
-* The information is stored in a new section called .gnu.static.attributes.
+* The information is stored in a new section called .gnu.build.attributes.
   (The name can be changed - it is basically irrelevant anyway, it is
   the new section flag (defined below) that matters). 
 
@@ -57,7 +57,7 @@ ChangeLog:
 * The type field of a note is used to distinguish the range of memory
   over which an attribute applies.  The name field identifies the
   attribute and gives it a value.  The description field specifies the
-  starting address for where the attribute is applied.
+  starting and ending addresses for where the attribute is applied.
 
   Two new note types are defined:  NT_GNU_BUILD_ATTRIBUTE_OPEN (0x100)
   and NT_GNU_BUILD_ATTRIBUTE_FUNC (0x101).  These are used by the
@@ -101,7 +101,7 @@ ChangeLog:
 
      Character      Allowed    Meaning
     --------------- Types      -------
-    -              <none>      Reserved for future use.
+    0              <none>      Reserved for future use.
     1               $          Version of the specification supported and producer(s) of the notes (see below).
     2               *          Stack protector
     3               !+         Relro
@@ -110,8 +110,8 @@ ChangeLog:
     6               $*         ABI
     7               *          Position Independence Status: 0 => static, 1 => pic, 2 => PIC, 3 => pie
     8               !+         Short enums
-    9..30          <none>      Reserved for future use.
-    31..126         $*         An annotation type not explicitly defined by this specification.
+    9..31          <none>      Reserved for future use.
+    32..126         $*         An annotation type not explicitly defined by this specification.
     127+           <none>      Reserved for future use.
 
   For * and $ type attributes the value is then appended.
@@ -150,15 +150,6 @@ Some examples:
   This note serves as the base address for other open notes that
   follow, allowing them to use an empty description field.
 
-  The last note should be an end-note (ascii value 0) which specifies
-  the end address of the range covered by the previous open notes.  If
-  no end note is present then the address range is presumed to be open
-  at the higher end.
-
-  End-notes can also be used to indicate the end of a function
-  specific note's address range.  These notes must have the
-  NT_GNU_BUILD_ATTRIBUTE_FUNC type.
-
 * When the linker merges two or more files containing these notes it
   should ensure that the above rules are maintained.  Simply
   concatenating the incoming note sections should ensure this.
index b59ac71349e5d9cada2c1dadd5e165704446c6bc..f295587c23ba1df7a73ae3905c639849b03f557c 100755 (executable)
@@ -3,7 +3,7 @@
 # Script to check which tools built the specified binaries.
 #
 # Created by Nick Clifton.
-# Copyright (c) 2016-2017 Red Hat.
+# Copyright (c) 2016-2018 Red Hat.
 #
 # This is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published
@@ -29,7 +29,7 @@
 #    * Allow arguments to command line options to be separated from the
 #      the option name by a space.  Eg: --before 20161212
 
-version=2.0
+version=3.0
 
 help ()
 {
@@ -48,6 +48,7 @@ Usage: $prog {files|options}
   {options} are:
   -h        --help            Display this information.
   -v        --version         Report the version number of this script.
+  -V        --verbose         Report on progress.
   -s        --silent          Produce no output, just an exit status.
   -i        --ignore          Silently ignore files where the builder cannot be found.
   -r=<PATH> --readelf=<PATH>  Path to version of readelf to use to read notes.
@@ -83,7 +84,8 @@ main ()
 
     scan_files
 
-    if [ $failed -ne 0 ] ; then
+    if [ $failed -ne 0 ];
+    then
        exit 1
     else
        exit 0
@@ -92,11 +94,10 @@ main ()
 
 report ()
 {
-    if [ $silent -ne 0 ]
+    if [ $silent -eq 0 ]
     then
-       return
+       echo $prog":" ${1+"$@"}
     fi
-    echo $prog":" ${1+"$@"}
 }
 
 fail ()
@@ -105,6 +106,14 @@ fail ()
     exit 1
 }
 
+verbose ()
+{
+    if [ $verb -ne 0 ]
+    then
+       echo $prog":" ${1+"$@"}
+    fi
+}
+
 # Initialise global variables.
 init ()
 {
@@ -115,6 +124,7 @@ init ()
 
     failed=0
     silent=0
+    verb=0
     ignore_unknown=0
     scanner=readelf
     tmpfile=/dev/shm/built.by.delme
@@ -149,6 +159,11 @@ parse_args ()
                ;;
            -s | --silent)
                silent=1;
+               verb=0;
+               ;;
+           -V | --verbose)
+               silent=0;
+               verb=1;
                ;;
            -i | --ignore)
                ignore_unknown=1;
@@ -203,7 +218,7 @@ parse_args ()
        shift
     done
 
-    if [ $num_files -gt 0 ] ;
+    if [ $num_files -gt 0 ];
     then
        # Remember that we are counting from zero not one.
        let "num_files--"
@@ -277,8 +292,10 @@ scan_file ()
     fi
 
     file $file | grep --silent -e ELF
-    if [ $? != 0 ] ; then
-       if [ $ignore_unknown -eq 0 ]; then
+    if [ $? != 0 ];
+    then
+       if [ $ignore_unknown -eq 0 ];
+       then
            report "$file: not an ELF format file"
            failed=1
        fi
@@ -286,7 +303,8 @@ scan_file ()
     fi
     
     $scanner --wide --notes $file > $tmpfile 2>&1
-    if [ $? != 0 ] ; then
+    if [ $? != 0 ];
+    then
        if [ $ignore_unknown -eq 0 ]; then
            report "$file: scanner '$scanner' failed - see $tmpfile"
            failed=1
@@ -300,7 +318,8 @@ scan_file ()
 
     grep --silent -e "\$<tool>" $tmpfile
 
-    if [ $? == 0 ] ; then
+    if [ $? == 0 ];
+    then
        # Convert:
        #   $<tool>gcc 7.0.0 20161212 0x00000000 NT_GNU...
        # or
@@ -314,13 +333,19 @@ scan_file ()
        ver_index=1
        date_index=2
 
-       eval 'builder=($(grep -e tool $tmpfile | cut -d " " -f 3-5))'
-
-       if [ ${#builder[*]} -gt 3 ] ; then
-           report "$file: contains multiple different creator notes"
+       eval 'builder=($(grep -e tool $tmpfile | cut -d " " -f 3-5 | sort -u))'
+       
+       verbose "build notes contain: ${builder[*]}"
+       
+       if [ ${#builder[*]} -gt 3 ];
+       then
+           report "$file: contains multiple, different creator notes"
        fi
-       if [ ${#builder[*]} -lt 3 ] ; then
-           if [ $ignore_unknown -eq 0 ]; then
+
+       if [ ${#builder[*]} -lt 3 ];
+       then
+           if [ $ignore_unknown -eq 0 ];
+           then
                report "$file: contains truncated creator notes"
                failed=1
            fi
@@ -328,27 +353,39 @@ scan_file ()
        fi
        builder[0]=`echo ${builder[0]} | cut -d \> -f 2`
     else
+       verbose "scan for build notes failed, trying debug information"
+
        # Try examining the debug information in case -grecord-gcc-switches has been used.
        $scanner --wide --debug-dump=info $file | grep -e DW_AT_producer > $tmpfile
        eval 'builder=($(grep -e GNU $tmpfile))'
 
-       if [ ${#builder[*]} -ge 11 ] ; then
+       if [ ${#builder[*]} -ge 11 ];
+       then
            # FIXME: We should grep for the right strings, rather than using
            # builtin knowledge of the format of the DW_AT_producer contents
+
+           verbose "DW_AT_producer contains: ${builder[*]}"
+
            tool_index=7
            ver_index=9
            date_index=10
            builder[7]="${builder[7]} ${builder[8]}"
        else
+           verbose "scan for debug information failed, trying .comment section"
+           
            # Alright - last chance.  Check the .comment section
            $scanner -p.comment $file > $tmpfile 2>&1
            grep --silent -e "does not exist" $tmpfile
 
-           if [ $? != 0 ] ; then
+           if [ $? != 0 ];
+           then
                eval 'builder=($(grep -e GNU $tmpfile))'
 
+               verbose ".comment contains: ${builder[*]}"
+
                # FIXME: We are using assumed knowledge of the layout of the builder comment.
-               if [ ${#builder[*]} -lt 5 ] ; then
+               if [ ${#builder[*]} -lt 5 ];
+               then
                    if [ $ignore_unknown -eq 0 ]; then
                        report "$file: could not parse .comment section"
                        failed=1
@@ -369,40 +406,54 @@ scan_file ()
        fi
     fi
 
-    if [ $tell -eq 1 ] ; then
-       if [ x$tool != x ] ; then
-           if [ ${builder[$tool_index]} != $tool ] ; then
+    if [ $tell -eq 1 ];
+    then
+       if [ x$tool != x ];
+       then
+           if [ "${builder[$tool_index]}" == $tool ];
+           then
                tell=0
            fi
        fi
-       if [ x$nottool != x ] ; then
-           if [ ${builder[$tool_index]} == $nottool ] ; then
+       if [ x$nottool != x ];
+       then
+           if [ "${builder[$tool_index]}" == $nottool ];
+           then
                tell=0
            fi
        fi
-       if [ x$minver != x ] ; then
-           if [[ ${builder[$ver_index]} < $minver ]] ; then
+       if [ x$minver != x ];
+       then
+           if [[ ${builder[$ver_index]} < $minver ]];
+           then
                tell=0
            fi
        fi
-       if [ x$maxver != x ] ; then
-           if [[ ${builder[$ver_index]} > $maxver ]] ; then
+       if [ x$maxver != x ];
+       then
+           if [[ ${builder[$ver_index]} > $maxver ]];
+           then
                tell=0
            fi
        fi
-       if [ x$before != x ] ; then
-           if [ ${builder[$date_index]} -ge $before ] ; then
+       if [ x$before != x ];
+       then
+           if [ ${builder[$date_index]} -ge $before ];
+           then
                tell=0
            fi
        fi
-       if [ x$after != x ] ; then
-           if [ ${builder[$date_index]} -le $after ] ; then
+       if [ x$after != x ];
+       then
+           if [ ${builder[$date_index]} -le $after ];
+           then
                tell=0
            fi
        fi      
     fi
     
-    if [ $tell -eq 1 ]; then
+    if [ $tell -eq 1 ];
+    then
        report "$file: created by: ${builder[$tool_index]} v${builder[$ver_index]} ${builder[$date_index]}"
     fi
 
index 24b46322c0f468668d1a1e8b41f17a5a29e3d461..c61b04f9e2a368a3a2cb80dd438400a0137de9c2 100755 (executable)
@@ -1,9 +1,9 @@
 #!/bin/bash
 
-# Script to check for ABI conflicts in annotated binaries
+# Script to check for ABI conflicts in annotated binaries.
 #
 # Created by Nick Clifton.
-# Copyright (c) 2017 Red Hat.
+# Copyright (c) 2017-2018 Red Hat.
 #
 # This is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published
@@ -28,7 +28,7 @@
 #    * Allow arguments to command line options to be separated from the
 #      the option name by a space.  Eg: --readelf foobar
 
-version=2.0
+version=3.0
 
 help ()
 {
@@ -48,8 +48,8 @@ Usage: $prog {files|options}
   -h        --help             Display this information.
   -v        --version          Report the version number of this script.
   -s        --silent           Produce no output, just an exit status.
+  -V        --verbose          Report on progress.
   -i        --inconsistencies  Only report potential ABI problems.
-  -V        --verbose          Report files without conflicts
   -r=<PATH> --readelf=<PATH>   Path to version of readelf to use to read notes.
   -t=<PATH> --tmpfile=<PATH>   Temporary file to use.
 
@@ -77,7 +77,8 @@ main ()
 
     scan_files
 
-    if [ $failed -ne 0 ] ; then
+    if [ $failed -ne 0 ];
+    then
        exit 1
     else
        exit 0
@@ -86,11 +87,10 @@ main ()
 
 report ()
 {
-    if [ $silent -ne 0 ]
+    if [ $silent -eq 0 ]
     then
-       return
+       echo $prog":" ${1+"$@"}
     fi
-    echo $prog":" ${1+"$@"}
 }
 
 fail ()
@@ -99,6 +99,14 @@ fail ()
     exit 1
 }
 
+verbose ()
+{
+    if [ $verb -ne 0 ]
+    then
+       echo $prog":" ${1+"$@"}
+    fi
+}
+
 # Initialise global variables.
 init ()
 {
@@ -109,7 +117,7 @@ init ()
 
     failed=0
     silent=0
-    verbose=0
+    verb=0
     inconsistencies=0
     ignore_abi=0
     ignore_enum=0
@@ -137,18 +145,17 @@ parse_args ()
                report "version: $version"
                exit 0
                ;;
-
            -h | --help)
                help 
                exit 0
                ;;
            -s | --silent)
                silent=1;
-               verbose=0;
+               verb=0;
                ;;
            -V | --verbose)
                silent=0;
-               verbose=1;
+               verb=1;
                ;;
            -i | --inconsistencies)
                silent=0;
@@ -213,7 +220,7 @@ parse_args ()
        shift
     done
 
-    if [ $num_files -gt 0 ] ;
+    if [ $num_files -gt 0 ];
     then
        # Remember that we are counting from zero not one.
        let "num_files--"
@@ -290,7 +297,7 @@ scan_file ()
     fi
 
     file $file | grep --silent -e ELF
-    if [ $? != 0 ] ;
+    if [ $? != 0 ];
     then
        if [ $ignore_unknown -eq 0 ];
        then
@@ -301,7 +308,7 @@ scan_file ()
     fi
     
     $scanner --wide --notes $file > $tmpfile 2>&1
-    if [ $? != 0 ] ;
+    if [ $? != 0 ];
     then
        report "$file: scanner '$scanner' failed - see $tmpfile"
        failed=1
@@ -309,6 +316,22 @@ scan_file ()
        return
     fi
 
+    grep -q -e "Unknown note" $tmpfile
+    if [ $? == 0 ];
+    then
+       report "$file: scanner '$scanner' failed - see $tmpfile"
+       failed=1
+       # Leave the tmpfile intact so that it can be examined by the user.
+       return
+    fi
+       
+    grep -q -e "Gap in build notes" $tmpfile
+    if [ $? == 0 ];
+    then
+       report "$file: there are gaps in the build notes"
+       failed=1
+    fi       
+
     local -a abis
 
     if [ $ignore_abi -ne 1 ];
@@ -320,29 +343,26 @@ scan_file ()
        # into:
        #   abis[n]=145e82c442000192
 
-       eval 'abis=($(grep -e \<ABI\> $tmpfile | cut -d " " -f 3 | cut -d x -f 2))'
+       eval 'abis=($(grep -e \<ABI\> $tmpfile | cut -d " " -f 3 | cut -d x -f 2 | sort -u))'
+
+       verbose "ABI Info: ${abis[*]}"
 
        if [ ${#abis[*]} -lt 1 ];
        then
            if [[ $ignore_abi -eq 0 && $inconsistencies -eq 0 ]];
            then
                report "$file: does not have an ABI note"
-               # grep -e ABI $tmpfile
            fi
        else
-           if [ ${#abis[*]} -eq 1 ];
+           if [ ${#abis[*]} -gt 1 ];
            then
-               if [ $verbose -eq 1 ];
-               then
-                   report "$file: ABI: ${abis[0]}"
-               fi
-           else
                local i mismatch=0
 
                if [ $inconsistencies -eq 0 ];
                then
                    report "$file: contains ${#abis[*]} ABI notes"
                fi
+
                i=1;
                while [ $i -lt ${#abis[*]} ]
                do
@@ -350,18 +370,15 @@ scan_file ()
                    then
                        # FIXME: Add code to differentiate between functions which have changed ABI and files ?
                        report "$file: differing ABI values detected: ${abis[i]} vs ${abis[i-1]}"
-                       failed=1;
-                       mismatch=1;
+                       failed=1
+                       mismatch=1
                    fi
                    let "i++"
                done
 
                if [ $mismatch -eq 0 ];
                then
-                   if [ $verbose -eq 1 ];
-                   then
-                       report "$file: ABI: ${abis[0]}"
-                   fi
+                   verbose "$file: ABI: ${abis[0]}"
                fi
            fi
        fi
@@ -378,7 +395,9 @@ scan_file ()
        # into:
        #   abis[n]=false
 
-       eval 'abis=($(grep -e "short enum" $tmpfile | cut -f 2 -d ">" | cut -f 1 -d " "))'
+       eval 'abis=($(grep -e "short enum" $tmpfile | cut -f 2 -d ">" | cut -f 1 -d " " | sort -u))'
+
+       verbose "Enum Info: ${abis[*]}"
 
        if [ ${#abis[*]} -lt 1 ];
        then
@@ -387,13 +406,8 @@ scan_file ()
                report "$file: does not record enum size"
            fi
        else
-           if [ ${#abis[*]} -eq 1 ];
+           if [ ${#abis[*]} -gt 1 ];
            then
-               if [ $verbose -eq 1 ];
-               then
-                   report "$file: -fshort-enums: ${abis[0]}"
-               fi
-           else
                local i mismatch=0
 
                if [ $inconsistencies -eq 0 ];
@@ -406,18 +420,15 @@ scan_file ()
                    if test "${abis[i]}" != "${abis[i-1]}" ;
                    then
                        report "$file: differing -fshort-enums detected: ${abis[i]} vs ${abis[i-1]}"
-                       failed=1;
-                       mismatch=1;
+                       failed=1
+                       mismatch=1
                    fi
                    let "i++"
                done
 
-               if [ $mismatch -eq 0 ] ;
+               if [ $mismatch -eq 0 ];
                then
-                   if [ $verbose -eq 1 ];
-                   then
-                       report "$file: -fshort-enums: ${abis[0]}"
-                   fi
+                   verbose "$file: -fshort-enums: ${abis[0]}"
                fi
            fi
        fi
@@ -432,7 +443,9 @@ scan_file ()
        # into:
        #   abis[n]=1
 
-       eval 'abis=($(grep -e FORTIFY $tmpfile | cut -f 2 -d ":" | cut -b 3-5 | sed -e "s/ff/unknown/"))'
+       eval 'abis=($(grep -e FORTIFY $tmpfile | cut -f 2 -d ":" | cut -b 3-5 | sed -e "s/ff/unknown/" | sort -u))'
+
+       verbose "Fortify Info: ${abis[*]}"
 
        if [ ${#abis[*]} -lt 1 ];
        then
@@ -441,13 +454,8 @@ scan_file ()
                report "$file: does not record _FORTIFY_SOURCE level"
            fi
        else
-           if [ ${#abis[*]} -eq 1 ];
+           if [ ${#abis[*]} -gt 1 ];
            then
-               if [ $verbose -eq 1 ];
-               then
-                   report "$file: -D_FORTIFY_SOURCE=${abis[0]}"
-               fi
-           else
                local i mismatch=0
 
                if [ $inconsistencies -eq 0 ];
@@ -468,10 +476,7 @@ scan_file ()
 
                if [ $mismatch -eq 0 ];
                then
-                   if [ $verbose -eq 1 ];
-                   then
-                       report "$file: -D_FORTIFY_SOURCE=${abis[0]}"
-                   fi
+                   verbose "$file: -D_FORTIFY_SOURCE=${abis[0]}"
                fi
            fi
        fi
@@ -484,7 +489,9 @@ scan_file ()
        # into:
        #   abis[n]=<type>
 
-       eval 'abis=($(grep -e "stack prot" $tmpfile | cut -f 4 -d " " | cut -b 6-))'
+       eval 'abis=($(grep -e "stack prot" $tmpfile | cut -f 4 -d " " | cut -b 6- | sort -u))'
+
+       verbose "Stack Protection Info: ${abis[*]}"
 
        if [ ${#abis[*]} -lt 1 ];
        then
@@ -495,10 +502,7 @@ scan_file ()
        else
            if [ ${#abis[*]} -eq 1 ];
            then
-               if [ $verbose -eq 1 ];
-               then
-                   report "$file: -fstack-protect=${abis[0]}"
-               fi
+               verbose "$file: -fstack-protect=${abis[0]}"
            else
                local i mismatch=0
 
@@ -520,10 +524,7 @@ scan_file ()
 
                if [ $mismatch -eq 0 ];
                then
-                   if [ $verbose -eq 1 ];
-                   then
-                       report "$file: -fstack-protect=${abis[0]}"
-                   fi
+                   verbose "$file: -fstack-protect=${abis[0]}"
                fi
            fi
        fi
index 8b4c3a4c30f4b5ff7a8a5f7f833020c76e01f5eb..cb59f973a16de04da59ea20e39ad5a9ec839c2da 100755 (executable)
@@ -3,7 +3,7 @@
 # Script to check for hardening options in annotated binaries
 #
 # Created by Nick Clifton.
-# Copyright (c) 2017 Red Hat.
+# Copyright (c) 2017-2018 Red Hat.
 #
 # This is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published
@@ -29,7 +29,7 @@
 #    * Allow arguments to command line options to be separated from the
 #      the option name by a space.  Eg: --readelf foobar
 
-version=2.0
+version=3.0
 
 help ()
 {
@@ -64,6 +64,7 @@ Usage: $prog {files|options}
   -v        --version          Report the version number of this script and exit.
 
   -s        --silent           Produce no output, just an exit status.
+  -V        --verbose          Report on progress.
   -u        --vulnerable       Only report files known to be vulnerable. [default]
   -n        --not-hardened     Report any file that is not proven to be hardened.
   -a        --all              Report the hardening status of all files.
@@ -103,7 +104,8 @@ main ()
 
     scan_files
 
-    if [ $failed -ne 0 ] ; then
+    if [ $failed -ne 0 ];
+    then
        exit 1
     else
        exit 0
@@ -112,19 +114,54 @@ main ()
 
 report ()
 {
-    if [ $report -eq 0 ]
+    if [ $report -ne 0 ]
     then
-       return
+       echo $prog":" ${1+"$@"}
     fi
-    echo $prog":" ${1+"$@"}
 }
 
-fail ()
+ICE ()
 {
     report "Internal error: " ${1+"$@"}
     exit 1
 }
 
+verbose ()
+{
+    if [ $verb -ne 0 ]
+    then
+       echo $prog":" ${1+"$@"}
+    fi
+}
+
+maybe ()
+{
+    if [ $report -gt 1 ]
+    then
+       echo $prog": $file: MAYBE:" ${1+"$@"}
+    fi
+
+    vulnerable=1
+}
+
+fail ()
+{
+    if [ $report -gt 0 ]
+    then
+       echo $prog": $file: FAIL:" ${1+"$@"}
+    fi
+
+    vulnerable=1
+}
+
+pass ()
+{
+    if [ $report -gt 2 ]
+    then
+       echo $prog": $file: PASS:" ${1+"$@"}
+    fi
+}
+
 # Initialise global variables.
 init ()
 {
@@ -135,6 +172,7 @@ init ()
 
     failed=0
     report=1 # Quad-state, 0=> report nothing, 1=> report known vulnerable, 2=> report not proven hardened, 3=> report all
+    verb=0
     filetype=auto
     skip_opt=0
     skip_stack=0
@@ -167,9 +205,12 @@ parse_args ()
                help 
                exit 0
                ;;
-
            -s | --silent)
                report=0;
+               verb=0;
+               ;;
+           -V | --verbose)
+               verb=1;
                ;;
            -u | --vulnerable)
                report=1;
@@ -262,7 +303,7 @@ parse_args ()
        shift
     done
 
-    if [ $num_files -gt 0 ] ;
+    if [ $num_files -gt 0 ];
     then
        # Remember that we are counting from zero not one.
        let "num_files--"
@@ -291,11 +332,11 @@ scan_file ()
     # Paranoia checks - the user should never encounter these.
     if test "x$1" = "x" ;
     then
-       fail "scan_file called without an argument"
+       ICE "scan_file called without an argument"
     fi
     if test "x$2" != "x" ;
     then
-       fail "scan_file called with too many arguments"
+       ICE "scan_file called with too many arguments"
     fi
 
     # Use quotes when accessing files in order to preserve
@@ -339,7 +380,7 @@ scan_file ()
     fi
 
     file $file | grep --silent -e ELF
-    if [ $? != 0 ] ;
+    if [ $? != 0 ];
     then
        if [ $ignore_unknown -eq 0 ];
        then
@@ -350,28 +391,43 @@ scan_file ()
     fi
 
     $scanner --wide --notes --debug-dump=info --dynamic --segments $file > $tmpfile 2>&1
-    if [ $? != 0 ] ;
+    if [ $? != 0 ];
     then
-       report "$file: scanner '$scanner' failed - see $tmpfile"
+       report "scanner '$scanner' failed - see $tmpfile"
        failed=1
        # Leave the tmpfile intact so that it can be examined by the user.
        return
     fi
 
+    grep -q -e "Unknown note" $tmpfile
+    if [ $? == 0 ];
+    then
+       report "scanner '$scanner' did not recognise the build attribute notes - see $tmpfile"
+       failed=1
+       # Leave the tmpfile intact so that it can be examined by the user.
+       return
+    fi       
+
+    grep -q -e "Gap in build notes" $tmpfile
+    if [ $? == 0 ];
+    then
+       maybe "there are gaps in the build notes"
+    fi       
+
     local -a hard
     local vulnerable=0
 
-    if [ $skip_opt -eq 0 ] ;
+    if [ $skip_opt -eq 0 ];
     then
        check_optimization_level
     fi
 
-    if [ $skip_stack -eq 0 ] ;
+    if [ $skip_stack -eq 0 ];
     then
        check_for_stack_protector
     fi
 
-    if [ $skip_fortify -eq 0 ] ;
+    if [ $skip_fortify -eq 0 ];
     then
        check_for_fortify
     fi
@@ -379,18 +435,18 @@ scan_file ()
     # Do not check the bind_now or relro status of unlinked files.
     if [[ $filetype == exec || $filetype == lib        || ( $filetype == auto && $file != *.o && $file != x*.a ) ]] ;
     then
-       if [ $skip_bind_now -eq 0 ] ;
+       if [ $skip_bind_now -eq 0 ];
        then
            check_for_bind_now
        fi
        
-       if [ $skip_relro -eq 0 ] ;
+       if [ $skip_relro -eq 0 ];
        then
            check_for_relro
        fi
     fi
 
-    if [ $skip_pic -eq 0 ] ;
+    if [ $skip_pic -eq 0 ];
     then
        check_for_pie_or_pic
     fi
@@ -413,46 +469,34 @@ check_for_fortify ()
     # into:
     #   2
     
-    eval 'hard=($(grep -e FORTIFY $tmpfile | grep NT_GNU_BUILD_ATTRIBUTE_OPEN | cut -f 2 -d ":" | cut -b 3-5 | sed -e "s/ff/-1/" | sort | uniq))'
+    eval 'hard=($(grep -e FORTIFY $tmpfile | grep OPEN | cut -f 2 -d ":" | cut -b 3-5 | sed -e "s/ff/-1/" | sort -u))'
 
+    verbose "FORTIFY Info: ${hard[*]}"
+    
     if [ ${#hard[*]} -lt 1 ];
     then
-       if [ $report -gt 1 ];
-       then
-           # Or an old version of readelf is being used which does not recognise the fortify note...
-           report "$file: MAYBE: does not record _FORTIFY_SOURCE level"
-       fi
-       vulnerable=1
+       # Or an old version of readelf is being used which does not recognise the fortify note...
+       maybe "does not record _FORTIFY_SOURCE level"
     else
-       if [ ${#hard[*]} -gt 1 ];
-       then
-           # FIXME: Check for multiple values above 1 ?
-           if [ $report -gt 1 ];
-           then
-               report "$file: MAYBE: multiple values for _FORTIFY_SOURCE level recorded"
-           fi
-           vulnerable=1
-       else
-           if [ ${hard[0]} -lt 0 ];
+       # Check the value(s) to make sure that they are all >= 2.
+       local i
+
+       i=0;
+       while [ $i -lt ${#hard[*]} ]
+       do
+           if [ ${hard[i]} -lt 0 ];
            then
-               if [ $report -gt 1 ];
-               then
-                   report "$file: MAYBE: sources compiled with --save-temps do not record _FORTIFY_SOURCE level"
-               fi
-               vulnerable=1
+               maybe "sources compiled with --save-temps do not record _FORTIFY_SOURCE level"
            else
-               if [[ ${hard[0]} -lt 2 ]];
+               if [[ ${hard[i]} -lt 2 ]];
                then
-                   report "$file: FAIL: insufficient value for -D_FORTIFY_SOURCE=${hard[0]}"
-                   vulnerable=1
+                   fail "insufficient value for -D_FORTIFY_SOURCE=${hard[i]}"
                else
-                   if [ $report -gt 2 ];
-                   then
-                       report "$file: PASS: -D_FORTIFY_SOURCE=${hard[0]}"
-                   fi
+                   pass "-D_FORTIFY_SOURCE=${hard[i]}"
                fi
            fi
-       fi
+           let "i++"
+       done
     fi
 }
 
@@ -464,8 +508,10 @@ check_for_stack_protector ()
     #   GA*<stack prot>strong 0x00000000 NT_GNU_BUILD_ATTRIBUTE_OPEN
     # into:
     #   strong
-    eval 'hard=($(grep -e "stack prot" $tmpfile | grep NT_GNU_BUILD_ATTRIBUTE_OPEN | cut -f 2 -d ">" | cut -f 1 -d " " | sort | uniq))'
+    eval 'hard=($(grep -e "stack prot" $tmpfile | grep OPEN | cut -f 2 -d ">" | cut -f 1 -d " " | sort -u))'
 
+    verbose "Stack Protection Info: ${hard[*]}"
+    
     if [ ${#hard[*]} -lt 1 ];
     then
        # Stack protector note not recorded.  Try examining the debug
@@ -475,30 +521,23 @@ check_for_stack_protector ()
        # into:
        #   strong
        eval hard=($(gawk -e 'BEGIN { FPAT = "-f[no-]*stack-protector[^ ]*" } /f/ { print substr ($1,19) ; }' $tmpfile | sort | uniq))
+
+       verbose "DW_AT_producer stack records: ${hard[*]}"
     fi
   
     if [ ${#hard[*]} -lt 1 ];
     then
-       if [ $report -gt 1 ];
-       then
-           report "$file: MAYBE: does not record -fstack_protector setting"
-       fi
-       vulnerable=1
+       maybe "does not record -fstack_protector setting"
     else
        if [ ${#hard[*]} -gt 1 ];
        then
-           report "$file: FAIL: multiple, different, settings of -fstack-protector used"
-           vulnerable=1
+           fail "multiple, different, settings of -fstack-protector used"
        else
            if test "x${hard[0]}" = "xstrong" ;
            then
-               if [ $report -gt 2 ];
-               then
-                   report "$file: PASS: compiled with -fstack-protector-strong"
-               fi
+               pass "compiled with -fstack-protector-strong"
            else
-               vulnerable=1
-               report "$file: FAIL: compiled with -fstack-protector-${hard[0]}"
+               fail "compiled with -fstack-protector-${hard[0]}"
            fi
        fi
     fi
@@ -509,19 +548,19 @@ check_for_stack_protector ()
     #   GA*<stack prot>strong  0x00000000 NT_GNU_BUILD_ATTRIBUTE_FUNC
     # into:
     #   strong
-    eval 'hard=($(grep -e "stack prot" $tmpfile | grep NT_GNU_BUILD_ATTRIBUTE_FUNC | cut -f 2 -d ">" | cut -f 1 -d " " | sort | uniq))'
+    eval 'hard=($(grep -e "stack prot" $tmpfile | grep -e NT_GNU_BUILD_ATTRIBUTE_FUNC -e func | cut -f 2 -d ">" | cut -f 1 -d " " | sort -u))'
+
+    verbose "Stack Prot Info: ${hard[*]}"
 
     if [ ${#hard[*]} -gt 0 ];
     then
        if [ ${#hard[*]} -gt 1 ];
        then
-           report "$file: FAIL: contains functions compiled without -fstack-protector=strong"
-           vulnerable=1
+           fail "contains functions compiled without -fstack-protector=strong"
        else
            if test "x${hard[0]}" != "xstrong" ;
            then
-               report "$file: FAIL: contains functions compiled with -fstack-protector-${hard[0]}"
-               vulnerable=1
+               fail "contains functions compiled with -fstack-protector-${hard[0]}"
            fi
        fi
     fi
@@ -534,7 +573,9 @@ check_for_pie_or_pic ()
     #   GA*<PIC>PIE          0x00000000        NT_GNU_BUILD_ATTRIBUTE_OPEN
     # into:
     #   PIE
-    eval 'hard=($(grep -e "<PIC>" $tmpfile | grep NT_GNU_BUILD_ATTRIBUTE_OPEN | cut -f 2 -d ">" | cut -f 1 -d " " | sort | uniq))'
+    eval 'hard=($(grep -e "<PIC>" $tmpfile | grep OPEN | cut -f 2 -d ">" | cut -f 1 -d " " | sort -u))'
+
+    verbose "PIC Info: ${hard[*]}"
 
     if [ ${#hard[*]} -lt 1 ];
     then
@@ -544,44 +585,33 @@ check_for_pie_or_pic ()
        #   <c> DW_AT_producer : (indirect string, offset: 0x0): GNU C11 6.3.1 20161221 (Red Hat 6.3.1-1) -g -O2 -fPIC
        # into:
        #   PIC
-       eval hard=($(gawk -e 'BEGIN { FPAT = "-f[pP][iI][cCeE]" } /f/ { print substr ($1,3) ; }' $tmpfile | sort | uniq))
+       eval hard=($(gawk -e 'BEGIN { FPAT = "-f[pP][iI][cCeE]" } /f/ { print substr ($1,3) ; }' $tmpfile | sort -u))
+
+       verbose "DW_AT_producer records: ${hard[*]}"
     fi
   
     if [ ${#hard[*]} -lt 1 ];
     then
-       if [ $report -gt 1 ];
-       then
-           report "$file: MAYBE: does not record -fpic/-fpie setting"
-       fi
-       vulnerable=1
+       maybe "does not record -fpic/-fpie setting"
     else
        if [ ${#hard[*]} -gt 1 ];
        then
-           report "$file: FAIL: multiple, different, settings of -fpic/-fpie used"
-           vulnerable=1
+           fail "multiple, different, settings of -fpic/-fpie used"
        else
            if [[ $filetype = lib || ( $filetype = auto && $file == *.so ) ]] ;
            then
                if [[ "x${hard[0]}" -eq "xPIC" || "x${hard[0]}" -eq "xpic" ]] ;
                then
-                   if [ $report -gt 2 ];
-                   then
-                       report "$file: PASS: compiled with -f${hard[0]}"
-                   fi
+                   pass "compiled with -f${hard[0]}"
                else
-                   vulnerable=1
-                   report "$file: FAIL: compiled with -f${hard[0]}"
+                   fail "compiled with -f${hard[0]}"
                fi
            else
                if [[ "x${hard[0]}" -eq "xPIE" || "x${hard[0]}" -eq "xpie" ]] ;
                then
-                   if [ $report -gt 2 ];
-                   then
-                       report "$file: PASS: compiled with -f${hard[0]}"
-                   fi
+                   pass "compiled with -f${hard[0]}"
                else
-                   vulnerable=1
-                   report "$file: FAIL: compiled with -f${hard[0]}"
+                   fail "compiled with -f${hard[0]}"
                fi
            fi
        fi
@@ -610,7 +640,9 @@ check_optimization_level ()
     #   GA*GOW:0x052b        0x00000000        NT_GNU_BUILD_ATTRIBUTE_OPEN
     # into:
     #   0x052b
-    eval 'hard=($(grep -e "GOW:" $tmpfile | grep NT_GNU_BUILD_ATTRIBUTE_OPEN | cut -f 2 -d ":" | cut -f 1 -d " " | sort | uniq))'
+    eval 'hard=($(grep -e "GOW:" $tmpfile | grep OPEN | cut -f 2 -d ":" | cut -f 1 -d " " | sort -u))'
+
+    verbose "Optimization Info: ${hard[*]}"
 
     if [ ${#hard[*]} -lt 1 ];
     then
@@ -620,16 +652,13 @@ check_optimization_level ()
        #   <c> DW_AT_producer : (indirect string, offset: 0x0): GNU C11 6.3.1 20161221 (Red Hat 6.3.1-1) -g -O2 -fPIC
        # into:
        #   2
-       eval hard=($(gawk -e 'BEGIN { FPAT = "-O[0123]" } /O[0123]/ { print substr ($1,3,1) ; }' $tmpfile | sort | uniq))
+       eval hard=($(gawk -e 'BEGIN { FPAT = "-O[0123]" } /O[0123]/ { print substr ($1,3,1) ; }' $tmpfile | sort -u))
+
+       verbose "DW_AT_producer records: ${hard[*]}"
 
        if [ ${#hard[*]} -lt 1 ];
        then
-           if [ $report -gt 1 ];
-           then
-               report "$file: MAYBE: does not record -O setting"
-           fi
-
-           vulnerable=1
+           maybe "does not record -O setting"
        else
            local i
 
@@ -638,14 +667,10 @@ check_optimization_level ()
            do
                if [ ${hard[i]} -lt 2 ];
                then
-                   report "$file: FAIL: optimization level of -O${hard[i]} used"
-                   vulnerable=1
+                   fail "optimization level of -O${hard[i]} used"
                    break
                else
-                   if [ $report -gt 2 ];
-                   then
-                       report "$file: PASS: optimization level of -O${hard[i]} used"
-                   fi
+                   pass "optimization level of -O${hard[i]} used"
                fi
                let "i++"
            done
@@ -659,14 +684,10 @@ check_optimization_level ()
            declare -i opt=$(((${hard[i]} & 0x600) >> 9))
            if [ $opt -lt 2 ];
            then
-               report "$file: FAIL: optimization level of -O$opt used"
-               vulnerable=1
+               fail "optimization level of -O$opt used"
                break
            else
-               if [ $report -gt 2 ];
-               then
-                   report "$file: PASS: optimization level of -O$opt used"
-               fi
+               pass "optimization level of -O$opt used"
            fi
            let "i++"
        done
@@ -677,15 +698,14 @@ check_for_bind_now ()
 {
     # Look for the DT_BIND_NOW dynamic tag
     eval hard='($(grep -e BIND_NOW $tmpfile))'
+
+    verbose "BIND_NOW tags: ${hard[*]}"
+
     if [ ${#hard[*]} -lt 1 ];
     then
-       report "$file: FAIL: -Wl,-z,now not used"
-       vulnerable=1
+       fail "-Wl,-z,now not used"
     else
-       if [ $report -gt 2 ];
-       then
-           report "$file: PASS: -Wl,-z,now used"
-       fi
+       pass "-Wl,-z,now used"
     fi
 }
 
@@ -693,15 +713,14 @@ check_for_relro ()
 {
     # Look for the DT_BIND_NOW dynamic tag
     eval hard='($(grep -e GNU_RELRO $tmpfile))'
+
+    verbose "GNU_RELRO tags: ${hard[*]}"
+
     if [ ${#hard[*]} -lt 1 ];
     then
-       report "$file: FAIL: -Wl,-z,relro not used"
-       vulnerable=1
+       fail "-Wl,-z,relro not used"
     else
-       if [ $report -gt 2 ];
-       then
-           report "$file: PASS: -Wl,-z,relro used"
-       fi
+       pass "-Wl,-z,relro used"
     fi
 }
 
This page took 0.061234 seconds and 5 git commands to generate.