* Fix push/pop APIs on queues

Signed-off-by: Dave Thaler <dthaler@microsoft.com>

* Fix SAL warning

Signed-off-by: Dave Thaler <dthaler@microsoft.com>

* Remove deprecated code

Fixes #980

Signed-off-by: Dave Thaler <dthaler@microsoft.com>
This commit is contained in:
Dave Thaler 2022-04-20 15:09:36 -07:00 коммит произвёл GitHub
Родитель 70d5e42587
Коммит 2f484db0c7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 61 добавлений и 87 удалений

Просмотреть файл

@ -88,7 +88,6 @@ EXPORTS
ebpf_api_elf_verify_section_from_file
ebpf_api_elf_verify_section_from_memory
ebpf_api_elf_free
ebpf_api_link_program
ebpf_api_close_handle
ebpf_api_get_pinned_map_info
ebpf_api_map_info_free

Просмотреть файл

@ -238,20 +238,6 @@ extern "C"
uint32_t
ebpf_api_get_pinned_map(const uint8_t* name, uint32_t name_length, ebpf_handle_t* handle);
/**
* @brief Bind a program to an attach point and return a handle representing
* the link.
*
* @param[in] program_handle Handle to program to attach.
* @param[in] attach_type Attach point to attach program to.
* @param[out] link_handle Pointer to memory that contains the link handle
* on success.
* @retval ERROR_SUCCESS The operations succeeded.
* @retval ERROR_INVALID_PARAMETER One or more parameters are incorrect.
*/
uint32_t
ebpf_api_link_program(ebpf_handle_t program_handle, ebpf_attach_type_t attach_type, ebpf_handle_t* link_handle);
/**
* @brief Detach the eBPF program from the link.
*

Просмотреть файл

@ -216,15 +216,6 @@ ebpf_map_create(
fd_t
ebpf_program_get_fd(_In_ const struct bpf_program* program);
/**
* @brief Fetch fd for a map object.
*
* @param[in] map Pointer to eBPF map.
* @return fd for the map on success, ebpf_fd_invalid on failure.
*/
fd_t
ebpf_map_get_fd(_In_ const struct bpf_map* map);
/**
* @brief Clean up ebpf_object. Also delete all the sub objects
* (maps, programs) and close the related file descriptors.
@ -273,13 +264,13 @@ ebpf_map_set_pin_path(_In_ struct bpf_map* map, _In_ const char* path);
* @brief Update value for the specified key in an eBPF map.
*
* @param[in] map_fd File descriptor for the eBPF map.
* @param[in] key Pointer to buffer containing key.
* @param[in] key Pointer to buffer containing key, or NULL for a map with no keys.
* @param[out] value Pointer to buffer containing value.
*
* @retval EBPF_SUCCESS The operation was successful.
*/
ebpf_result_t
ebpf_map_update_element(fd_t map_fd, _In_ const void* key, _In_ const void* value, uint64_t flags);
ebpf_map_update_element(fd_t map_fd, _In_opt_ const void* key, _In_ const void* value, uint64_t flags);
/**
* @brief Delete an element in an eBPF map.
@ -313,13 +304,13 @@ ebpf_map_lookup_element(fd_t map_fd, _In_ const void* key, _Out_ void* value);
* On successful lookup, the element is removed from the map.
*
* @param[in] map_fd File descriptor for the eBPF map.
* @param[in] key Pointer to buffer containing key.
* @param[in] key Pointer to buffer containing key, or NULL for a map with no keys.
* @param[out] value Pointer to buffer that contains value on success.
*
* @retval EBPF_SUCCESS The operation was successful.
*/
ebpf_result_t
ebpf_map_lookup_and_delete_element(fd_t map_fd, _In_ const void* key, _Out_ void* value);
ebpf_map_lookup_and_delete_element(fd_t map_fd, _In_opt_ const void* key, _Out_ void* value);
/**
* @brief Return the next key in an eBPF map.

Просмотреть файл

@ -256,7 +256,7 @@ _map_lookup_element(
ebpf_handle_t handle,
bool find_and_delete,
uint32_t key_size,
_In_ const uint8_t* key,
_In_reads_opt_(key_size) const uint8_t* key,
uint32_t value_size,
_Out_ uint8_t* value) noexcept
{
@ -273,7 +273,9 @@ _map_lookup_element(
request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_FIND_ELEMENT;
request->find_and_delete = find_and_delete;
request->handle = handle;
std::copy(key, key + key_size, request->key);
if (key_size > 0) {
std::copy(key, key + key_size, request->key);
}
result = win32_error_code_to_ebpf_result(invoke_ioctl(request_buffer, reply_buffer));
@ -334,7 +336,7 @@ Exit:
}
static ebpf_result_t
_ebpf_map_lookup_element_helper(fd_t map_fd, bool find_and_delete, _In_ const void* key, _Out_ void* value)
_ebpf_map_lookup_element_helper(fd_t map_fd, bool find_and_delete, _In_opt_ const void* key, _Out_ void* value)
{
ebpf_result_t result = EBPF_SUCCESS;
ebpf_handle_t map_handle;
@ -343,7 +345,7 @@ _ebpf_map_lookup_element_helper(fd_t map_fd, bool find_and_delete, _In_ const vo
uint32_t max_entries = 0;
uint32_t type;
if (map_fd <= 0 || key == nullptr || value == nullptr) {
if (map_fd <= 0 || value == nullptr) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
@ -360,7 +362,10 @@ _ebpf_map_lookup_element_helper(fd_t map_fd, bool find_and_delete, _In_ const vo
if (result != EBPF_SUCCESS) {
goto Exit;
}
assert(key_size != 0);
if ((key == nullptr) != (key_size == 0)) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
assert(value_size != 0);
result = _map_lookup_element(map_handle, find_and_delete, key_size, (uint8_t*)key, value_size, (uint8_t*)value);
@ -376,7 +381,7 @@ ebpf_map_lookup_element(fd_t map_fd, _In_ const void* key, _Out_ void* value)
}
ebpf_result_t
ebpf_map_lookup_and_delete_element(fd_t map_fd, _In_ const void* key, _Out_ void* value)
ebpf_map_lookup_and_delete_element(fd_t map_fd, _In_opt_ const void* key, _Out_ void* value)
{
return _ebpf_map_lookup_element_helper(map_fd, true, key, value);
}
@ -384,7 +389,7 @@ ebpf_map_lookup_and_delete_element(fd_t map_fd, _In_ const void* key, _Out_ void
static ebpf_result_t
_update_map_element(
ebpf_handle_t map_handle,
_In_ const void* key,
_In_opt_ const void* key,
uint32_t key_size,
_In_ const void* value,
uint32_t value_size,
@ -402,7 +407,9 @@ _update_map_element(
request->header.id = ebpf_operation_id_t::EBPF_OPERATION_MAP_UPDATE_ELEMENT;
request->handle = (uint64_t)map_handle;
request->option = static_cast<ebpf_map_option_t>(flags);
std::copy((uint8_t*)key, (uint8_t*)key + key_size, request->data);
if (key_size > 0) {
std::copy((uint8_t*)key, (uint8_t*)key + key_size, request->data);
}
std::copy((uint8_t*)value, (uint8_t*)value + value_size, request->data + key_size);
result = win32_error_code_to_ebpf_result(invoke_ioctl(request_buffer));
@ -441,7 +448,7 @@ _update_map_element_with_handle(
}
ebpf_result_t
ebpf_map_update_element(fd_t map_fd, _In_ const void* key, _In_ const void* value, uint64_t flags)
ebpf_map_update_element(fd_t map_fd, _In_opt_ const void* key, _In_ const void* value, uint64_t flags)
{
ebpf_result_t result = EBPF_SUCCESS;
ebpf_handle_t map_handle;
@ -450,7 +457,7 @@ ebpf_map_update_element(fd_t map_fd, _In_ const void* key, _In_ const void* valu
uint32_t max_entries = 0;
uint32_t type;
if (map_fd <= 0 || key == nullptr || value == nullptr) {
if (map_fd <= 0 || value == nullptr) {
return EBPF_INVALID_ARGUMENT;
}
@ -473,7 +480,9 @@ ebpf_map_update_element(fd_t map_fd, _In_ const void* key, _In_ const void* valu
if (result != EBPF_SUCCESS) {
return result;
}
assert(key_size != 0);
if ((key == nullptr) != (key_size == 0)) {
return EBPF_INVALID_ARGUMENT;
}
assert(value_size != 0);
assert(type != 0);
@ -489,6 +498,8 @@ ebpf_map_update_element(fd_t map_fd, _In_ const void* key, _In_ const void* valu
}
}
assert(key_size != 0);
__analysis_assume(key_size != 0);
return _update_map_element_with_handle(map_handle, key_size, (const uint8_t*)key, handle, flags);
} else {
return _update_map_element(map_handle, key, key_size, value, value_size, flags);
@ -605,12 +616,12 @@ ebpf_map_get_next_key(fd_t map_fd, _In_opt_ const void* previous_key, _Out_ void
result = win32_error_code_to_ebpf_result(invoke_ioctl(request_buffer, reply_buffer));
if (reply->header.id != ebpf_operation_id_t::EBPF_OPERATION_MAP_GET_NEXT_KEY) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if (result == EBPF_SUCCESS) {
if (reply->header.id != ebpf_operation_id_t::EBPF_OPERATION_MAP_GET_NEXT_KEY) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
std::copy(reply->next_key, reply->next_key + key_size, (uint8_t*)next_key);
}
} catch (const std::bad_alloc&) {
@ -963,29 +974,6 @@ ebpf_program_query_info(
return win32_error_code_to_ebpf_result(retval);
}
uint32_t
ebpf_api_link_program(ebpf_handle_t program_handle, ebpf_attach_type_t attach_type, ebpf_handle_t* link_handle)
{
ebpf_operation_link_program_request_t request = {
EBPF_OFFSET_OF(ebpf_operation_link_program_request_t, data),
EBPF_OPERATION_LINK_PROGRAM,
program_handle,
attach_type};
ebpf_operation_link_program_reply_t reply;
uint32_t retval = invoke_ioctl(request, reply);
if (retval != ERROR_SUCCESS) {
return retval;
}
if (reply.header.id != ebpf_operation_id_t::EBPF_OPERATION_LINK_PROGRAM) {
return ERROR_INVALID_PARAMETER;
}
*link_handle = reply.link_handle;
return retval;
}
static ebpf_result_t
_link_ebpf_program(
ebpf_handle_t program_handle,
@ -2663,15 +2651,6 @@ ebpf_program_get_fd(_In_ const struct bpf_program* program)
return program->fd;
}
fd_t
ebpf_map_get_fd(_In_ const struct bpf_map* map)
{
if (map == nullptr) {
return ebpf_fd_invalid;
}
return map->map_fd;
}
void
ebpf_object_close(_In_opt_ _Post_invalid_ struct bpf_object* object)
{

Просмотреть файл

@ -1359,10 +1359,13 @@ static ebpf_result_t
_find_circular_map_entry(
_In_ ebpf_core_map_t* map, _In_opt_ const uint8_t* key, _In_ bool delete_on_success, _Outptr_ uint8_t** data)
{
// Queue uses no key, so key must be NULL.
if (!map || key)
if (!map)
return EBPF_INVALID_ARGUMENT;
// Queue uses no key, but the caller always passes in a non-null pointer (with a 0 key size)
// so we cannot require key to be null.
UNREFERENCED_PARAMETER(key);
ebpf_core_circular_map_t* circular_map = EBPF_FROM_FIELD(ebpf_core_circular_map_t, core_map, map);
ebpf_lock_state_t state = ebpf_lock_lock(&circular_map->lock);
*data = _ebpf_core_circular_map_peek_or_pop(circular_map, delete_on_success);
@ -1375,10 +1378,14 @@ _update_circular_map_entry(
_In_ ebpf_core_map_t* map, _In_ const uint8_t* key, _In_opt_ const uint8_t* data, ebpf_map_option_t option)
{
ebpf_result_t result;
// Queue uses no key, so key must be NULL.
if (!map || key || !data)
if (!map || !data)
return EBPF_INVALID_ARGUMENT;
// Queue uses no key, but the caller always passes in a non-null pointer (with a 0 key size)
// so we cannot require key to be null.
UNREFERENCED_PARAMETER(key);
ebpf_core_circular_map_t* circular_map = EBPF_FROM_FIELD(ebpf_core_circular_map_t, core_map, map);
ebpf_lock_state_t state = ebpf_lock_lock(&circular_map->lock);
result = _ebpf_core_circular_map_push(circular_map, data, option & BPF_EXIST);
@ -1947,7 +1954,7 @@ ebpf_map_update_entry(
switch (map->ebpf_map_definition.type) {
case BPF_MAP_TYPE_QUEUE:
case BPF_MAP_TYPE_STACK:
if (key_size != 0 || key != NULL) {
if (key_size != 0) {
EBPF_LOG_MESSAGE_UINT64(
EBPF_TRACELOG_LEVEL_ERROR,
EBPF_TRACELOG_KEYWORD_MAP,

Просмотреть файл

@ -110,12 +110,6 @@ typedef class _single_instance_hook : public _hook_helper
ebpf_provider_unload(provider);
}
uint32_t
attach(ebpf_handle_t program_handle)
{
return ebpf_api_link_program(program_handle, attach_type, &link_handle);
}
uint32_t
attach(bpf_program* program)
{

Просмотреть файл

@ -470,6 +470,24 @@ TEST_CASE("libbpf create queue", "[libbpf]")
int err = bpf_map_get_next_key(map_fd, NULL, &next_key);
REQUIRE(err == -ENOTSUP);
// Push 2 elements.
uint32_t value = 1;
REQUIRE(bpf_map_update_elem(map_fd, nullptr, &value, 0) == 0);
value = 2;
REQUIRE(bpf_map_update_elem(map_fd, nullptr, &value, 0) == 0);
// Pop elements.
REQUIRE(bpf_map_lookup_elem(map_fd, nullptr, &value) == 0);
REQUIRE(value == 1);
REQUIRE(bpf_map_lookup_and_delete_elem(map_fd, nullptr, &value) == 0);
REQUIRE(value == 1);
REQUIRE(bpf_map_lookup_elem(map_fd, nullptr, &value) == 0);
REQUIRE(value == 2);
REQUIRE(bpf_map_lookup_and_delete_elem(map_fd, nullptr, &value) == 0);
REQUIRE(value == 2);
REQUIRE(bpf_map_lookup_elem(map_fd, nullptr, &value) == -ENOENT);
REQUIRE(bpf_map_lookup_and_delete_elem(map_fd, nullptr, &value) == -ENOENT);
Platform::_close(map_fd);
}