Skip to content

Commit

Permalink
Add penalty system, add simple penalty to getrandom()
Browse files Browse the repository at this point in the history
  • Loading branch information
fwsGonzo committed Jul 6, 2024
1 parent baea67c commit 1592adb
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 8 deletions.
4 changes: 3 additions & 1 deletion lib/libriscv/linux/system_calls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,7 +935,7 @@ static void syscall_getrandom(Machine<W>& machine)
}
const size_t need = std::min((size_t)g_len, sizeof(buffer));
#if defined(__OpenBSD__)
const ssize_t result = 0; // always success
const ssize_t result = need; // always success
arc4random_buf(buffer, need);
#elif defined(__APPLE__)
const int sec_result = SecRandomCopyBytes(kSecRandomDefault, need, (uint8_t *)buffer);
Expand All @@ -945,6 +945,8 @@ static void syscall_getrandom(Machine<W>& machine)
#endif
if (result > 0) {
machine.copy_to_guest(g_addr, buffer, result);
// getrandom() is a slow syscall, penalize it
machine.penalize(16 * result); // 16 per byte
}
machine.set_result(result);

Expand Down
18 changes: 18 additions & 0 deletions lib/libriscv/machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,24 @@ namespace riscv
set_result(-errno);
}

template <int W>
void Machine<W>::penalize(uint32_t val)
{
if constexpr (timed_vm_calls) {
// TODO: We don't know if we are in a timed VM call or not
// so, ignore this for now.
return;
}
m_penalty += val;
// Penalty consequences are disabled when the max penalty is zero
if (m_penalty_max == 0)
return;
if (m_counter + m_penalty >= m_max_counter) {
throw MachineTimeoutException(MAX_INSTRUCTIONS_REACHED,
"Penalty reached instruction limit", m_penalty);
}
}

template <int W> RISCV_COLD_PATH()
void Machine<W>::timeout_exception(uint64_t max_instr)
{
Expand Down
17 changes: 16 additions & 1 deletion lib/libriscv/machine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,22 @@ namespace riscv
void set_instruction_counter(uint64_t val) noexcept { m_counter = val; }
void increment_counter(uint64_t val) noexcept { m_counter += val; }
void reset_instruction_counter() noexcept { m_counter = 0; }
void penalize(uint64_t val) noexcept;
uint64_t max_instructions() const noexcept { return m_max_counter; }
void set_max_instructions(uint64_t val) noexcept { m_max_counter = val; }
/// @brief Penalty counters are used to prevent guest programs from
/// monopolizing the CPU by executing expensive system calls. The
/// penalty counter is increased each time a system call is executed,
/// and has to be reset manually. A maximum penalty of 0 means that
/// the machine will never stop due to penalties. When the penalty
/// counter overflows, an exception is thrown.
/// @param val The penalty value to add to the counter.
void penalize(uint32_t val);
void set_penalty_counter(uint32_t val) noexcept { m_penalty = val; }
uint32_t penalty_counter() const noexcept { return m_penalty; }
void reset_penalty_counter() noexcept { m_penalty = 0; }
void set_penalty_max(uint32_t val) noexcept { m_penalty_max = val; }
uint32_t penalty_max() const noexcept { return m_penalty_max; }
void reset_penalty_max() noexcept { m_penalty_max = 0; }

CPU<W> cpu;
Memory<W> memory;
Expand Down Expand Up @@ -445,6 +458,8 @@ namespace riscv

uint64_t m_counter = 0;
uint64_t m_max_counter = 0;
uint32_t m_penalty = 0;
uint32_t m_penalty_max = 1024u;
mutable void* m_userdata = nullptr;
mutable printer_func m_printer = default_printer;
mutable printer_func m_debug_printer = default_printer;
Expand Down
6 changes: 0 additions & 6 deletions lib/libriscv/machine_inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,6 @@ inline bool Machine<W>::instruction_limit_reached() const noexcept {
return m_counter >= m_max_counter && m_max_counter != 0;
}

template <int W>
void Machine<W>::penalize(uint64_t val) noexcept
{
m_max_counter = (val >= m_max_counter) ? 0u : m_max_counter - val;
}

template <int W>
template <bool Throw>
inline bool Machine<W>::simulate_with(uint64_t max_instr, uint64_t counter, address_t pc)
Expand Down

0 comments on commit 1592adb

Please sign in to comment.