This file is indexed.

/usr/src/linux-source-3.13.0/debian/scripts/retpoline-extract-one is in linux-source-3.13.0 3.13.0-160.210.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#!/bin/bash

exec </dev/null

object="$1"
src="$2"
bit16="$3"

SECTION=".discard.retpoline_safe"

# Form an associative lookup for the symbol numbers in the ELF symbol table.
# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
__symbolmap_init()
{
	readelf -W --syms "$1" |
		awk '($4 == "SECTION" && $1 ~ /^[0-9]*:/) { printf("%08x %08x\n", int($1), int($7)); }' | \
	while read symbol_num section_num
	do
		echo "symbolmap_$symbol_num='$section_num'"
	done
}
symbolmap_init()
{
	eval $(__symbolmap_init "$1")
}
symbolmap()
{
	eval RET="\$symbolmap_$1"
	if [ "$RET" = '' ]; then
		echo "symbolmap: $1: invalid section" 1>&2
		exit 1
	fi
}

# Form an associative lookup for the section numbers in the ELF symbol table.
# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
__sectionmap_init()
{
	readelf -W --headers "$1" | \
		awk '
						{ sub("\\[", ""); sub("\\]", ""); }
                        ($1 ~ /^[0-9][0-9]*/)   { printf("%08x %s %s %s\n", int($1), $2, $3, $4); }
		' | \
	{
		while read section_num section_name section_type section_vma
		do
			echo "sectionmap_$section_num='$section_name'"
			echo "sectionvma_$section_num='$section_vma'"
			case "$section_type" in
			REL|RELA) section_relocation="$section_type" ;;
			esac
		done
		echo "section_relocation='$section_relocation'"
	}
}
sectionmap_init()
{
	eval $(__sectionmap_init "$1")
}
sectionmap()
{
	eval RET="\$sectionmap_$1"
	if [ "$RET" = '' ]; then
		echo "sectionmap: $1: invalid section" 1>&2
		exit 1
	fi
}
sectionvma()
{
	eval RET="\$sectionvma_$1"
	if [ "$RET" = '' ]; then
		echo "sectionvma: $1: invalid section" 1>&2
		exit 1
	fi
}

# Read and parse the hex-dump output.
hex="[0-9a-f]"
hex_8="$hex$hex$hex$hex$hex$hex$hex$hex"
hexspc="[0-9a-f ]"
hexspc_8="$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc$hexspc"

raw32()
{
	readelf --hex-dump "$2" "$1" 2>/dev/null |
	sed \
		-e '/^Hex/d' -e '/^$/d' -e '/^ *NOTE/d' \
		-e 's/  *[^ ][^ ]*  *\('"$hex_8"'\) \('"$hexspc_8"'\) \('"$hexspc_8"'\) \('"$hexspc_8"'\) .*/\1 \2 \3 \4 /' \
		-e 's/\('"$hex$hex"'\)\('"$hex$hex"'\)\('"$hex$hex"'\)\('"$hex$hex"'\) /\4\3\2\1 /g' \
		-e 's/ $//g' -e 's/ /\n/g'
}
#-e 's/\([^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ]\) \([^ ][^ ][^ ][^ ][^ ][^ ][^ ][^ ]\) /\2\1 /g' \

rela()
{
	#file="$(basename "$1")"
	file="$1"

	# Read relocation information for a 64bit binary.  Each relocation entry
	# is 3 long longs so we collect 6 quads here.  Note that the dump is in
	# listed in increasing byte order not withstanding the quad split.
	#
	# The record says to take the value of <symbol> add <symbol offset> and
	# shove that into <write offset> in the segment of the <symbol>.
	#
	# Format:
	#  <write offset>	64 bits
	#  <symbol number>	32 bits
	#  <relocation type>	32 bits
	#  <symbol offset>	64 bits
	raw32 "$1" ".rela$SECTION" | \
	{
		a1=''; a2=''; a3=''; a4=''; a5=''
		while read a6
		do
			[ "$a1" = '' ] && { a1="$a6"; continue; }
			[ "$a2" = '' ] && { a2="$a6"; continue; }
			[ "$a3" = '' ] && { a3="$a6"; continue; }
			[ "$a4" = '' ] && { a4="$a6"; continue; }
			[ "$a5" = '' ] && { a5="$a6"; continue; }

			#echo ">$a1< >$a2< >$a3< >$a4< >$a5< >$a6<" 1>&2
			#echo "type<$a3> symbol<$a4> offset<$a2$a1> addr<$a6a5>" 1>&2

			symbolmap "$a4"; section_num="$RET"
			#echo "section_num<$section_num>" 1>&2

			sectionmap "$section_num"; section="$RET"
			sectionvma "$section_num"; vma="$RET"
			#echo "section<$section> vma<$vma>" 1>&2

			# Adjust the segment addressing by the segment offset.
			printf -v addr "%u" "0x$a6$a5"
			printf -v vma "%u" "0x$vma"
			let offset="$addr + $vma"
			printf -v offset "%x" "$offset"

			echo "$file-$section-$offset"

			a1=''; a2=''; a3=''; a4=''; a5=''
		done
	} | sed -e 's/-00*\([0-9a-f]\)/-\1/'
}

