common/nvdrv: improve memory validation and error handling

Implements several improvements to memory handling and validation:

- host_memory: Add IsValidMapping() and IsDirectMappingEnabled() methods to
  validate memory access
- host_memory: Fix virtual base offset calculation to use proper pointer
  arithmetic
- host_memory: Add size field to track allocation size
- nvhost_ctrl_gpu: Return InvalidState instead of InvalidValue for TPC mask
  buffer size validation
- Update copyright year for citron

The changes improve memory safety by adding explicit validation checks and
fixing pointer arithmetic in the virtual memory implementation.
This commit is contained in:
Zephyron 2025-02-01 21:50:33 +10:00
parent 70a9f20ae1
commit f4b9e54b22
No known key found for this signature in database
GPG key ID: 2177ADED8AC966AF
3 changed files with 32 additions and 2 deletions

View file

@ -200,11 +200,20 @@ public:
UNREACHABLE(); UNREACHABLE();
} }
bool IsValidMapping(size_t offset, size_t size) const {
return (offset + size) <= backing_size;
}
bool IsDirectMappingEnabled() const {
return direct_mapping_enabled;
}
const size_t backing_size; ///< Size of the backing memory in bytes const size_t backing_size; ///< Size of the backing memory in bytes
const size_t virtual_size; ///< Size of the virtual address placeholder in bytes const size_t virtual_size; ///< Size of the virtual address placeholder in bytes
u8* backing_base{}; u8* backing_base{};
u8* virtual_base{}; u8* virtual_base{};
bool direct_mapping_enabled{false};
private: private:
/// Release all resources in the object /// Release all resources in the object
@ -602,6 +611,14 @@ public:
virtual_base = nullptr; virtual_base = nullptr;
} }
bool IsValidMapping(size_t offset, size_t size) const {
return (offset + size) <= backing_size;
}
bool IsDirectMappingEnabled() const {
return virtual_base == nullptr;
}
const size_t backing_size; ///< Size of the backing memory in bytes const size_t backing_size; ///< Size of the backing memory in bytes
const size_t virtual_size; ///< Size of the virtual address placeholder in bytes const size_t virtual_size; ///< Size of the virtual address placeholder in bytes
@ -675,6 +692,14 @@ public:
void EnableDirectMappedAddress() {} void EnableDirectMappedAddress() {}
bool IsValidMapping(size_t offset, size_t size) const {
return false;
}
bool IsDirectMappingEnabled() const {
return false;
}
u8* backing_base{nullptr}; u8* backing_base{nullptr};
u8* virtual_base{nullptr}; u8* virtual_base{nullptr};
}; };
@ -696,7 +721,9 @@ HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_)
// Ensure the virtual base is aligned to the L2 block size. // Ensure the virtual base is aligned to the L2 block size.
virtual_base = reinterpret_cast<u8*>( virtual_base = reinterpret_cast<u8*>(
Common::AlignUp(reinterpret_cast<uintptr_t>(virtual_base), HugePageSize)); Common::AlignUp(reinterpret_cast<uintptr_t>(virtual_base), HugePageSize));
virtual_base_offset = virtual_base - impl->virtual_base; virtual_base_offset = static_cast<size_t>(
reinterpret_cast<uintptr_t>(virtual_base) -
reinterpret_cast<uintptr_t>(impl->virtual_base));
} }
} catch (const std::bad_alloc&) { } catch (const std::bad_alloc&) {

View file

@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
@ -82,6 +83,8 @@ private:
// Fallback if fastmem is not supported on this platform // Fallback if fastmem is not supported on this platform
std::unique_ptr<Common::VirtualBuffer<u8>> fallback_buffer; std::unique_ptr<Common::VirtualBuffer<u8>> fallback_buffer;
size_t size;
}; };
} // namespace Common } // namespace Common

View file

@ -270,7 +270,7 @@ NvResult nvhost_ctrl_gpu::GetTpcMasks2(IoctlGetTpcMasks& params) {
// Validate input parameters // Validate input parameters
if (params.mask_buf_size == 0 || params.mask_buf_size > params.tpc_mask_buf.size()) { if (params.mask_buf_size == 0 || params.mask_buf_size > params.tpc_mask_buf.size()) {
LOG_ERROR(Service_NVDRV, "Invalid mask buffer size {}", params.mask_buf_size); LOG_ERROR(Service_NVDRV, "Invalid mask buffer size {}", params.mask_buf_size);
return NvResult::InvalidValue; return NvResult::InvalidState;
} }
// Set up TPC mask values based on GPU configuration // Set up TPC mask values based on GPU configuration