diff options
| author | bunnei <bunneidev@gmail.com> | 2019-02-27 11:22:26 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-02-27 11:22:26 -0500 | 
| commit | eb5a3dd1c7b4c69c708924208acd2077ff08308f (patch) | |
| tree | 2e7d700cd854170203772883d6b66b108c7a428e /src/core/hle | |
| parent | be1a1584fca26837932be42374815282ba5767f5 (diff) | |
| parent | d29f9e9709b3cab6448b43f00f4f0204680ceee5 (diff) | |
Merge pull request #2161 from lioncash/handle-table
 kernel/handle_table: Allow process capabilities to limit the handle table size
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/errors.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/handle_table.cpp | 40 | ||||
| -rw-r--r-- | src/core/hle/kernel/handle_table.h | 25 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/process_capability.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/process_capability.h | 4 | 
6 files changed, 63 insertions, 19 deletions
| diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h index d17eb0cb6..8097b3863 100644 --- a/src/core/hle/kernel/errors.h +++ b/src/core/hle/kernel/errors.h @@ -14,6 +14,7 @@ constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED{ErrorModule::Kernel, 7};  constexpr ResultCode ERR_INVALID_CAPABILITY_DESCRIPTOR{ErrorModule::Kernel, 14};  constexpr ResultCode ERR_INVALID_SIZE{ErrorModule::Kernel, 101};  constexpr ResultCode ERR_INVALID_ADDRESS{ErrorModule::Kernel, 102}; +constexpr ResultCode ERR_OUT_OF_MEMORY{ErrorModule::Kernel, 104};  constexpr ResultCode ERR_HANDLE_TABLE_FULL{ErrorModule::Kernel, 105};  constexpr ResultCode ERR_INVALID_ADDRESS_STATE{ErrorModule::Kernel, 106};  constexpr ResultCode ERR_INVALID_MEMORY_PERMISSIONS{ErrorModule::Kernel, 108}; diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index c8acde5b1..bdfaa977f 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -14,32 +14,47 @@  namespace Kernel {  namespace {  constexpr u16 GetSlot(Handle handle) { -    return handle >> 15; +    return static_cast<u16>(handle >> 15);  }  constexpr u16 GetGeneration(Handle handle) { -    return handle & 0x7FFF; +    return static_cast<u16>(handle & 0x7FFF);  }  } // Anonymous namespace  HandleTable::HandleTable() { -    next_generation = 1;      Clear();  }  HandleTable::~HandleTable() = default; +ResultCode HandleTable::SetSize(s32 handle_table_size) { +    if (static_cast<u32>(handle_table_size) > MAX_COUNT) { +        return ERR_OUT_OF_MEMORY; +    } + +    // Values less than or equal to zero indicate to use the maximum allowable +    // size for the handle table in the actual kernel, so we ignore the given +    // value in that case, since we assume this by default unless this function +    // is called. +    if (handle_table_size > 0) { +        table_size = static_cast<u16>(handle_table_size); +    } + +    return RESULT_SUCCESS; +} +  ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {      DEBUG_ASSERT(obj != nullptr); -    u16 slot = next_free_slot; -    if (slot >= generations.size()) { +    const u16 slot = next_free_slot; +    if (slot >= table_size) {          LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");          return ERR_HANDLE_TABLE_FULL;      }      next_free_slot = generations[slot]; -    u16 generation = next_generation++; +    const u16 generation = next_generation++;      // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.      // Horizon OS uses zero to represent an invalid handle, so skip to 1. @@ -64,10 +79,11 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) {  }  ResultCode HandleTable::Close(Handle handle) { -    if (!IsValid(handle)) +    if (!IsValid(handle)) {          return ERR_INVALID_HANDLE; +    } -    u16 slot = GetSlot(handle); +    const u16 slot = GetSlot(handle);      objects[slot] = nullptr; @@ -77,10 +93,10 @@ ResultCode HandleTable::Close(Handle handle) {  }  bool HandleTable::IsValid(Handle handle) const { -    std::size_t slot = GetSlot(handle); -    u16 generation = GetGeneration(handle); +    const std::size_t slot = GetSlot(handle); +    const u16 generation = GetGeneration(handle); -    return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation; +    return slot < table_size && objects[slot] != nullptr && generations[slot] == generation;  }  SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const { @@ -97,7 +113,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {  }  void HandleTable::Clear() { -    for (u16 i = 0; i < MAX_COUNT; ++i) { +    for (u16 i = 0; i < table_size; ++i) {          generations[i] = i + 1;          objects[i] = nullptr;      } diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index 89a3bc740..44901391b 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h @@ -50,6 +50,20 @@ public:      ~HandleTable();      /** +     * Sets the number of handles that may be in use at one time +     * for this handle table. +     * +     * @param handle_table_size The desired size to limit the handle table to. +     * +     * @returns an error code indicating if initialization was successful. +     *          If initialization was not successful, then ERR_OUT_OF_MEMORY +     *          will be returned. +     * +     * @pre handle_table_size must be within the range [0, 1024] +     */ +    ResultCode SetSize(s32 handle_table_size); + +    /**       * Allocates a handle for the given object.       * @return The created Handle or one of the following errors:       *           - `ERR_HANDLE_TABLE_FULL`: the maximum number of handles has been exceeded. @@ -104,13 +118,20 @@ private:      std::array<u16, MAX_COUNT> generations;      /** +     * The limited size of the handle table. This can be specified by process +     * capabilities in order to restrict the overall number of handles that +     * can be created in a process instance +     */ +    u16 table_size = static_cast<u16>(MAX_COUNT); + +    /**       * Global counter of the number of created handles. Stored in `generations` when a handle is       * created, and wraps around to 1 when it hits 0x8000.       */ -    u16 next_generation; +    u16 next_generation = 1;      /// Head of the free slots linked list. -    u16 next_free_slot; +    u16 next_free_slot = 0;  };  } // namespace Kernel diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index c5aa19afa..8009150e0 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -99,7 +99,13 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {      vm_manager.Reset(metadata.GetAddressSpaceType());      const auto& caps = metadata.GetKernelCapabilities(); -    return capabilities.InitializeForUserProcess(caps.data(), caps.size(), vm_manager); +    const auto capability_init_result = +        capabilities.InitializeForUserProcess(caps.data(), caps.size(), vm_manager); +    if (capability_init_result.IsError()) { +        return capability_init_result; +    } + +    return handle_table.SetSize(capabilities.GetHandleTableSize());  }  void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp index 3a2164b25..583e35b79 100644 --- a/src/core/hle/kernel/process_capability.cpp +++ b/src/core/hle/kernel/process_capability.cpp @@ -96,7 +96,7 @@ void ProcessCapabilities::InitializeForMetadatalessProcess() {      interrupt_capabilities.set();      // Allow using the maximum possible amount of handles -    handle_table_size = static_cast<u32>(HandleTable::MAX_COUNT); +    handle_table_size = static_cast<s32>(HandleTable::MAX_COUNT);      // Allow all debugging capabilities.      is_debuggable = true; @@ -337,7 +337,7 @@ ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) {          return ERR_RESERVED_VALUE;      } -    handle_table_size = (flags >> 16) & 0x3FF; +    handle_table_size = static_cast<s32>((flags >> 16) & 0x3FF);      return RESULT_SUCCESS;  } diff --git a/src/core/hle/kernel/process_capability.h b/src/core/hle/kernel/process_capability.h index fbc8812a3..5cdd80747 100644 --- a/src/core/hle/kernel/process_capability.h +++ b/src/core/hle/kernel/process_capability.h @@ -156,7 +156,7 @@ public:      }      /// Gets the number of total allowable handles for the process' handle table. -    u32 GetHandleTableSize() const { +    s32 GetHandleTableSize() const {          return handle_table_size;      } @@ -252,7 +252,7 @@ private:      u64 core_mask = 0;      u64 priority_mask = 0; -    u32 handle_table_size = 0; +    s32 handle_table_size = 0;      u32 kernel_version = 0;      ProgramType program_type = ProgramType::SysModule; | 
