github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/tools/check-syzos.sh (about) 1 #!/bin/sh 2 # Copyright 2025 syzkaller project authors. All rights reserved. 3 # Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 4 # 5 # This script scans the syz-executor binary for data relocations accesses 6 # within the "guest" ELF section that are problematic for the SYZOS guest 7 # code. 8 # 9 # It uses $TARGETOS and $TARGETARCH to locate the binary and determine the 10 # correct architecture. 11 # 12 13 set -e 14 15 SECTION_TO_CHECK="guest" 16 17 echoerr() { 18 echo "$@" >&2 19 } 20 21 AWK_CMD="awk" 22 if command -v gawk > /dev/null; then 23 AWK_CMD="gawk" 24 fi 25 26 if [ "$TARGETOS" != "linux" ]; then 27 echo "[INFO] TARGETOS is '$TARGETOS', not 'linux'. Skipping check." 28 exit 0 29 fi 30 31 if [ -z "$TARGETARCH" ]; then 32 echoerr "Error: \$TARGETARCH environment variable is not set." 33 exit 1 34 fi 35 36 BINARY="bin/${TARGETOS}_${TARGETARCH}/syz-executor" 37 38 if [ ! -f "$BINARY" ]; then 39 echoerr "Error: Binary not found at '$BINARY'" 40 exit 1 41 fi 42 43 echoerr "--> Analyzing architecture '$TARGETARCH'..." 44 OBJDUMP_CMD="" 45 46 if [ "$TARGETARCH" = "amd64" ]; then 47 ARCH="x86_64" 48 if command -v x86_64-linux-gnu-objdump > /dev/null; then 49 OBJDUMP_CMD="x86_64-linux-gnu-objdump" 50 fi 51 elif [ "$TARGETARCH" = "arm64" ]; then 52 ARCH="aarch64" 53 PATTERNS_TO_FIND='adrp' 54 if command -v aarch64-linux-gnu-objdump > /dev/null; then 55 OBJDUMP_CMD="aarch64-linux-gnu-objdump" 56 fi 57 else 58 echo "[INFO] Unsupported architecture '$TARGETARCH', skipping check." 59 exit 0 60 fi 61 echoerr "--> Detected architecture: $ARCH" 62 63 if [ -z "$OBJDUMP_CMD" ]; then 64 echoerr "--> Arch-specific objdump not found, falling back to generic 'objdump'..." 65 if command -v objdump > /dev/null; then 66 OBJDUMP_CMD="objdump" 67 fi 68 fi 69 70 if [ -z "$OBJDUMP_CMD" ]; then 71 echoerr "Error: Could not find a usable objdump binary." 72 exit 1 73 fi 74 echoerr "--> Using objdump: $OBJDUMP_CMD" 75 76 echoerr "--> Verifying existence of section '$SECTION_TO_CHECK' in '$BINARY'..." 77 if ! "$OBJDUMP_CMD" -h --section="$SECTION_TO_CHECK" "$BINARY" >/dev/null 2>&1; then 78 echo 79 echo "[INFO] Section '$SECTION_TO_CHECK' not found in '$BINARY'. Skipping check." 80 exit 0 81 fi 82 83 echoerr "--> Disassembling section '$SECTION_TO_CHECK' and scanning for problematic instructions..." 84 85 DISASSEMBLY_STATUS=0 86 DISASSEMBLY_OUTPUT=$("$OBJDUMP_CMD" -d --section="$SECTION_TO_CHECK" "$BINARY" 2>/dev/null) || DISASSEMBLY_STATUS=$? 87 88 if [ $DISASSEMBLY_STATUS -ne 0 ]; then 89 echoerr "Error: '$OBJDUMP_CMD' failed to disassemble the '$SECTION_TO_CHECK' section." 90 # Attempt to show the actual error to the user 91 "$OBJDUMP_CMD" -d --section="$SECTION_TO_CHECK" "$BINARY" >/dev/null 92 exit 1 93 fi 94 95 if [ "$TARGETARCH" = "amd64" ]; then 96 echoerr "--> Getting guest section boundaries..." 97 SECTION_INFO=$("$OBJDUMP_CMD" -h "$BINARY" | grep " $SECTION_TO_CHECK ") 98 if [ -z "$SECTION_INFO" ]; then 99 echoerr "Error: Could not get section info for '$SECTION_TO_CHECK'" 100 exit 1 101 fi 102 GUEST_VMA=$(echo "$SECTION_INFO" | $AWK_CMD '{print "0x"$4}') 103 GUEST_SIZE=$(echo "$SECTION_INFO" | $AWK_CMD '{print "0x"$3}') 104 GUEST_START=$(printf "%d" "$GUEST_VMA") 105 GUEST_END=$((GUEST_START + $(printf "%d" "$GUEST_SIZE"))) 106 echoerr "--> Guest section range (hex): [$(printf "0x%x" "$GUEST_START"), $(printf "0x%x" "$GUEST_END"))" 107 108 FOUND_INSTRUCTIONS=$(echo "$DISASSEMBLY_OUTPUT" | { 109 current_func="" 110 problematic_lines="" 111 while IFS= read -r line; do 112 if echo "$line" | grep -q -E '^[0-9a-f]+ <.*>:$'; then 113 current_func=$(echo "$line" | sed -n 's/.*<\(.*\)>:/\1/p') 114 continue 115 fi 116 if echo "$line" | grep -q '(%rip)'; then 117 target_addr_hex=$(echo "$line" | sed -n 's/.*# \([0-9a-f]\+\).*/\1/p') 118 if [ -z "$target_addr_hex" ]; then 119 continue 120 fi 121 target_addr_dec=$(printf "%d" "0x$target_addr_hex") 122 if [ "$target_addr_dec" -lt "$GUEST_START" ] || [ "$target_addr_dec" -gt "$GUEST_END" ]; then 123 if [ -n "$current_func" ]; then 124 problematic_lines="${problematic_lines}In function <${current_func}>:\n" 125 fi 126 problematic_lines="${problematic_lines}\t${line}\n" 127 fi 128 fi 129 done 130 printf "%b" "$problematic_lines" 131 }) 132 else 133 # The original logic for other architectures (e.g. arm64) 134 FOUND_INSTRUCTIONS=$(echo "$DISASSEMBLY_OUTPUT" | $AWK_CMD -v pattern="$PATTERNS_TO_FIND" ' 135 # Match a function header, e.g., "0000000000401136 <my_func>:" 136 /^[0-9a-f]+ <.*>:$/ { 137 match($0, /<.*>/) 138 current_func = substr($0, RSTART, RLENGTH) 139 } 140 # If the line matches the instruction pattern, print the context. 141 $0 ~ pattern { 142 if (current_func) { 143 print "In function " current_func ":" 144 } 145 print "\t" $0 146 } 147 ' || true) 148 fi 149 150 if [ -n "$FOUND_INSTRUCTIONS" ]; then 151 echo 152 echo "------------------------------------------------------------------" 153 echo "[FAIL] Found problematic data access instructions in '$SECTION_TO_CHECK'." 154 echo "The following instructions are likely to cause crashes in SyzOS:" 155 echo "$FOUND_INSTRUCTIONS" | sed 's/^/ /' 156 echo "------------------------------------------------------------------" 157 echo 158 echo "This typically happens when the C compiler emits read-only constants for" 159 echo "zero-initializing structs or for jump tables in switch statements." 160 exit 1 161 else 162 # Do not print anything to stdout unless there's an error. 163 echoerr 164 echoerr "[OK] No problematic data access instructions found in '$SECTION_TO_CHECK'." 165 exit 0 166 fi