Add non-threadsafe process callbacks

This commit is contained in:
Maurice Heumann 2022-12-27 09:36:46 +01:00
parent a6e0d7de47
commit 65417e3e7a
6 changed files with 206 additions and 21 deletions

View File

@ -29,6 +29,10 @@ target_link_libraries(driver
shared shared
) )
target_compile_options(driver PRIVATE
"/Zc:threadSafeInit-"
)
target_link_options(driver PRIVATE target_link_options(driver PRIVATE
"/IGNORE:4210" "/IGNORE:4210"
) )

View File

@ -5,6 +5,7 @@
#include "exception.hpp" #include "exception.hpp"
#include "hypervisor.hpp" #include "hypervisor.hpp"
#include "globals.hpp" #include "globals.hpp"
#include "process_callback.hpp"
#define DOS_DEV_NAME L"\\DosDevices\\HelloDev" #define DOS_DEV_NAME L"\\DosDevices\\HelloDev"
#define DEV_NAME L"\\Device\\HelloDev" #define DEV_NAME L"\\Device\\HelloDev"
@ -16,8 +17,13 @@ public:
: sleep_callback_([this](const sleep_callback::type type) : sleep_callback_([this](const sleep_callback::type type)
{ {
this->sleep_notification(type); this->sleep_notification(type);
}) }),
, irp_(driver_object, DEV_NAME, DOS_DEV_NAME) process_callback_(
[this](const HANDLE parent_id, const HANDLE process_id, const process_callback::type type)
{
this->process_notification(parent_id, process_id, type);
}),
irp_(driver_object, DEV_NAME, DOS_DEV_NAME)
{ {
debug_log("Driver started\n"); debug_log("Driver started\n");
} }
@ -41,6 +47,7 @@ private:
bool hypervisor_was_enabled_{false}; bool hypervisor_was_enabled_{false};
hypervisor hypervisor_{}; hypervisor hypervisor_{};
sleep_callback sleep_callback_{}; sleep_callback sleep_callback_{};
process_callback::scoped_process_callback process_callback_{};
irp irp_{}; irp irp_{};
void sleep_notification(const sleep_callback::type type) void sleep_notification(const sleep_callback::type type)
@ -58,6 +65,19 @@ private:
this->hypervisor_.enable(); this->hypervisor_.enable();
} }
} }
void process_notification(HANDLE /*parent_id*/, const HANDLE process_id, const process_callback::type type)
{
if (type == process_callback::type::create)
{
debug_log("Created process: %X\n", process_id);
}
if (type == process_callback::type::destroy)
{
debug_log("Destroyed process: %X\n", process_id);
}
}
}; };
global_driver* global_driver_instance{nullptr}; global_driver* global_driver_instance{nullptr};

View File

