1
0
mirror of https://github.com/TomHarte/CLK.git synced 2024-11-19 23:32:28 +00:00

Be more careful as to authorisation.

This commit is contained in:
Thomas Harte 2023-11-02 15:37:59 -04:00
parent 8d0deeb20e
commit 770803b073
2 changed files with 59 additions and 12 deletions

View File

@ -903,9 +903,9 @@ void jump_far(InstructionT &instruction, ContextT &context) {
const Source source_segment = instruction.data_segment(); const Source source_segment = instruction.data_segment();
context.memory.preauthorise_read(source_segment, source_address, sizeof(uint16_t) * 2); context.memory.preauthorise_read(source_segment, source_address, sizeof(uint16_t) * 2);
const uint16_t offset = context.memory.template access<uint16_t, AccessType::Read>(source_segment, source_address); const uint16_t offset = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(source_segment, source_address);
source_address += 2; source_address += 2;
const uint16_t segment =context. memory.template access<uint16_t, AccessType::Read>(source_segment, source_address); const uint16_t segment = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(source_segment, source_address);
context.flow_controller.jump(segment, offset); context.flow_controller.jump(segment, offset);
} }
@ -945,11 +945,12 @@ void ld(
auto source_address = address<uint16_t, AccessType::Read>(instruction, pointer, context); auto source_address = address<uint16_t, AccessType::Read>(instruction, pointer, context);
const Source source_segment = instruction.data_segment(); const Source source_segment = instruction.data_segment();
destination = context.memory.template access<uint16_t, AccessType::Read>(source_segment, source_address); context.memory.preauthorise_read(source_segment, source_address, 4);
destination = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(source_segment, source_address);
source_address += 2; source_address += 2;
switch(selector) { switch(selector) {
case Source::DS: context.registers.ds() = context.memory.template access<uint16_t, AccessType::Read>(source_segment, source_address); break; case Source::DS: context.registers.ds() = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(source_segment, source_address); break;
case Source::ES: context.registers.es() = context.memory.template access<uint16_t, AccessType::Read>(source_segment, source_address); break; case Source::ES: context.registers.es() = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(source_segment, source_address); break;
} }
} }
@ -1919,8 +1920,8 @@ template <
context.memory.preauthorise_read(address, sizeof(uint16_t) * 2); context.memory.preauthorise_read(address, sizeof(uint16_t) * 2);
context.memory.preauthorise_stack_write(sizeof(uint16_t) * 3); context.memory.preauthorise_stack_write(sizeof(uint16_t) * 3);
const uint16_t ip = context.memory.template access<uint16_t, AccessType::Read>(address); const uint16_t ip = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(address);
const uint16_t cs = context.memory.template access<uint16_t, AccessType::Read>(address + 2); const uint16_t cs = context.memory.template access<uint16_t, AccessType::PreauthorisedRead>(address + 2);
auto flags = context.status.get(); auto flags = context.status.get();
Primitive::push<uint16_t, true>(flags, context); Primitive::push<uint16_t, true>(flags, context);

View File

@ -14,6 +14,8 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <unordered_map>
#include <unordered_set>
#include "NSData+dataWithContentsOfGZippedFile.h" #include "NSData+dataWithContentsOfGZippedFile.h"
@ -125,10 +127,32 @@ struct Memory {
} }
// Preauthorisation call-ins. // Preauthorisation call-ins.
void preauthorise_stack_write(uint32_t) {} void preauthorise_stack_write(uint32_t length) {
void preauthorise_stack_read(uint32_t) {} uint16_t sp = registers_.sp_;
void preauthorise_read(InstructionSet::x86::Source, uint16_t, uint32_t) {} while(length--) {
void preauthorise_read(uint16_t, uint32_t) {} --sp;
preauthorise(InstructionSet::x86::Source::SS, sp);
}
}
void preauthorise_stack_read(uint32_t length) {
uint16_t sp = registers_.sp_;
while(length--) {
preauthorise(InstructionSet::x86::Source::SS, sp);
++sp;
}
}
void preauthorise_read(InstructionSet::x86::Source segment, uint16_t start, uint32_t length) {
while(length--) {
preauthorise(segment, start);
++start;
}
}
void preauthorise_read(uint32_t start, uint32_t length) {
while(length--) {
preauthorise(start);
++start;
}
}
// Access call-ins. // Access call-ins.
@ -179,10 +203,26 @@ struct Memory {
Accessed, Accessed,
}; };
std::unordered_set<uint32_t> preauthorisations;
std::unordered_map<uint32_t, Tag> tags; std::unordered_map<uint32_t, Tag> tags;
std::vector<uint8_t> memory; std::vector<uint8_t> memory;
const Registers &registers_; const Registers &registers_;
void preauthorise(uint32_t address) {
preauthorisations.insert(address);
}
void preauthorise(InstructionSet::x86::Source segment, uint16_t address) {
preauthorise((segment_base(segment) + address) & 0xf'ffff);
}
bool test_preauthorisation(uint32_t address) {
auto authorisation = preauthorisations.find(address);
if(authorisation == preauthorisations.end()) {
return false;
}
preauthorisations.erase(authorisation);
return true;
}
uint32_t segment_base(InstructionSet::x86::Source segment) { uint32_t segment_base(InstructionSet::x86::Source segment) {
uint32_t physical_address; uint32_t physical_address;
using Source = InstructionSet::x86::Source; using Source = InstructionSet::x86::Source;
@ -208,6 +248,12 @@ struct Memory {
// to a selector, they're just at an absolute location. // to a selector, they're just at an absolute location.
template <typename IntT, AccessType type> template <typename IntT, AccessType type>
typename ReturnType<IntT, type>::type &access(uint32_t address, Tag tag) { typename ReturnType<IntT, type>::type &access(uint32_t address, Tag tag) {
if constexpr (type == AccessType::PreauthorisedRead || type == AccessType::PreauthorisedWrite) {
if(!test_preauthorisation(address)) {
printf("Non preauthorised access\n");
}
}
// Check for address wraparound // Check for address wraparound
if(address > 0x10'0000 - sizeof(IntT)) { if(address > 0x10'0000 - sizeof(IntT)) {
if constexpr (std::is_same_v<IntT, uint8_t>) { if constexpr (std::is_same_v<IntT, uint8_t>) {
@ -225,7 +271,7 @@ struct Memory {
} }
if(tags.find(address) == tags.end()) { if(tags.find(address) == tags.end()) {
printf("Access to unexpected RAM address"); printf("Access to unexpected RAM address\n");
} }
tags[address] = tag; tags[address] = tag;
return *reinterpret_cast<IntT *>(&memory[address]); return *reinterpret_cast<IntT *>(&memory[address]);