kernel/object: Amend handle types to distinguish between readable and writable events

Two kernel object should absolutely never have the same handle ID type.
This can cause incorrect behavior when it comes to retrieving object
types from the handle table. In this case it allows converting a
WritableEvent into a ReadableEvent and vice-versa, which is undefined
behavior, since the object types are not the same.

This also corrects ClearEvent() to check both kernel types like the
kernel itself does.
This commit is contained in:
Lioncash 2018-12-03 22:50:16 -05:00
parent adc4d332fc
commit 5eb057f422
6 changed files with 20 additions and 11 deletions

View file

@ -13,7 +13,7 @@ Object::~Object() = default;
bool Object::IsWaitable() const { bool Object::IsWaitable() const {
switch (GetHandleType()) { switch (GetHandleType()) {
case HandleType::Event: case HandleType::ReadableEvent:
case HandleType::Thread: case HandleType::Thread:
case HandleType::Timer: case HandleType::Timer:
case HandleType::ServerPort: case HandleType::ServerPort:
@ -21,6 +21,7 @@ bool Object::IsWaitable() const {
return true; return true;
case HandleType::Unknown: case HandleType::Unknown:
case HandleType::WritableEvent:
case HandleType::SharedMemory: case HandleType::SharedMemory:
case HandleType::Process: case HandleType::Process:
case HandleType::AddressArbiter: case HandleType::AddressArbiter:

View file

@ -19,7 +19,8 @@ using Handle = u32;
enum class HandleType : u32 { enum class HandleType : u32 {
Unknown, Unknown,
Event, WritableEvent,
ReadableEvent,
SharedMemory, SharedMemory,
Thread, Thread,
Process, Process,

View file

@ -29,7 +29,7 @@ public:
return reset_type; return reset_type;
} }
static const HandleType HANDLE_TYPE = HandleType::Event; static const HandleType HANDLE_TYPE = HandleType::ReadableEvent;
HandleType GetHandleType() const override { HandleType GetHandleType() const override {
return HANDLE_TYPE; return HANDLE_TYPE;
} }

View file

@ -1575,16 +1575,23 @@ static ResultCode ClearEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
const auto& handle_table = Core::CurrentProcess()->GetHandleTable(); const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
SharedPtr<ReadableEvent> evt = handle_table.Get<ReadableEvent>(handle);
if (evt == nullptr) { auto writable_event = handle_table.Get<WritableEvent>(handle);
LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle); if (writable_event) {
return ERR_INVALID_HANDLE; writable_event->Clear();
return RESULT_SUCCESS;
} }
evt->Clear(); auto readable_event = handle_table.Get<ReadableEvent>(handle);
if (readable_event) {
readable_event->Clear();
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
LOG_ERROR(Kernel_SVC, "Event handle does not exist, handle=0x{:08X}", handle);
return ERR_INVALID_HANDLE;
}
static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) { static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);

View file

@ -39,7 +39,7 @@ public:
return name; return name;
} }
static const HandleType HANDLE_TYPE = HandleType::Event; static const HandleType HANDLE_TYPE = HandleType::WritableEvent;
HandleType GetHandleType() const override { HandleType GetHandleType() const override {
return HANDLE_TYPE; return HANDLE_TYPE;
} }

View file

@ -153,7 +153,7 @@ QString WaitTreeWaitObject::GetText() const {
std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitObject& object) { std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitObject& object) {
switch (object.GetHandleType()) { switch (object.GetHandleType()) {
case Kernel::HandleType::Event: case Kernel::HandleType::ReadableEvent:
return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object));
case Kernel::HandleType::Timer: case Kernel::HandleType::Timer:
return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object)); return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object));