# Form an associative lookup for the raw contents for an ELF section.
# Uses 8 character 0 expanded hexadecimal key for ease of consumption.
contentmap_init()
{
	raw32 "$1" "$2" >"$tmp.cm"
	let offset=0
	while read value
	do
		printf -v offset_hex "%08x" $offset
		eval contentmap_$offset_hex=\'$value\'

		let offset="$offset + 4"
	done <"$tmp.cm"
	rm -f "$tmp.cm"
}
contentmap()
{
	eval RET="\$contentmap_$1"
	if [ "$RET" = '' ]; then
		echo "contentmap: $1: invalid offset" 1>&2
		exit 1
	fi
}

rel()
{
	# Load up the current contents of the $SECTION segment
	# as the offsets (see below) are recorded there and we will need
	# those to calculate the actuall address.
	contentmap_init "$1" "$SECTION"

	#file="$(basename "$1")"
	file="$1"

	# Read relocation information for a 32bit binary.  Each relocation entry
	# is 3 longs so we collect 3 quads here.  Note that the dump is in
	# listed in increasing byte order not withstanding the quad split.
	#
	# The record says to take the value of <symbol> and add that to the
	# existing contents of <write offset> in the segment of the <symbol>.
	#
	# Format:
	#  <write offset>	32 bits
	#  <symbol number>	24 bits
	#  <relocation type>	 8 bits
	raw32 "$1" ".rel$SECTION" | \
	{
		a1=''
		while read a2
		do
			[ "$a1" = '' ] && { a1="$a2"; continue; }

			#echo ">$a1< >$a2<"
			contentmap "$a1"; offset="$RET"
			symbolmap "00${a2%??}"; section_num="$RET"

			sectionmap "$section_num"; section="$RET"
			sectionvma "$section_num"; vma="$RET"
			#echo ">$a1< >$a2< >$offset< >$section<"

			echo "$file-$section-$offset"

			a1=''
		done
	} | sed -e 's/-00*\([0-9a-f]\)/-\1/'
}

tmp="/tmp/retpoline-extract.$$"

disassemble()
{
	local object="$1"
	local src="$2"
	local options="$3"
	local selector="$4"

	objdump $options --disassemble --no-show-raw-insn "$object" | \
	awk -F' ' '
		BEGIN				{ file="'"$object"'"; src="'"$src"'"; }
		/Disassembly of section/        { segment=$4; sub(":", "", segment); }
		/^[0-9a-f][0-9a-f]* <.*>:/      { tag=$0; sub(".*<", "", tag); sub(">.*", "", tag); }
		$0 ~ /(call|jmp)q?  *\*0x[0-9a-f]*\(%rip\)/ {
			next
		}
		$0 ~ /(call|jmp)q?  *\*.*%/ {
			sub(":", "", $1);
			if ('"$selector"') {
				offset=$1
				$1=tag
				print(file "-" segment "-" offset " " src " " segment " " $0);
			}
		}
	'
}

# Accumulate potentially vunerable indirect call/jmp sequences.  We do this
# by examining the raw disassembly for affected forms, recording the location
# of each.
case "$bit16" in
'')	disassemble "$object" "$src" '' 'segment != ".init.text"' ;;
*)	disassemble "$object" "$src" '--disassembler-options=i8086' 'segment != ".init.text" && segment != ".text32" && segment != ".text64"'
	disassemble "$object" "$src" '--disassembler-options=i386' 'segment == ".text32"'
	disassemble "$object" "$src" '--disassembler-options=x86-64' 'segment == ".text64"'
	;;
esac | sort -k 1b,1 >"$object.ur-detected"
[ ! -s "$object.ur-detected" ] && rm -f "$object.ur-detected"

# Load up the symbol table and section mappings.
symbolmap_init "$object"
sectionmap_init "$object"

# Accumulate annotated safe indirect call/jmp sequences.  We do this by examining
# the $SECTION sections (and their associated relocation information),
# each entry represents the address of an instruction which has been marked
# as ok.
case "$section_relocation" in
REL)	rel "$object" ;;
RELA)	rela "$object" ;;
esac | sort -k 1b,1 >"$object.ur-safe"
[ ! -s "$object.ur-safe" ] && rm -f "$object.ur-safe"

# We will perform the below join on the summarised and sorted fragments
# formed above.  This is performed in retpoline-check.
#join -v 1 -j 1 "$tmp.extracted" "$tmp.safe" | sed -s 's/[^ ]*  *//'

rm -f "$tmp".*