Merge pull request #1935 from Zinebyte/fix/prefixed-syscall-validation
fix(relinker): reject prefixed system-call instructions
This commit is contained in:
commit
300bd79439
|
|
@ -1,5 +1,6 @@
|
|||
#include <relinker/analysis/SyscallScanner.hpp>
|
||||
#include <codegen/IInstructionScanner.hpp>
|
||||
#include <codegen/x86/DecodedInstruction.hpp>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
|
|
@ -26,17 +27,16 @@ void SyscallScanner::ScanCodeSectionForSyscalls(
|
|||
const std::vector<std::uint8_t>& codeSection,
|
||||
const FileByteOffset codeSectionOffset,
|
||||
const FileByteOffset codeSectionSize) {
|
||||
const std::size_t limit = std::min(codeSection.size(), static_cast<std::size_t>(codeSectionSize));
|
||||
|
||||
const auto scanner = Codegen::MakeInstructionScanner();
|
||||
const auto matches = scanner->ScanCodeSection(codeSection, codeSectionOffset, codeSectionSize);
|
||||
|
||||
for (const auto& [Offset, Length] : matches) {
|
||||
const std::size_t i = Offset - codeSectionOffset;
|
||||
const auto opcodeOffset = Codegen::DecodedInstruction{codeSection.data() + i, Length}.OpcodeOffset();
|
||||
|
||||
if (i + 1 < limit) {
|
||||
const std::uint8_t b0 = codeSection[i];
|
||||
const std::uint8_t b1 = codeSection[i + 1];
|
||||
if (opcodeOffset + 1 < Length) {
|
||||
const std::uint8_t b0 = codeSection[i + opcodeOffset];
|
||||
const std::uint8_t b1 = codeSection[i + opcodeOffset + 1];
|
||||
|
||||
const bool isSyscall = (b0 == SYSCALL_BYTE0 && b1 == SYSCALL_BYTE1);
|
||||
const bool isInt80 = (b0 == INT80_BYTE0 && b1 == INT80_BYTE1);
|
||||
|
|
|
|||
|
|
@ -57,6 +57,28 @@ def main():
|
|||
result, output = run_case(relinker, work, "syscall-filter", ["unused-filter=1"], b"\x0f\x05\xc3")
|
||||
assert result.returncode == 2 and "Forbidden syscall instruction" in result.stderr and not output.exists(), result
|
||||
|
||||
forbidden = (
|
||||
("rex-syscall", b"\x48\x0f\x05"),
|
||||
("operand-syscall", b"\x66\x0f\x05"),
|
||||
("address-sysenter", b"\x67\x0f\x34"),
|
||||
("segment-sysenter", b"\x2e\x0f\x34"),
|
||||
("rex-sysret", b"\x48\x0f\x07"),
|
||||
("mixed-sysret", b"\x66\x67\x48\x0f\x07"),
|
||||
("operand-int80", b"\x66\xcd\x80"),
|
||||
("segment-int80", b"\x64\xcd\x80"),
|
||||
)
|
||||
for name, instruction in forbidden:
|
||||
result, output = run_case(relinker, work, name, [], b"\x90" + instruction + b"\xc3")
|
||||
assert result.returncode == 2 and not output.exists(), (name, result.stdout, result.stderr)
|
||||
assert "Forbidden syscall instruction at code offset 0x1801" in result.stderr, (name, result.stderr)
|
||||
|
||||
result, output = run_case(relinker, work, "immediate-decoys", [],
|
||||
b"\x48\xb8\x0f\x05\xcd\x80\x0f\x34\x0f\x07\xc3")
|
||||
assert result.returncode == 0 and output.exists(), (result.stdout, result.stderr)
|
||||
|
||||
result, output = run_case(relinker, work, "skip-prefixed", ["--skip-syscall-check"], b"\x48\x0f\x05\xc3")
|
||||
assert result.returncode == 0 and output.exists(), (result.stdout, result.stderr)
|
||||
|
||||
result, output = run_case(relinker, work, "skip", ["--skip-syscall-check"], b"\x0f\x05\xc3")
|
||||
assert result.returncode == 0 and output.exists(), (result.stdout, result.stderr)
|
||||
second_code = b"\x90" * 16 + b"\xb8\x2a\x00\x00\x00\xc3"
|
||||
|
|
|
|||
Loading…
Reference in New Issue