Skip to content

Commit 5a9f29d

Browse files
committed
add reader validation for .rela.plt and DT_PLT* consistency
1 parent f4e824a commit 5a9f29d

1 file changed

Lines changed: 16 additions & 3 deletions

File tree

lib/caotral/binary/elf/reader.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ def validate_relocations
143143
rela_dyn = @context.sections.find { |section| section.section_name.to_s == ".rela.dyn" }
144144
pt_load = @context.program_headers.find { |ph| ph.type == :LOAD }
145145
dynamic = @context.sections.find { |section| section.section_name.to_s == ".dynamic" }
146+
rela_plt = @context.sections.find { |section| section.section_name.to_s == ".rela.plt" }
147+
failed_messages = []
146148
unless rela_dyn && pt_load && dynamic
147149
data = [
148150
rela_dyn ? nil : ".rela.dyn section",
@@ -160,15 +162,25 @@ def validate_relocations
160162
val = 24 if dyn.rela_ent?
161163
next unless val
162164
if dyn.un != val
163-
raise Caotral::Binary::ELF::Error, "Invalid dynamic section entry: expected #{val}, got #{dyn.un}"
165+
failed_messages << "Invalid dynamic section entry: expected #{val}, got #{dyn.un}"
164166
end
165167
end
166168

167169
valid_range = (pt_load.vaddr...(pt_load.vaddr + pt_load.memsz))
168170
unless rela_dyn.body.all? { |rel| valid_range.include?(rel.offset) }
169-
raise Caotral::Binary::ELF::Error, "Relocation entries in .rela.dyn exceed LOAD segment range"
171+
failed_messages << "Relocation entries in .rela.dyn exceed LOAD segment range"
170172
end
171173

174+
if rela_plt
175+
dynamic.body.find { |dt| dt.jmp_rel? }&.un == rela_plt.header.addr || failed_messages << "Dynamic section entry DT_JMPREL does not match .rela.plt address"
176+
dynamic.body.find { |dt| dt.plt_rel_size? }&.un == rela_plt.header.size || failed_messages << "Dynamic section entry DT_PLTRELSZ does not match .rela.plt size"
177+
dynamic.body.find { |dt| dt.plt_rel? }&.un == 7 || failed_messages << "Dynamic section entry DT_PLTREL does not indicate RELA type"
178+
rela_plt.body.each do |rel|
179+
valid_range.include?(rel.offset) || failed_messages << "Relocation entries in .rela.plt exceed LOAD segment range"
180+
rela_type_name(rel.type) == :AMD64_JUMP_SLOT || failed_messages << "Unexpected relocation type in .rela.plt: #{rel.type_name}"
181+
end
182+
end
183+
raise Caotral::Binary::ELF::Error, failed_messages.join("\n") unless failed_messages.empty?
172184
true
173185
end
174186

@@ -182,7 +194,8 @@ def decision(input)
182194
end
183195
end
184196

185-
def type(num) = Caotral::Binary::ELF::SectionHeader::SHT_BY_VALUE.fetch(num, :unknown)
197+
def section_type_name(num) = Caotral::Binary::ELF::SectionHeader::SHT_BY_VALUE.fetch(num, :unknown)
198+
def rela_type_name(num) = Caotral::Binary::ELF::Section::Rel::TYPES_BY_V.fetch(num, :unknown)
186199
end
187200
end
188201
end

0 commit comments

Comments
 (0)