From c7763603ef8ac1001b2926bf91ecc42a45dd5fcb Mon Sep 17 00:00:00 2001 From: David Marcec Date: Thu, 11 Oct 2018 23:06:34 +1100 Subject: [PATCH 1/2] Added error codes for nvmap --- src/core/hle/service/nvdrv/devices/nvmap.cpp | 71 ++++++++++++++++---- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index a2287cc1b2..c0b5ac47b8 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -11,6 +11,13 @@ namespace Service::Nvidia::Devices { +namespace NvErrCodes { +enum { + OperationNotPermitted = -1, + InvalidValue = -22, +}; +} + nvmap::nvmap() = default; nvmap::~nvmap() = default; @@ -44,7 +51,11 @@ u32 nvmap::ioctl(Ioctl command, const std::vector& input, std::vector& o u32 nvmap::IocCreate(const std::vector& input, std::vector& output) { IocCreateParams params; std::memcpy(¶ms, input.data(), sizeof(params)); + LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size); + if (!params.size) { + return static_cast(NvErrCodes::InvalidValue); + } // Create a new nvmap object and obtain a handle to it. auto object = std::make_shared(); object->id = next_id++; @@ -55,8 +66,6 @@ u32 nvmap::IocCreate(const std::vector& input, std::vector& output) { u32 handle = next_handle++; handles[handle] = std::move(object); - LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size); - params.handle = handle; std::memcpy(output.data(), ¶ms, sizeof(params)); @@ -66,9 +75,28 @@ u32 nvmap::IocCreate(const std::vector& input, std::vector& output) { u32 nvmap::IocAlloc(const std::vector& input, std::vector& output) { IocAllocParams params; std::memcpy(¶ms, input.data(), sizeof(params)); + LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr); + + if (!params.handle) { + return static_cast(NvErrCodes::InvalidValue); + } + + if ((params.align - 1) & params.align) { + return static_cast(NvErrCodes::InvalidValue); + } + + if (params.align < 0x1000) { + params.align = 0x1000; + } auto object = GetObject(params.handle); - ASSERT(object); + if (!object) { + return static_cast(NvErrCodes::InvalidValue); + } + + if (object->status == Object::Status::Allocated) { + return static_cast(NvErrCodes::OperationNotPermitted); + } object->flags = params.flags; object->align = params.align; @@ -76,8 +104,6 @@ u32 nvmap::IocAlloc(const std::vector& input, std::vector& output) { object->addr = params.addr; object->status = Object::Status::Allocated; - LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr); - std::memcpy(output.data(), ¶ms, sizeof(params)); return 0; } @@ -88,8 +114,14 @@ u32 nvmap::IocGetId(const std::vector& input, std::vector& output) { LOG_WARNING(Service_NVDRV, "called"); + if (!params.handle) { + return static_cast(NvErrCodes::InvalidValue); + } + auto object = GetObject(params.handle); - ASSERT(object); + if (!object) { + return static_cast(NvErrCodes::OperationNotPermitted); + } params.id = object->id; @@ -105,7 +137,14 @@ u32 nvmap::IocFromId(const std::vector& input, std::vector& output) { auto itr = std::find_if(handles.begin(), handles.end(), [&](const auto& entry) { return entry.second->id == params.id; }); - ASSERT(itr != handles.end()); + if (itr == handles.end()) { + return static_cast(NvErrCodes::InvalidValue); + } + + auto& object = itr->second; + if (object->status != Object::Status::Allocated) { + return static_cast(NvErrCodes::InvalidValue); + } itr->second->refcount++; @@ -125,8 +164,13 @@ u32 nvmap::IocParam(const std::vector& input, std::vector& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.param); auto object = GetObject(params.handle); - ASSERT(object); - ASSERT(object->status == Object::Status::Allocated); + if (!object) { + return static_cast(NvErrCodes::InvalidValue); + } + + if (object->status != Object::Status::Allocated) { + return static_cast(NvErrCodes::OperationNotPermitted); + } switch (static_cast(params.param)) { case ParamTypes::Size: @@ -163,9 +207,12 @@ u32 nvmap::IocFree(const std::vector& input, std::vector& output) { LOG_WARNING(Service_NVDRV, "(STUBBED) called"); auto itr = handles.find(params.handle); - ASSERT(itr != handles.end()); - - ASSERT(itr->second->refcount > 0); + if (itr == handles.end()) { + return static_cast(NvErrCodes::InvalidValue); + } + if (!itr->second->refcount) { + return static_cast(NvErrCodes::InvalidValue); + } itr->second->refcount--; From c55b5de0fb0c8db59b0520553b22e520b5f966ed Mon Sep 17 00:00:00 2001 From: David Marcec Date: Fri, 12 Oct 2018 17:06:46 +1100 Subject: [PATCH 2/2] Made the minimum alignment more clear --- src/core/hle/service/nvdrv/devices/nvmap.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp index c0b5ac47b8..43651d8a6c 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.cpp +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -85,8 +85,9 @@ u32 nvmap::IocAlloc(const std::vector& input, std::vector& output) { return static_cast(NvErrCodes::InvalidValue); } - if (params.align < 0x1000) { - params.align = 0x1000; + const u32 min_alignment = 0x1000; + if (params.align < min_alignment) { + params.align = min_alignment; } auto object = GetObject(params.handle);