aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2025-09-10 13:57:41 +0200
committerAlexander Potapenko <glider@google.com>2025-09-11 08:49:06 +0000
commit4d84111421bcf66c236e6ef9af5846514e66653b (patch)
treee33d854a49111de2087aa03c113525d6984a0e12 /tools
parentfdeaa69b728b8c7a429af7101cdd788f1dc9b916 (diff)
tools: add check-syzos.sh
As shown in https://github.com/google/syzkaller/issues/5565, SYZOS code in the `guest` section cannot reference global data, because it is relocated into the guest memory. While arm64 executor has a dynamic check for data accesses, it is virtually impossible to do the same on x86 without implementing an x86 disassembler. Instead of doing so, introduce a build-time script that will detect instructions referencing global data on a best-effort basis.
Diffstat (limited to 'tools')
-rwxr-xr-xtools/check-syzos.sh122
1 files changed, 122 insertions, 0 deletions
diff --git a/tools/check-syzos.sh b/tools/check-syzos.sh
new file mode 100755
index 000000000..2b8a72a60
--- /dev/null
+++ b/tools/check-syzos.sh
@@ -0,0 +1,122 @@
+#!/bin/sh
+# Copyright 2025 syzkaller project authors. All rights reserved.
+# Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+#
+# This script scans the syz-executor binary for data relocations accesses
+# within the "guest" ELF section that are problematic for the SYZOS guest
+# code.
+#
+# It uses $TARGETOS and $TARGETARCH to locate the binary and determine the
+# correct architecture.
+#
+
+set -e
+
+SECTION_TO_CHECK="guest"
+
+echoerr() {
+ echo "$@" >&2
+}
+
+if [ "$TARGETOS" != "linux" ]; then
+ echo "[INFO] TARGETOS is '$TARGETOS', not 'linux'. Skipping check."
+ exit 0
+fi
+
+if [ -z "$TARGETARCH" ]; then
+ echoerr "Error: \$TARGETARCH environment variable is not set."
+ exit 1
+fi
+
+BINARY="bin/${TARGETOS}_${TARGETARCH}/syz-executor"
+
+if [ ! -f "$BINARY" ]; then
+ echoerr "Error: Binary not found at '$BINARY'"
+ exit 1
+fi
+
+echoerr "--> Analyzing architecture '$TARGETARCH'..."
+OBJDUMP_CMD=""
+
+if [ "$TARGETARCH" = "amd64" ]; then
+ ARCH="x86_64"
+ PATTERNS_TO_FIND='\\(%rip\\)'
+ if command -v x86_64-linux-gnu-objdump > /dev/null; then
+ OBJDUMP_CMD="x86_64-linux-gnu-objdump"
+ fi
+elif [ "$TARGETARCH" = "arm64" ]; then
+ ARCH="aarch64"
+ PATTERNS_TO_FIND='adrp'
+ if command -v aarch64-linux-gnu-objdump > /dev/null; then
+ OBJDUMP_CMD="aarch64-linux-gnu-objdump"
+ fi
+else
+ echo "[INFO] Unsupported architecture '$TARGETARCH', skipping check."
+ exit 0
+fi
+echoerr "--> Detected architecture: $ARCH"
+
+if [ -z "$OBJDUMP_CMD" ]; then
+ echoerr "--> Arch-specific objdump not found, falling back to generic 'objdump'..."
+ if command -v objdump > /dev/null; then
+ OBJDUMP_CMD="objdump"
+ fi
+fi
+
+if [ -z "$OBJDUMP_CMD" ]; then
+ echoerr "Error: Could not find a usable objdump binary."
+ exit 1
+fi
+echoerr "--> Using objdump: $OBJDUMP_CMD"
+
+echoerr "--> Verifying existence of section '$SECTION_TO_CHECK' in '$BINARY'..."
+if ! "$OBJDUMP_CMD" -h --section="$SECTION_TO_CHECK" "$BINARY" >/dev/null 2>&1; then
+ echo
+ echo "[INFO] Section '$SECTION_TO_CHECK' not found in '$BINARY'. Skipping check."
+ exit 0
+fi
+
+echoerr "--> Disassembling section '$SECTION_TO_CHECK' and scanning for patterns ('$PATTERNS_TO_FIND')..."
+
+DISASSEMBLY_STATUS=0
+DISASSEMBLY_OUTPUT=$("$OBJDUMP_CMD" -d --section="$SECTION_TO_CHECK" "$BINARY" 2>/dev/null) || DISASSEMBLY_STATUS=$?
+
+if [ $DISASSEMBLY_STATUS -ne 0 ]; then
+ echoerr "Error: '$OBJDUMP_CMD' failed to disassemble the '$SECTION_TO_CHECK' section."
+ # Attempt to show the actual error to the user
+ "$OBJDUMP_CMD" -d --section="$SECTION_TO_CHECK" "$BINARY" >/dev/null
+ exit 1
+fi
+
+FOUND_INSTRUCTIONS=$(echo "$DISASSEMBLY_OUTPUT" | awk -v pattern="$PATTERNS_TO_FIND" '
+ # Match a function header, e.g., "0000000000401136 <my_func>:"
+ /^[0-9a-f]+ <.*>:$/ {
+ match($0, /<.*>/)
+ current_func = substr($0, RSTART, RLENGTH)
+ }
+ # If the line matches the instruction pattern, print the context.
+ $0 ~ pattern {
+ if (current_func) {
+ print "In function " current_func ":"
+ }
+ print "\t" $0
+ }
+' || true)
+
+if [ -n "$FOUND_INSTRUCTIONS" ]; then
+ echo
+ echo "------------------------------------------------------------------"
+ echo "[FAIL] Found problematic data access instructions in '$SECTION_TO_CHECK'."
+ echo "The following instructions are likely to cause crashes in SyzOS:"
+ echo "$FOUND_INSTRUCTIONS" | sed 's/^/ /'
+ echo "------------------------------------------------------------------"
+ echo
+ echo "This typically happens when the C compiler emits read-only constants for"
+ echo "zero-initializing structs or for jump tables in switch statements."
+ exit 1
+else
+ # Do not print anything to stdout unless there's an error.
+ echoerr
+ echoerr "[OK] No problematic data access instructions found in '$SECTION_TO_CHECK'."
+ exit 0
+fi