mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:27:35 +00:00
Everywhere: Make ByteBuffer::{create_*,copy}() OOM-safe
This commit is contained in:
parent
3a9f00c59b
commit
97e97bccab
105 changed files with 629 additions and 290 deletions
|
@ -213,7 +213,10 @@ KResult Ext2FSInode::write_indirect_block(BlockBasedFileSystem::BlockIndex block
|
|||
const auto entries_per_block = EXT2_ADDR_PER_BLOCK(&fs().super_block());
|
||||
VERIFY(blocks_indices.size() <= entries_per_block);
|
||||
|
||||
auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
if (!block_contents_result.has_value())
|
||||
return ENOMEM;
|
||||
auto block_contents = block_contents_result.release_value();
|
||||
OutputMemoryStream stream { block_contents };
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
|
||||
|
||||
|
@ -235,7 +238,10 @@ KResult Ext2FSInode::grow_doubly_indirect_block(BlockBasedFileSystem::BlockIndex
|
|||
VERIFY(blocks_indices.size() > old_blocks_length);
|
||||
VERIFY(blocks_indices.size() <= entries_per_doubly_indirect_block);
|
||||
|
||||
auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
if (!block_contents_result.has_value())
|
||||
return ENOMEM;
|
||||
auto block_contents = block_contents_result.release_value();
|
||||
auto* block_as_pointers = (unsigned*)block_contents.data();
|
||||
OutputMemoryStream stream { block_contents };
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
|
||||
|
@ -275,7 +281,10 @@ KResult Ext2FSInode::shrink_doubly_indirect_block(BlockBasedFileSystem::BlockInd
|
|||
VERIFY(old_blocks_length >= new_blocks_length);
|
||||
VERIFY(new_blocks_length <= entries_per_doubly_indirect_block);
|
||||
|
||||
auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
if (!block_contents_result.has_value())
|
||||
return ENOMEM;
|
||||
auto block_contents = block_contents_result.release_value();
|
||||
auto* block_as_pointers = (unsigned*)block_contents.data();
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<u8*>(block_as_pointers));
|
||||
TRY(fs().read_block(block, &buffer, fs().block_size()));
|
||||
|
@ -308,7 +317,10 @@ KResult Ext2FSInode::grow_triply_indirect_block(BlockBasedFileSystem::BlockIndex
|
|||
VERIFY(blocks_indices.size() > old_blocks_length);
|
||||
VERIFY(blocks_indices.size() <= entries_per_triply_indirect_block);
|
||||
|
||||
auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
if (!block_contents_result.has_value())
|
||||
return ENOMEM;
|
||||
auto block_contents = block_contents_result.release_value();
|
||||
auto* block_as_pointers = (unsigned*)block_contents.data();
|
||||
OutputMemoryStream stream { block_contents };
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(stream.data());
|
||||
|
@ -351,7 +363,10 @@ KResult Ext2FSInode::shrink_triply_indirect_block(BlockBasedFileSystem::BlockInd
|
|||
VERIFY(old_blocks_length >= new_blocks_length);
|
||||
VERIFY(new_blocks_length <= entries_per_triply_indirect_block);
|
||||
|
||||
auto block_contents = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
auto block_contents_result = ByteBuffer::create_uninitialized(fs().block_size());
|
||||
if (!block_contents_result.has_value())
|
||||
return ENOMEM;
|
||||
auto block_contents = block_contents_result.release_value();
|
||||
auto* block_as_pointers = (unsigned*)block_contents.data();
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<u8*>(block_as_pointers));
|
||||
TRY(fs().read_block(block, &buffer, fs().block_size()));
|
||||
|
@ -583,7 +598,8 @@ Vector<Ext2FS::BlockIndex> Ext2FSInode::compute_block_list_impl_internal(const e
|
|||
if (!count)
|
||||
return;
|
||||
size_t read_size = count * sizeof(u32);
|
||||
auto array_storage = ByteBuffer::create_uninitialized(read_size);
|
||||
// FIXME: Handle possible OOM situation.
|
||||
auto array_storage = ByteBuffer::create_uninitialized(read_size).release_value();
|
||||
auto* array = (u32*)array_storage.data();
|
||||
auto buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)array);
|
||||
if (auto result = fs().read_block(array_block_index, &buffer, read_size, 0); result.is_error()) {
|
||||
|
@ -1109,7 +1125,10 @@ KResult Ext2FSInode::write_directory(Vector<Ext2FSDirectoryEntry>& entries)
|
|||
|
||||
dbgln_if(EXT2_DEBUG, "Ext2FSInode[{}]::write_directory(): New directory contents to write (size {}):", identifier(), directory_size);
|
||||
|
||||
auto directory_data = ByteBuffer::create_uninitialized(directory_size);
|
||||
auto directory_data_result = ByteBuffer::create_uninitialized(directory_size);
|
||||
if (!directory_data_result.has_value())
|
||||
return ENOMEM;
|
||||
auto directory_data = directory_data_result.release_value();
|
||||
OutputMemoryStream stream { directory_data };
|
||||
|
||||
for (auto& entry : entries) {
|
||||
|
|
|
@ -251,7 +251,7 @@ UNMAP_AFTER_INIT int NE2000NetworkAdapter::ram_test()
|
|||
out8(REG_WR_REMOTEBYTECOUNT1, 0x00);
|
||||
out8(REG_WR_RECEIVECONFIGURATION, BIT_RECEIVECONFIGURATION_MON);
|
||||
out8(REG_RW_COMMAND, BIT_COMMAND_DMA_ABORT | BIT_COMMAND_START);
|
||||
auto buffer = ByteBuffer::create_uninitialized(NE2K_RAM_SIZE);
|
||||
Array<u8, NE2K_RAM_SIZE> buffer;
|
||||
|
||||
const u8 patterns[3] = { 0x5a, 0xff, 0x00 };
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
|
@ -412,22 +412,35 @@ void NE2000NetworkAdapter::receive()
|
|||
dbgln_if(NE2000_DEBUG, "NE2000NetworkAdapter: Packet received {} length={}", (packet_ok ? "intact" : "damaged"), header.length);
|
||||
|
||||
if (packet_ok) {
|
||||
auto packet = NetworkByteBuffer::create_uninitialized(sizeof(received_packet_header) + header.length);
|
||||
int bytes_left = packet.size();
|
||||
size_t bytes_in_packet = sizeof(received_packet_header) + header.length;
|
||||
|
||||
auto packet_result = NetworkByteBuffer::create_uninitialized(bytes_in_packet);
|
||||
u8 drop_buffer[NE2K_PAGE_SIZE];
|
||||
Bytes buffer { drop_buffer, array_size(drop_buffer) };
|
||||
bool will_drop { false };
|
||||
if (!packet_result.has_value()) {
|
||||
dbgln("NE2000NetworkAdapter: Not enough memory for packet with length = {}, dropping.", header.length);
|
||||
will_drop = true;
|
||||
} else {
|
||||
buffer = packet_result->bytes();
|
||||
}
|
||||
|
||||
int current_offset = 0;
|
||||
int ring_offset = header_address;
|
||||
|
||||
while (bytes_left > 0) {
|
||||
int copy_size = min(bytes_left, NE2K_PAGE_SIZE);
|
||||
rdma_read(ring_offset, packet.span().slice(current_offset, copy_size));
|
||||
current_offset += copy_size;
|
||||
while (bytes_in_packet > 0) {
|
||||
int copy_size = min(bytes_in_packet, NE2K_PAGE_SIZE);
|
||||
rdma_read(ring_offset, buffer.slice(current_offset, copy_size));
|
||||
if (!will_drop)
|
||||
current_offset += copy_size;
|
||||
ring_offset += copy_size;
|
||||
bytes_left -= copy_size;
|
||||
bytes_in_packet -= copy_size;
|
||||
if (ring_offset == NE2K_RAM_RECV_END)
|
||||
ring_offset = NE2K_RAM_RECV_BEGIN;
|
||||
}
|
||||
|
||||
did_receive(packet.span().slice(sizeof(received_packet_header)));
|
||||
if (!will_drop)
|
||||
did_receive(buffer.slice(sizeof(received_packet_header)));
|
||||
}
|
||||
|
||||
if (header.next_packet_page == (NE2K_RAM_RECV_BEGIN >> 8))
|
||||
|
|
|
@ -33,8 +33,12 @@ void NetworkAdapter::send_packet(ReadonlyBytes packet)
|
|||
void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet)
|
||||
{
|
||||
size_t size_in_bytes = sizeof(EthernetFrameHeader) + sizeof(ARPPacket);
|
||||
auto buffer = NetworkByteBuffer::create_zeroed(size_in_bytes);
|
||||
auto* eth = (EthernetFrameHeader*)buffer.data();
|
||||
auto buffer_result = NetworkByteBuffer::create_zeroed(size_in_bytes);
|
||||
if (!buffer_result.has_value()) {
|
||||
dbgln("Dropping ARP packet targeted at {} as there is not enough memory to buffer it", packet.target_hardware_address().to_string());
|
||||
return;
|
||||
}
|
||||
auto* eth = (EthernetFrameHeader*)buffer_result->data();
|
||||
eth->set_source(mac_address());
|
||||
eth->set_destination(destination);
|
||||
eth->set_ether_type(EtherType::ARP);
|
||||
|
|
|
@ -30,8 +30,9 @@ public:
|
|||
using HashType = HashT;
|
||||
using DigestType = typename HashT::DigestType;
|
||||
|
||||
// FIXME: Do something other than VERIFY()'ing inside Optional in case of OOM.
|
||||
FortunaPRNG()
|
||||
: m_counter(ByteBuffer::create_zeroed(BlockType::block_size()))
|
||||
: m_counter(ByteBuffer::create_zeroed(BlockType::block_size()).release_value())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -95,8 +96,17 @@ private:
|
|||
}
|
||||
}
|
||||
DigestType digest = new_key.digest();
|
||||
m_key = ByteBuffer::copy(digest.immutable_data(),
|
||||
digest.data_length());
|
||||
if (m_key.size() == digest.data_length()) {
|
||||
// Avoid reallocating, just overwrite the key.
|
||||
m_key.overwrite(0, digest.immutable_data(), digest.data_length());
|
||||
} else {
|
||||
auto buffer_result = ByteBuffer::copy(digest.immutable_data(), digest.data_length());
|
||||
// If there's no memory left to copy this into, bail out.
|
||||
if (!buffer_result.has_value())
|
||||
return;
|
||||
|
||||
m_key = buffer_result.release_value();
|
||||
}
|
||||
|
||||
m_reseed_number++;
|
||||
m_p0_len = 0;
|
||||
|
|
|
@ -379,8 +379,9 @@ UNMAP_AFTER_INIT void IDEChannel::detect_disks()
|
|||
}
|
||||
}
|
||||
|
||||
ByteBuffer wbuf = ByteBuffer::create_uninitialized(512);
|
||||
ByteBuffer bbuf = ByteBuffer::create_uninitialized(512);
|
||||
// FIXME: Handle possible OOM situation here.
|
||||
ByteBuffer wbuf = ByteBuffer::create_uninitialized(512).release_value();
|
||||
ByteBuffer bbuf = ByteBuffer::create_uninitialized(512).release_value();
|
||||
u8* b = bbuf.data();
|
||||
u16* w = (u16*)wbuf.data();
|
||||
|
||||
|
|
|
@ -58,7 +58,8 @@ Result<NonnullOwnPtr<GUIDPartitionTable>, PartitionTable::Error> GUIDPartitionTa
|
|||
GUIDPartitionTable::GUIDPartitionTable(const StorageDevice& device)
|
||||
: MBRPartitionTable(device)
|
||||
{
|
||||
m_cached_header = ByteBuffer::create_zeroed(m_device->block_size());
|
||||
// FIXME: Handle OOM failure here.
|
||||
m_cached_header = ByteBuffer::create_zeroed(m_device->block_size()).release_value();
|
||||
VERIFY(partitions_count() == 0);
|
||||
if (!initialize())
|
||||
m_valid = false;
|
||||
|
@ -87,7 +88,12 @@ bool GUIDPartitionTable::initialize()
|
|||
return false;
|
||||
}
|
||||
|
||||
auto entries_buffer = ByteBuffer::create_zeroed(m_device->block_size());
|
||||
auto entries_buffer_result = ByteBuffer::create_zeroed(m_device->block_size());
|
||||
if (!entries_buffer_result.has_value()) {
|
||||
dbgln("GUIPartitionTable: not enough memory for entries buffer");
|
||||
return false;
|
||||
}
|
||||
auto entries_buffer = entries_buffer_result.release_value();
|
||||
auto raw_entries_buffer = UserOrKernelBuffer::for_kernel_buffer(entries_buffer.data());
|
||||
size_t raw_byte_index = header().partition_array_start_lba * m_device->block_size();
|
||||
for (size_t entry_index = 0; entry_index < header().entries_count; entry_index++) {
|
||||
|
|
|
@ -47,7 +47,7 @@ bool MBRPartitionTable::read_boot_record()
|
|||
MBRPartitionTable::MBRPartitionTable(const StorageDevice& device, u32 start_lba)
|
||||
: PartitionTable(device)
|
||||
, m_start_lba(start_lba)
|
||||
, m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()))
|
||||
, m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()).release_value()) // FIXME: Do something sensible if this fails because of OOM.
|
||||
{
|
||||
if (!read_boot_record() || !initialize())
|
||||
return;
|
||||
|
@ -68,7 +68,7 @@ MBRPartitionTable::MBRPartitionTable(const StorageDevice& device, u32 start_lba)
|
|||
MBRPartitionTable::MBRPartitionTable(const StorageDevice& device)
|
||||
: PartitionTable(device)
|
||||
, m_start_lba(0)
|
||||
, m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()))
|
||||
, m_cached_header(ByteBuffer::create_zeroed(m_device->block_size()).release_value()) // FIXME: Do something sensible if this fails because of OOM.
|
||||
{
|
||||
if (!read_boot_record() || contains_ebr() || is_protective_mbr() || !initialize())
|
||||
return;
|
||||
|
|
|
@ -73,7 +73,10 @@ KResultOr<size_t> StorageDevice::read(FileDescription&, u64 offset, UserOrKernel
|
|||
off_t pos = whole_blocks * block_size();
|
||||
|
||||
if (remaining > 0) {
|
||||
auto data = ByteBuffer::create_uninitialized(block_size());
|
||||
auto data_result = ByteBuffer::create_uninitialized(block_size());
|
||||
if (!data_result.has_value())
|
||||
return ENOMEM;
|
||||
auto data = data_result.release_value();
|
||||
auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data.data());
|
||||
auto read_request = make_request<AsyncBlockDeviceRequest>(AsyncBlockDeviceRequest::Read, index + whole_blocks, 1, data_buffer, block_size());
|
||||
auto result = read_request->wait();
|
||||
|
@ -141,7 +144,8 @@ KResultOr<size_t> StorageDevice::write(FileDescription&, u64 offset, const UserO
|
|||
// partial write, we have to read the block's content first, modify it,
|
||||
// then write the whole block back to the disk.
|
||||
if (remaining > 0) {
|
||||
auto data = ByteBuffer::create_zeroed(block_size());
|
||||
// FIXME: Do something sensible with this OOM scenario.
|
||||
auto data = ByteBuffer::create_zeroed(block_size()).release_value();
|
||||
auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data.data());
|
||||
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue