ebpf-for-windows/libs/platform/ebpf_serialize.c

181 строка
6.2 KiB
C
Исходник Обычный вид История

// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
// This file contains function implementations for serializing and de-serializing
// various eBPF structures to/from ebpf_operation*_request/response structures.
#include "ebpf_serialize.h"
void
ebpf_map_information_array_free(uint16_t map_count, _In_count_(map_count) const ebpf_map_information_t* map_info)
{
uint16_t map_index;
for (map_index = 0; map_index < map_count; map_index++) {
ebpf_free(map_info[map_index].pin_path);
}
ebpf_free((void*)map_info);
}
ebpf_result_t
ebpf_serialize_core_map_information_array(
uint16_t map_count,
_In_count_(map_count) const ebpf_core_map_information_t* map_info,
_Out_writes_bytes_to_(output_buffer_length, *serialized_data_length) uint8_t* output_buffer,
size_t output_buffer_length,
_Out_ size_t* serialized_data_length,
_Out_ size_t* required_length)
{
ebpf_result_t result = EBPF_SUCCESS;
uint16_t map_index;
uint8_t* current = NULL;
*serialized_data_length = 0;
// Compute required length for serialized array of map information objects.
*required_length = 0;
for (map_index = 0; map_index < map_count; map_index++) {
// Increment required_length by EBPF_OFFSET_OF(ebpf_serialized_map_information_t, pin_path).
result = ebpf_safe_size_t_add(
*required_length, EBPF_OFFSET_OF(ebpf_serialized_map_information_t, pin_path), required_length);
if (result != EBPF_SUCCESS)
goto Exit;
// Increment required_length by map_info[map_index].pin_path.length.
result = ebpf_safe_size_t_add(*required_length, map_info[map_index].pin_path.length, required_length);
if (result != EBPF_SUCCESS)
goto Exit;
}
// Output buffer too small.
if (output_buffer_length < *required_length) {
result = EBPF_INSUFFICIENT_BUFFER;
goto Exit;
}
*serialized_data_length = *required_length;
current = output_buffer;
for (map_index = 0; map_index < map_count; map_index++) {
size_t serialized_map_information_length;
const ebpf_core_map_information_t* source = &map_info[map_index];
ebpf_serialized_map_information_t* destination = (ebpf_serialized_map_information_t*)current;
// Compute required length for serialized map information.
result = ebpf_safe_size_t_add(
EBPF_OFFSET_OF(ebpf_serialized_map_information_t, pin_path),
source->pin_path.length,
&serialized_map_information_length);
if (result != EBPF_SUCCESS)
goto Exit;
// Copy the map definition fields.
destination->definition = source->definition;
// Set the length of the pin path.
destination->pin_path_length = (uint16_t)source->pin_path.length;
// Copy the pin path buffer.
memcpy(destination->pin_path, source->pin_path.value, source->pin_path.length);
// Move the output buffer current pointer.
current += serialized_map_information_length;
}
Exit:
return result;
}
ebpf_result_t
ebpf_deserialize_map_information_array(
size_t input_buffer_length,
_In_reads_bytes_(input_buffer_length) const uint8_t* input_buffer,
uint16_t map_count,
_Outptr_result_buffer_(map_count) ebpf_map_information_t** map_info)
{
ebpf_result_t result = EBPF_SUCCESS;
uint16_t map_index;
size_t out_map_size;
ebpf_map_information_t* out_map_info = NULL;
uint8_t* current;
size_t buffer_left;
// Allocate the output maps.
result = ebpf_safe_size_t_multiply(sizeof(ebpf_map_information_t), (size_t)map_count, &out_map_size);
if (result != EBPF_SUCCESS)
goto Exit;
out_map_info = (ebpf_map_information_t*)ebpf_allocate(out_map_size);
if (out_map_info == NULL) {
result = EBPF_NO_MEMORY;
goto Exit;
}
current = (uint8_t*)input_buffer;
buffer_left = input_buffer_length;
for (map_index = 0; map_index < map_count; map_index++) {
ebpf_serialized_map_information_t* source;
ebpf_map_information_t* destination;
size_t destination_pin_path_length;
// Check if sufficient input buffer remaining.
if (buffer_left < sizeof(ebpf_serialized_map_information_t)) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
source = (ebpf_serialized_map_information_t*)current;
destination = &out_map_info[map_index];
// Copy the map definition part.
destination->definition = source->definition;
// Advance the input buffer current pointer.
current += EBPF_OFFSET_OF(ebpf_serialized_map_information_t, pin_path);
// Adjust remaining input buffer length.
result = ebpf_safe_size_t_subtract(
buffer_left, EBPF_OFFSET_OF(ebpf_serialized_map_information_t, pin_path), &buffer_left);
if (result != EBPF_SUCCESS)
goto Exit;
// Check if sufficient input buffer remaining.
if (buffer_left < source->pin_path_length) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if (source->pin_path_length > 0) {
// Allocate the buffer to hold the pin path in destination map information structure.
destination_pin_path_length = source->pin_path_length + 1;
if (result != EBPF_SUCCESS)
goto Exit;
destination->pin_path = ebpf_allocate(destination_pin_path_length);
if (destination->pin_path == NULL) {
result = EBPF_NO_MEMORY;
goto Exit;
}
// Copy the pin path.
memcpy(destination->pin_path, source->pin_path, source->pin_path_length);
// Advance the input buffer current pointer.
current += source->pin_path_length;
// Adjust remaining input buffer length.
result = ebpf_safe_size_t_subtract(buffer_left, source->pin_path_length, &buffer_left);
if (result != EBPF_SUCCESS)
goto Exit;
}
}
*map_info = out_map_info;
out_map_info = NULL;
Exit:
if (out_map_info != NULL)
ebpf_map_information_array_free(map_count, out_map_info);
return result;
}