blob: 163753f03dc639f8198218effa5ebd0c44396614 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
|
#!/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
}
AWK_CMD="awk"
if command -v gawk > /dev/null; then
AWK_CMD="gawk"
fi
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"
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 problematic instructions..."
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
if [ "$TARGETARCH" = "amd64" ]; then
echoerr "--> Getting guest section boundaries..."
SECTION_INFO=$("$OBJDUMP_CMD" -h "$BINARY" | grep " $SECTION_TO_CHECK ")
if [ -z "$SECTION_INFO" ]; then
echoerr "Error: Could not get section info for '$SECTION_TO_CHECK'"
exit 1
fi
GUEST_VMA=$(echo "$SECTION_INFO" | $AWK_CMD '{print "0x"$4}')
GUEST_SIZE=$(echo "$SECTION_INFO" | $AWK_CMD '{print "0x"$3}')
GUEST_START=$(printf "%d" "$GUEST_VMA")
GUEST_END=$((GUEST_START + $(printf "%d" "$GUEST_SIZE")))
echoerr "--> Guest section range (hex): [$(printf "0x%x" "$GUEST_START"), $(printf "0x%x" "$GUEST_END"))"
FOUND_INSTRUCTIONS=$(echo "$DISASSEMBLY_OUTPUT" | {
current_func=""
problematic_lines=""
while IFS= read -r line; do
if echo "$line" | grep -q -E '^[0-9a-f]+ <.*>:$'; then
current_func=$(echo "$line" | sed -n 's/.*<\(.*\)>:/\1/p')
continue
fi
if echo "$line" | grep -q '(%rip)'; then
target_addr_hex=$(echo "$line" | sed -n 's/.*# \([0-9a-f]\+\).*/\1/p')
if [ -z "$target_addr_hex" ]; then
continue
fi
target_addr_dec=$(printf "%d" "0x$target_addr_hex")
if [ "$target_addr_dec" -lt "$GUEST_START" ] || [ "$target_addr_dec" -gt "$GUEST_END" ]; then
if [ -n "$current_func" ]; then
problematic_lines="${problematic_lines}In function <${current_func}>:\n"
fi
problematic_lines="${problematic_lines}\t${line}\n"
fi
fi
done
printf "%b" "$problematic_lines"
})
else
# The original logic for other architectures (e.g. arm64)
FOUND_INSTRUCTIONS=$(echo "$DISASSEMBLY_OUTPUT" | $AWK_CMD -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)
fi
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
|