Skip to content

Commit

Permalink
Fix bounds checking
Browse files Browse the repository at this point in the history
Signed-off-by: Alan Jowett <[email protected]>
  • Loading branch information
Alan Jowett committed Oct 16, 2024
1 parent 0e15c81 commit fb607f1
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 10 deletions.
49 changes: 39 additions & 10 deletions libfuzzer/libfuzz_harness.cc
Original file line number Diff line number Diff line change
Expand Up @@ -248,19 +248,21 @@ std::string g_error_message;
*/
int capture_printf(FILE* stream, const char* format, ...)
{
if (!stream) {
return 0;
}
if (!format) {
return 0;
}
// Format the message and append it to g_error_message.

UNREFERENCED_PARAMETER(stream);

va_list args;
va_start(args, format);
int ret = vfprintf(stream, format, args);
char buffer[1024];
int ret = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);

g_error_message += format;
if (ret < 0) {
return ret;
}

g_error_message += buffer;

return ret;
}
Expand Down Expand Up @@ -532,6 +534,32 @@ ubpf_context_from(std::vector<uint8_t>& memory, std::vector<uint8_t>& ubpf_stack
return context;
}

/**
* @brief Function to check if the given address and size are within the bounds of the memory or stack.
*
* @param[in] context The context passed to ubpf_register_data_bounds_check.
* @param[in] addr The address to check.
* @param[in] size The size of the memory to check.
* @return true The address and size are within the bounds of the memory or stack.
* @return false The address and size are not within the bounds of the memory or stack.
*/
bool bounds_check(void* context, uint64_t addr, uint64_t size)
{
ubpf_context_t* ubpf_context = reinterpret_cast<ubpf_context_t*>(context);

// Check if the lower bound of the address is within the bounds of the memory or stack.
if (ubpf_classify_address(ubpf_context, addr) == address_type_t::Unknown) {
return false;
}

// Check if the upper bound of the address is within the bounds of the memory or stack.
if (ubpf_classify_address(ubpf_context, addr + size - 1) == address_type_t::Unknown) {
return false;
}

return false;
}

/**
* @brief Invoke the ubpf interpreter with the given program code and input memory.
*
Expand Down Expand Up @@ -559,9 +587,10 @@ call_ubpf_interpreter(
}

ubpf_register_debug_fn(vm.get(), &context, ubpf_debug_function);
ubpf_register_data_bounds_check(vm.get(), &context, bounds_check);

// Execute the program using the input memory.
if (ubpf_exec_ex(vm.get(), &context, 0, &interpreter_result, ubpf_stack.data(), ubpf_stack.size()) != 0) {
if (ubpf_exec_ex(vm.get(), &context, sizeof(context), &interpreter_result, ubpf_stack.data(), ubpf_stack.size()) != 0) {
throw std::runtime_error("Failed to execute program with error: " + g_error_message);
}

Expand Down Expand Up @@ -603,7 +632,7 @@ call_ubpf_jit(
throw std::runtime_error("Failed to compile program with error: " + std::string(error_message));
}

jit_result = fn(&context, 0, ubpf_stack.data(), ubpf_stack.size());
jit_result = fn(&context, sizeof(context), ubpf_stack.data(), ubpf_stack.size());

// Compilation succeeded.
return true;
Expand Down
8 changes: 8 additions & 0 deletions vm/inc/ubpf.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,14 @@ extern "C"
int
ubpf_register_data_relocation(struct ubpf_vm* vm, void* user_context, ubpf_data_relocation relocation);

/**
* @brief Function that is called by the VM to check if a memory access is within bounds.
*
* @param[in] context The user context that was passed to ubpf_register_data_bounds_check.
* @param[in] addr The address to check.
* @param[in] size The size of the memory access.
* @return bool True if the memory access is within bounds, false otherwise.
*/
typedef bool (*ubpf_bounds_check)(void* context, uint64_t addr, uint64_t size);

/**
Expand Down

0 comments on commit fb607f1

Please sign in to comment.