Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions libs/execution_context/ebpf_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ _ebpf_validate_native_btf_resolved_function_entry_array(
return false;
}

// Validate the first element before using its "total_size" as the array stride.
if (!_ebpf_validate_native_btf_resolved_function_entry(native_btf_entry_array)) {
return false;
}

size_t entry_size = native_btf_entry_array[0].header.total_size;
for (uint16_t i = 0; i < count; i++) {
const btf_resolved_function_entry_t* native_btf_entry =
Expand Down Expand Up @@ -309,6 +314,10 @@ _ebpf_validate_native_helper_function_entry_array(
if (native_helper_function_entry_array == NULL) {
return false;
}
// Validate the first element before using its "total_size" as the array stride.
if (!_ebpf_validate_native_helper_function_entry(native_helper_function_entry_array)) {
return false;
}
// Use "total_size" to calculate the actual size of the helper_function_entry_t struct.
size_t helper_prototype_size = native_helper_function_entry_array[0].header.total_size;
for (uint16_t i = 0; i < count; i++) {
Expand Down Expand Up @@ -353,6 +362,10 @@ _ebpf_validate_native_program_entry_array(
if (native_program_entry_array == NULL) {
return false;
}
// Validate the first element before using its "total_size" as the array stride.
if (!_ebpf_validate_native_program_entry(native_program_entry_array)) {
return false;
}
// Use "total_size" to calculate the actual size of the program_entry_t struct.
size_t program_entry_size = native_program_entry_array[0].header.total_size;
for (size_t i = 0; i < count; i++) {
Expand Down Expand Up @@ -384,6 +397,10 @@ _ebpf_validate_native_map_entry_array(_In_reads_(count) const map_entry_t* nativ
if (native_map_entry_array == NULL) {
return false;
}
// Validate the first element before using its "total_size" as the array stride.
if (!_ebpf_validate_native_map_entry(native_map_entry_array)) {
return false;
}
// Use "total_size" to calculate the actual size of the map_entry_t struct.
size_t map_entry_size = native_map_entry_array[0].header.total_size;
for (size_t i = 0; i < count; i++) {
Expand Down Expand Up @@ -417,6 +434,10 @@ _ebpf_validate_native_map_initial_values_array(
if (native_map_initial_values_array == NULL) {
return false;
}
// Validate the first element before using its "total_size" as the array stride.
if (!_ebpf_validate_native_map_initial_values(native_map_initial_values_array)) {
return false;
}
// Use "total_size" to calculate the actual size of the map_initial_values_t struct.
size_t map_initial_values_size = native_map_initial_values_array[0].header.total_size;
for (size_t i = 0; i < count; i++) {
Expand Down Expand Up @@ -451,6 +472,10 @@ _ebpf_validate_global_variable_section_info_array(
if (native_global_variable_section_info_array == NULL) {
return false;
}
// Validate the first element before using its "total_size" as the array stride.
if (!_ebpf_validate_native_global_variable_section_info(native_global_variable_section_info_array)) {
return false;
}
// Use "total_size" to calculate the actual size of the global_variable_section_info_t struct.
size_t global_variable_section_info_size = native_global_variable_section_info_array[0].header.total_size;
for (size_t i = 0; i < count; i++) {
Expand Down Expand Up @@ -1256,7 +1281,7 @@ _ebpf_native_initialize_maps(
for (uint32_t i = 0; i < map_count; i++) {
// Copy the map_entry_t from native module to ebpf_native_map_t.
map_entry_t* map_entry = (map_entry_t*)ARRAY_ELEMENT_INDEX(maps, i, map_entry_size);
memcpy(&native_maps[i].entry, map_entry, map_entry_size);
memcpy(&native_maps[i].entry, map_entry, min(map_entry_size, sizeof(native_maps[i].entry)));
map_entry_t* entry = &native_maps[i].entry;

if (entry->definition.pinning != LIBBPF_PIN_NONE && entry->definition.pinning != LIBBPF_PIN_BY_NAME) {
Expand Down Expand Up @@ -1555,7 +1580,10 @@ _ebpf_native_initialize_global_variables(
global_variables, i, global_variable_section_info_size);

// Copy the global variable section info.
memcpy(&local_global_section_info, global_variable_section_info, global_variable_section_info_size);
memcpy(
&local_global_section_info,
global_variable_section_info,
min(global_variable_section_info_size, sizeof(local_global_section_info)));
global_variable_section_info = NULL;

const ebpf_native_map_t* native_map = _ebpf_native_find_map_by_name(instance, local_global_section_info.name);
Expand Down Expand Up @@ -1825,7 +1853,7 @@ _ebpf_native_resolve_helpers_for_program(
helper_function_entry_t local_helper_entry = {0};
const helper_function_entry_t* entry =
(const helper_function_entry_t*)ARRAY_ELEMENT_INDEX(helper_info, i, helper_entry_size);
memcpy(&local_helper_entry, entry, helper_entry_size);
memcpy(&local_helper_entry, entry, min(helper_entry_size, sizeof(local_helper_entry)));

if (local_helper_entry.helper_id == 0) {
// Sentinel entry — this helper is not used by this program.
Expand Down Expand Up @@ -1977,7 +2005,10 @@ _ebpf_native_initialize_programs(_Inout_ ebpf_native_module_instance_t* instance
for (uint32_t i = 0; i < native_program->program_entry.helper_count; i++) {
const helper_function_entry_t* helper_entry =
(const helper_function_entry_t*)ARRAY_ELEMENT_INDEX(helper_info, i, helper_entry_size);
memcpy(&native_program->program_entry.helpers[i], helper_entry, helper_entry_size);
memcpy(
&native_program->program_entry.helpers[i],
helper_entry,
min(helper_entry_size, sizeof(native_program->program_entry.helpers[i])));
helper_entry = NULL;
}
}
Expand Down Expand Up @@ -2717,7 +2748,7 @@ _ebpf_native_helper_address_changed(
helper_function_entry_t local_helper_entry = {0};
const helper_function_entry_t* entry =
(const helper_function_entry_t*)ARRAY_ELEMENT_INDEX(helper_info, i, helper_entry_size);
memcpy(&local_helper_entry, entry, helper_entry_size);
memcpy(&local_helper_entry, entry, min(helper_entry_size, sizeof(local_helper_entry)));

if (local_helper_entry.helper_id == 0) {
// Sentinel entry — skip.
Expand Down
61 changes: 55 additions & 6 deletions libs/shared/shared_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,37 @@ uint16_t _supported_ebpf_extension_version[] = {
EBPF_NATIVE_GLOBAL_VARIABLE_SECTION_DATA_CURRENT_VERSION,
};

// Maximum "total_size" for each extension object type. An object's total_size covers the structure including any
// trailing padding, so it can never exceed the size of the current version of that structure.
size_t _ebpf_extension_type_max_total_size[] = {
// eBPF extension object maximum total sizes.
EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION_TOTAL_SIZE,
EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_TOTAL_SIZE,
EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_TOTAL_SIZE,
EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_TOTAL_SIZE,
EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION_TOTAL_SIZE,
EBPF_PROGRAM_DATA_CURRENT_VERSION_TOTAL_SIZE,
EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_TOTAL_SIZE,
EBPF_MAP_PROVIDER_DATA_CURRENT_VERSION_TOTAL_SIZE,
EBPF_MAP_CLIENT_DATA_CURRENT_VERSION_TOTAL_SIZE,
EBPF_BASE_MAP_PROVIDER_DISPATCH_TABLE_CURRENT_VERSION_TOTAL_SIZE,
EBPF_BASE_MAP_PROVIDER_PROPERTIES_CURRENT_VERSION_TOTAL_SIZE,
EBPF_BASE_MAP_CLIENT_DISPATCH_TABLE_CURRENT_VERSION_TOTAL_SIZE,
EBPF_BTF_RESOLVED_FUNCTION_PROTOTYPE_CURRENT_VERSION_TOTAL_SIZE,
EBPF_BTF_RESOLVED_FUNCTION_PROVIDER_DATA_CURRENT_VERSION_TOTAL_SIZE,

// eBPF native module object maximum total sizes.
EBPF_NATIVE_HELPER_FUNCTION_ENTRY_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_HELPER_FUNCTION_DATA_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_MAP_ENTRY_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_MAP_DATA_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_PROGRAM_ENTRY_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_PROGRAM_RUNTIME_CONTEXT_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_MAP_INITIAL_VALUES_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_GLOBAL_VARIABLE_SECTION_INFO_CURRENT_VERSION_TOTAL_SIZE,
EBPF_NATIVE_GLOBAL_VARIABLE_SECTION_DATA_CURRENT_VERSION_TOTAL_SIZE,
};

#define EBPF_ATTACH_PROVIDER_DATA_SIZE_1 EBPF_SIZE_INCLUDING_FIELD(ebpf_attach_provider_data_t, link_type)
size_t _ebpf_attach_provider_data_supported_size[] = {EBPF_ATTACH_PROVIDER_DATA_SIZE_1};

Expand Down Expand Up @@ -215,9 +246,22 @@ _ebpf_validate_extension_object_header(
uint16_t count = _ebpf_extension_type_supported_sizes[object_type].count;
__analysis_assume(supported_sizes != NULL);

return (
(header->version == _supported_ebpf_extension_version[object_type]) &&
(_ebpf_is_size_supported(supported_sizes, count, header->size)));
if (header->version != _supported_ebpf_extension_version[object_type]) {
return false;
}

if (!_ebpf_is_size_supported(supported_sizes, count, header->size)) {
return false;
}

// "total_size" is used as an array stride and as a copy length, so it must be bounded above: it can never
// exceed the size of the current version of the structure being copied into. Values smaller than "size"
// (including 0, which existing producers may leave unset) are not memory-unsafe and are tolerated.
if (header->total_size > _ebpf_extension_type_max_total_size[object_type]) {
return false;
}

return true;
}

#ifndef GUID_NULL
Expand Down Expand Up @@ -302,6 +346,10 @@ ebpf_validate_helper_function_prototype_array(
if (helper_prototype_array == NULL) {
return false;
}
// Validate the first element before using its "total_size" as the array stride.
if (!_ebpf_validate_helper_function_prototype(helper_prototype_array)) {
return false;
}
// Use "total_size" to calculate the actual size of the ebpf_helper_function_prototype_t struct.
size_t helper_prototype_size = helper_prototype_array[0].header.total_size;
for (uint32_t i = 0; i < count; i++) {
Expand Down Expand Up @@ -528,7 +576,7 @@ _duplicate_helper_function_prototype_array(
for (uint32_t i = 0; i < count; i++) {
ebpf_helper_function_prototype_t* helper_prototype =
(ebpf_helper_function_prototype_t*)ARRAY_ELEMENT_INDEX(helper_prototype_array, i, helper_prototype_size);
memcpy(&local_helper_prototype_array[i], helper_prototype, helper_prototype_size);
memcpy(&local_helper_prototype_array[i], helper_prototype, min(helper_prototype_size, sizeof(*helper_prototype)));
local_helper_prototype_array[i].header.version = EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION;
local_helper_prototype_array[i].header.size = EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE;
local_helper_prototype_array[i].header.total_size = EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_TOTAL_SIZE;
Expand All @@ -538,8 +586,9 @@ _duplicate_helper_function_prototype_array(
result = EBPF_NO_MEMORY;
goto Exit;
}
if (local_helper_prototype_array[i].header.size == EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION) {
local_helper_prototype_array[i].flags = helper_prototype[i].flags;
// Only copy the "flags" field if the source prototype is large enough to contain it.
if (helper_prototype->header.size >= EBPF_HELPER_FUNCTION_PROTOTYPE_SIZE_1) {
local_helper_prototype_array[i].flags = helper_prototype->flags;
}
}

Expand Down
Loading