2021-06-09 18:44:24 +03:00
|
|
|
// 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) {
|
2021-06-10 05:32:57 +03:00
|
|
|
result = EBPF_INSUFFICIENT_BUFFER;
|
2021-06-09 18:44:24 +03:00
|
|
|
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;
|
2021-06-10 05:32:57 +03:00
|
|
|
}
|