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:
parent
adc4d332fc
commit
5eb057f422
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1575,14 +1575,21 @@ 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);
|
||||||
return RESULT_SUCCESS;
|
if (readable_event) {
|
||||||
|
readable_event->Clear();
|
||||||
|
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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in New Issue