orbis: vmem: fix resource leak on error, log more errors

This commit is contained in:
DH 2025-12-03 18:58:45 +03:00
parent 17a7717584
commit f694b14a26

View file

@ -432,11 +432,13 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
blockFlags |= file->device->blockFlags; blockFlags |= file->device->blockFlags;
if (!validateProtection(prot)) { if (!validateProtection(prot)) {
rx::println(stderr, "map: invalid prot {}", prot);
return {{}, ErrorCode::INVAL}; return {{}, ErrorCode::INVAL};
} }
if (blockFlags & BlockFlags::PooledMemory) { if (blockFlags & BlockFlags::PooledMemory) {
if (size < dmem::kPageSize * 2 || size % dmem::kPageSize) { if (size < dmem::kPageSize * 2 || size % dmem::kPageSize) {
rx::println(stderr, "map: blockpool: invalid size {}", size);
return {{}, ErrorCode::INVAL}; return {{}, ErrorCode::INVAL};
} }
} }
@ -452,7 +454,9 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
} }
if (allocFlags & AllocationFlags::Fixed) { if (allocFlags & AllocationFlags::Fixed) {
if (addressHint % alignment) { if (addressHint & (alignment - 1)) {
rx::println(stderr, "map: invalid fixed address {:x}, alignment {:x}",
addressHint, alignment);
return {{}, ErrorCode::INVAL}; return {{}, ErrorCode::INVAL};
} }
} }
@ -485,10 +489,12 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
if (errc != std::errc{}) { if (errc != std::errc{}) {
if (errc == std::errc::not_enough_memory) { if (errc == std::errc::not_enough_memory) {
// virtual memory shouldn't care about physical memory // virtual memory shouldn't care about physical memory
rx::println(stderr, "map: OOM");
return {{}, ErrorCode::INVAL}; return {{}, ErrorCode::INVAL};
} }
if (errc == std::errc::file_exists) { if (errc == std::errc::file_exists) {
rx::println(stderr, "map: NoOverwrite overwrites memory");
return {{}, ErrorCode::NOMEM}; return {{}, ErrorCode::NOMEM};
} }
@ -502,6 +508,10 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
} }
} }
if (type != MemoryType::Invalid && !validateMemoryType(type, prot)) {
return {{}, ErrorCode::ACCES};
}
auto budget = process->getBudget(); auto budget = process->getBudget();
if (blockFlags & BlockFlags::PooledMemory) { if (blockFlags & BlockFlags::PooledMemory) {
@ -522,8 +532,6 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
} }
} }
allocFlags = AllocationFlags::Fixed | (allocFlags & AllocationFlags::NoMerge);
if (blockFlags & BlockFlags::DirectMemory) { if (blockFlags & BlockFlags::DirectMemory) {
if (!budget->acquire(BudgetResource::Dmem, size)) { if (!budget->acquire(BudgetResource::Dmem, size)) {
rx::println(stderr, "map: dmem budget: failed to allocate {:#x} bytes", rx::println(stderr, "map: dmem budget: failed to allocate {:#x} bytes",
@ -538,15 +546,14 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
if (blockFlags & BlockFlags::PooledMemory) { if (blockFlags & BlockFlags::PooledMemory) {
if (auto errc = blockpool::allocateControlBlock(); errc != ErrorCode{}) { if (auto errc = blockpool::allocateControlBlock(); errc != ErrorCode{}) {
rx::println(stderr,
"map: blockpool: failed to allocate control block, error {}",
errc);
return {{}, errc}; return {{}, errc};
} }
allocationInfo.flagsEx |= BlockFlagsEx::PoolControl; allocationInfo.flagsEx |= BlockFlagsEx::PoolControl;
} }
if (type != MemoryType::Invalid && !validateMemoryType(type, prot)) {
return {{}, ErrorCode::ACCES};
}
if (auto error = process->invoke([=] { if (auto error = process->invoke([=] {
return file->device->map(range, fileOffset, prot, file, process); return file->device->map(range, fileOffset, prot, file, process);
}); });
@ -563,6 +570,7 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
blockpool::releaseControlBlock(); blockpool::releaseControlBlock();
} }
rx::println(stderr, "map: device allocation failure, blockFlags {}", blockFlags);
return {{}, error}; return {{}, error};
} }
@ -595,8 +603,10 @@ std::pair<rx::AddressRange, orbis::ErrorCode> orbis::vmem::mapFile(
} }
{ {
auto [_it, errc, _range] = vmem->map(range.beginAddress(), range.size(), auto [_it, errc, _range] = vmem->map(
allocationInfo, allocFlags, alignment); range.beginAddress(), range.size(), allocationInfo,
AllocationFlags::Fixed | (allocFlags & AllocationFlags::NoMerge),
alignment);
rx::dieIf(errc != std::errc{}, "failed to commit virtual memory {}", errc); rx::dieIf(errc != std::errc{}, "failed to commit virtual memory {}", errc);
} }