@ -115,7 +115,7 @@ int atexit(const globals::destructor destructor)
try try
{ {
globals::destructors->push_back(destructor); globals::destructors->push_front(destructor);
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {

View File

@ -168,29 +168,45 @@ namespace utils
T& push_back(const T& obj) T& push_back(const T& obj)
{ {
auto& entry = this->add_uninitialized_entry(); auto& entry = this->add_uninitialized_entry_back();
new(&entry) T(obj); new(&entry) T(obj);
return entry; return entry;
} }
T& push_back(T&& obj) T& push_back(T&& obj)
{ {
auto& entry = this->add_uninitialized_entry(); auto& entry = this->add_uninitialized_entry_back();
new(&entry) T(std::move(obj)); new(&entry) T(std::move(obj));
return entry; return entry;
} }
template <typename... Args> template <typename... Args>
T& emplace_back(Args&&... args) T& emplace_back(Args&&... args)
{ {
auto& entry = this->add_uninitialized_entry(); auto& entry = this->add_uninitialized_entry_back();
new(&entry) T(std::forward<Args>(args)...); new(&entry) T(std::forward<Args>(args)...);
return entry;
}
T& push_front(const T& obj)
{
auto& entry = this->add_uninitialized_entry_front();
new(&entry) T(obj);
return entry;
}
T& push_front(T&& obj)
{
auto& entry = this->add_uninitialized_entry_front();
new(&entry) T(std::move(obj));
return entry;
}
template <typename... Args>
T& emplace_front(Args&&... args)
{
auto& entry = this->add_uninitialized_entry_front();
new(&entry) T(std::forward<Args>(args)...);
return entry; return entry;
} }
@ -271,6 +287,30 @@ namespace utils
return {}; return {};
} }
void erase(T& entry)
{
auto** insertion_point = &this->entries_;
while (*insertion_point)
{
if ((*insertion_point)->entry != &entry)
{
insertion_point = &(*insertion_point)->next;
continue;
}
auto* list_entry = *insertion_point;
*insertion_point = list_entry->next;
list_entry->entry->~T();
this->object_allocator_.free(list_entry->entry_base);
this->list_allocator_.free(list_entry->this_base);
return;
}
throw std::runtime_error("Bad entry");
}
iterator erase(iterator iterator) iterator erase(iterator iterator)
{ {
auto* list_entry = iterator.get_entry(); auto* list_entry = iterator.get_entry();
@ -350,19 +390,12 @@ namespace utils
destructor.cancel(); destructor.cancel();
} }
list_entry& create_uninitialized_list_entry()
T& add_uninitialized_entry()
{ {
void* list_base = {}; void* list_base = {};
void* entry_base = {}; void* entry_base = {};
this->allocate_entry(list_base, entry_base); this->allocate_entry(list_base, entry_base);
auto** insertion_point = &this->entries_;
while (*insertion_point)
{
insertion_point = &(*insertion_point)->next;
}
auto* obj = align_pointer<T>(entry_base); auto* obj = align_pointer<T>(entry_base);
auto* entry = align_pointer<list_entry>(list_base); auto* entry = align_pointer<list_entry>(list_base);
@ -371,9 +404,30 @@ namespace utils
entry->next = nullptr; entry->next = nullptr;
entry->entry = obj; entry->entry = obj;
*insertion_point = entry; return *entry;
}
return *obj; T& add_uninitialized_entry_back()
{
auto** insertion_point = &this->entries_;
while (*insertion_point)
{
insertion_point = &(*insertion_point)->next;
}
auto& entry = this->create_uninitialized_list_entry();
*insertion_point = &entry;
return *entry.entry;
}
T& add_uninitialized_entry_front()
{
auto& entry = this->create_uninitialized_list_entry();
entry.next = this->entries_;
this->entries_ = &entry;
return *entry.entry;
} }
}; };
} }

View File

@ -0,0 +1,65 @@
#include "std_include.hpp"
#include "process_callback.hpp"
#include "list.hpp"
#include "logging.hpp"
namespace process_callback
{
namespace
{
utils::list<callback_function>& get_callback_list()
{
static utils::list<callback_function> list{};
return list;
}
void process_notification_callback(const HANDLE parent_id, const HANDLE process_id, const BOOLEAN create)
{
const auto& list = get_callback_list();
for (const auto& callback : list)
{
callback(parent_id, process_id, create == FALSE ? type::destroy : type::create);
}
}
class process_notifier
{
public:
process_notifier()
: added_(PsSetCreateProcessNotifyRoutine(process_notification_callback, FALSE) == STATUS_SUCCESS)
{
get_callback_list();
if (!added_)
{
debug_log("Failed to register process notification callback\n");
}
}
~process_notifier()
{
if (this->added_)
{
PsSetCreateProcessNotifyRoutine(process_notification_callback, TRUE);
}
}
private:
bool added_{};
};
}
void* add(callback_function callback)
{
static process_notifier _;
return &get_callback_list().push_back(std::move(callback));
}
void remove(void* handle)
{
if (handle)
{
get_callback_list().erase(*static_cast<callback_function*>(handle));
}
}
}

View File

@ -0,0 +1,42 @@
#pragma once
#include "functional.hpp"
namespace process_callback
{
enum class type
{
create,
destroy,
};
using callback = void(HANDLE parent_id, HANDLE process_id, type type);
using callback_function = std::function<callback>;
void* add(callback_function callback);
void remove(void* handle);
class scoped_process_callback
{
public:
scoped_process_callback() = default;
scoped_process_callback(callback_function function)
: handle_(add(std::move(function)))
{
}
~scoped_process_callback()
{
remove(this->handle_);
}
scoped_process_callback(scoped_process_callback&& obj) noexcept = delete;
scoped_process_callback& operator=(scoped_process_callback&& obj) noexcept = delete;
scoped_process_callback(const scoped_process_callback& obj) = delete;
scoped_process_callback& operator=(const scoped_process_callback& obj) = delete;
private:
void* handle_{};
};
}