eBPF for Windows
ebpf_store_helper.h
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation
2 // SPDX-License-Identifier: MIT
3 
4 #pragma once
5 
6 #include "ebpf_program_types.h"
7 #include "ebpf_registry_helper.h"
8 #include "ebpf_windows.h"
9 
10 #ifdef USER_MODE
11 extern ebpf_registry_key_t ebpf_root_registry_key;
12 #endif
13 
14 static uint32_t
15 _open_or_create_provider_registry_key(_Out_ ebpf_registry_key_t* provider_key)
16 {
17  __return_type status = _SUCCESS;
18  ebpf_registry_key_t root_key = NULL;
19  *provider_key = NULL;
20 
21  // Open (or create) root eBPF registry path.
22 #ifndef USER_MODE
24 #else
25  status = create_registry_key(ebpf_root_registry_key, EBPF_ROOT_RELATIVE_PATH, REG_CREATE_FLAGS, &root_key);
26 #endif
27  if (!IS_SUCCESS(status)) {
28  goto Exit;
29  }
30 
31  // Open (or create) program data registry path.
32  status = create_registry_key(root_key, EBPF_PROVIDERS_REGISTRY_PATH, REG_CREATE_FLAGS, provider_key);
33  if (!IS_SUCCESS(status)) {
34  goto Exit;
35  }
36 
37 Exit:
38  if (root_key) {
39  close_registry_key(root_key);
40  }
41  return status;
42 }
43 
44 static __return_type
45 _update_helper_prototype(ebpf_registry_key_t helper_info_key, _In_ const ebpf_helper_function_prototype_t* helper_info)
46 {
47  __return_type status = _SUCCESS;
48  uint32_t offset;
49  ebpf_registry_key_t helper_function_key = NULL;
50  char serialized_data[sizeof(ebpf_helper_function_prototype_t)] = {0};
51 
52  status = create_registry_key_ansi(helper_info_key, helper_info->name, REG_CREATE_FLAGS, &helper_function_key);
53  if (!IS_SUCCESS(status)) {
54  goto Exit;
55  }
56 
57  // Serialize the helper prototype.
58  offset = 0;
59  memcpy(serialized_data, &helper_info->helper_id, sizeof(helper_info->helper_id));
60  offset += sizeof(helper_info->helper_id);
61 
62  memcpy(serialized_data + offset, &helper_info->return_type, sizeof(helper_info->return_type));
63  offset += sizeof(helper_info->return_type);
64 
65  memcpy(serialized_data + offset, helper_info->arguments, sizeof(helper_info->arguments));
66  offset += sizeof(helper_info->arguments);
67 
68  // Save the helper prototype data.
70  helper_function_key, EBPF_HELPER_DATA_PROTOTYPE, (uint8_t*)&serialized_data[0], offset);
71  if (!IS_SUCCESS(status)) {
72  goto Exit;
73  }
74 
75 Exit:
76  if (helper_function_key) {
77  close_registry_key(helper_function_key);
78  }
79 
80  return status;
81 }
82 
91 static __return_type
92 ebpf_store_update_section_information(
93  _In_reads_(section_info_count) ebpf_program_section_info_t* section_info, uint32_t section_info_count)
94 {
95  __return_type status = _SUCCESS;
96  ebpf_registry_key_t provider_key = NULL;
97  ebpf_registry_key_t section_info_key = NULL;
98 
99  if (section_info_count == 0) {
100  return status;
101  }
102 
103  // Open (or create) provider registry path.
104  status = _open_or_create_provider_registry_key(&provider_key);
105  if (!IS_SUCCESS(status)) {
106  goto Exit;
107  }
108 
109  // Open (or create) section data key.
110  status = create_registry_key(provider_key, EBPF_SECTIONS_REGISTRY_PATH, REG_CREATE_FLAGS, &section_info_key);
111  if (!IS_SUCCESS(status)) {
112  goto Exit;
113  }
114 
115  for (uint32_t i = 0; i < section_info_count; i++) {
116  ebpf_registry_key_t section_key = NULL;
117 
118  // Open or create the registry path.
119  status = create_registry_key(section_info_key, section_info[i].section_name, REG_CREATE_FLAGS, &section_key);
120  if (!IS_SUCCESS(status)) {
121  goto Exit;
122  }
123 
124  // Save program type.
126  section_key,
128  (uint8_t*)section_info[i].program_type,
129  sizeof(ebpf_program_type_t));
130  if (!IS_SUCCESS(status)) {
131  close_registry_key(section_key);
132  goto Exit;
133  }
134 
135  // Save attach type.
137  section_key,
139  (uint8_t*)section_info[i].attach_type,
140  sizeof(ebpf_attach_type_t));
141  if (!IS_SUCCESS(status)) {
142  close_registry_key(section_key);
143  goto Exit;
144  }
145 
146  // Save bpf_prog_type.
147  status = write_registry_value_dword(section_key, EBPF_DATA_BPF_PROG_TYPE, section_info[i].bpf_program_type);
148  if (!IS_SUCCESS(status)) {
149  close_registry_key(section_key);
150  goto Exit;
151  }
152 
153  // Save bpf_attach_type.
154  status = write_registry_value_dword(section_key, EBPF_DATA_BPF_ATTACH_TYPE, section_info[i].bpf_attach_type);
155  if (!IS_SUCCESS(status)) {
156  close_registry_key(section_key);
157  goto Exit;
158  }
159 
160  close_registry_key(section_key);
161  }
162 
163 Exit:
164  if (section_info_key) {
165  close_registry_key(section_info_key);
166  }
167  if (provider_key) {
168  close_registry_key(provider_key);
169  }
170 
171  return status;
172 }
173 
182 static __return_type
183 ebpf_store_update_program_information(
184  _In_reads_(program_info_count) ebpf_program_info_t* program_info, uint32_t program_info_count)
185 {
186  __return_type status = _SUCCESS;
187  ebpf_registry_key_t provider_key = NULL;
188  ebpf_registry_key_t program_info_key = NULL;
189 
190  if (program_info_count == 0) {
191  return status;
192  }
193 
194  // Open (or create) provider registry path.
195  status = _open_or_create_provider_registry_key(&provider_key);
196  if (!IS_SUCCESS(status)) {
197  goto Exit;
198  }
199 
200  // Open (or create) program data registry path.
201  status = create_registry_key(provider_key, EBPF_PROGRAM_DATA_REGISTRY_PATH, REG_CREATE_FLAGS, &program_info_key);
202  if (!IS_SUCCESS(status)) {
203  goto Exit;
204  }
205 
206  for (uint32_t i = 0; i < program_info_count; i++) {
207  ebpf_registry_key_t program_key = {0};
208  ebpf_registry_key_t helper_info_key = {0};
209 
210  // Convert program type GUID to string.
211  wchar_t guid_string[GUID_STRING_LENGTH + 1];
212  status = convert_guid_to_string(
213  &program_info[i].program_type_descriptor.program_type, guid_string, GUID_STRING_LENGTH + 1);
214  if (status != _SUCCESS) {
215  return status;
216  }
217 
218  status = create_registry_key(program_info_key, guid_string, REG_CREATE_FLAGS, &program_key);
219  if (!IS_SUCCESS(status)) {
220  goto Exit;
221  }
222 
223  // Save the friendly program type name.
225  program_key, EBPF_PROGRAM_DATA_NAME, program_info[i].program_type_descriptor.name);
226  if (!IS_SUCCESS(status)) {
227  close_registry_key(program_key);
228  goto Exit;
229  }
230 
231  // Save context descriptor.
233  program_key,
235  (uint8_t*)program_info[i].program_type_descriptor.context_descriptor,
236  sizeof(ebpf_context_descriptor_t));
237  if (!IS_SUCCESS(status)) {
238  close_registry_key(program_key);
239  goto Exit;
240  }
241 
242  // Save bpf_prog_type.
244  program_key, EBPF_DATA_BPF_PROG_TYPE, program_info[i].program_type_descriptor.bpf_prog_type);
245  if (!IS_SUCCESS(status)) {
246  close_registry_key(program_key);
247  goto Exit;
248  }
249 
250  // Save "is_privileged".
252  program_key, EBPF_PROGRAM_DATA_PRIVILEGED, program_info[i].program_type_descriptor.is_privileged);
253  if (!IS_SUCCESS(status)) {
254  close_registry_key(program_key);
255  goto Exit;
256  }
257 
258  // Save helper count.
259  status =
260  write_registry_value_dword(program_key, EBPF_PROGRAM_DATA_HELPER_COUNT, program_info[i].count_of_helpers);
261  if (!IS_SUCCESS(status)) {
262  close_registry_key(program_key);
263  goto Exit;
264  }
265 
266  if (program_info[i].count_of_helpers != 0) {
267  // Create (or open) helper registry path.
268  status = create_registry_key(
269  program_key, EBPF_PROGRAM_DATA_HELPERS_REGISTRY_PATH, REG_CREATE_FLAGS, &helper_info_key);
270  if (!IS_SUCCESS(status)) {
271  close_registry_key(program_key);
272  goto Exit;
273  }
274 
275  // Iterate over all the helper prototypes and save in registry.
276  for (uint32_t count = 0; count < program_info[i].count_of_helpers; count++) {
277  status = _update_helper_prototype(helper_info_key, &(program_info[i].helper_prototype[count]));
278  if (!IS_SUCCESS(status)) {
279  close_registry_key(program_key);
280  close_registry_key(helper_info_key);
281  goto Exit;
282  }
283  }
284 
285  close_registry_key(helper_info_key);
286  }
287  close_registry_key(program_key);
288  }
289 
290 Exit:
291  if (program_info_key) {
292  close_registry_key(program_info_key);
293  }
294  if (provider_key) {
295  close_registry_key(provider_key);
296  }
297 
298  return status;
299 }
300 
309 static __return_type
310 ebpf_store_update_global_helper_information(
311  _In_reads_(helper_info_count) ebpf_helper_function_prototype_t* helper_info, uint32_t helper_info_count)
312 {
313  __return_type status = _SUCCESS;
314  ebpf_registry_key_t provider_key = NULL;
315  ebpf_registry_key_t helper_info_key = NULL;
316 
317  if (helper_info_count == 0) {
318  return status;
319  }
320 
321  // Open (or create) provider registry path.
322  status = _open_or_create_provider_registry_key(&provider_key);
323  if (!IS_SUCCESS(status)) {
324  goto Exit;
325  }
326 
327  // Open (or create) global helpers registry path.
328  status = create_registry_key(provider_key, EBPF_GLOBAL_HELPERS_REGISTRY_PATH, REG_CREATE_FLAGS, &helper_info_key);
329  if (!IS_SUCCESS(status)) {
330  goto Exit;
331  }
332 
333  for (uint32_t i = 0; i < helper_info_count; i++) {
334 
335  status = _update_helper_prototype(helper_info_key, &helper_info[i]);
336  if (!IS_SUCCESS(status)) {
337  goto Exit;
338  }
339  }
340 
341 Exit:
342  if (helper_info_key) {
343  close_registry_key(helper_info_key);
344  }
345  if (provider_key) {
346  close_registry_key(provider_key);
347  }
348 
349  return status;
350 }
_SUCCESS
#define _SUCCESS
Definition: ebpf_registry_helper.h:9
EBPF_PROGRAM_DATA_PRIVILEGED
#define EBPF_PROGRAM_DATA_PRIVILEGED
Definition: ebpf_windows.h:30
EBPF_PROGRAM_DATA_CONTEXT_DESCRIPTOR
#define EBPF_PROGRAM_DATA_CONTEXT_DESCRIPTOR
Definition: ebpf_windows.h:28
_ebpf_program_info
Definition: ebpf_program_types.h:41
write_registry_value_dword
_Must_inspect_result_ ebpf_registry_result_t write_registry_value_dword(ebpf_registry_key_t key, const wchar_t *value_name, uint32_t value)
REG_CREATE_FLAGS
#define REG_CREATE_FLAGS
Definition: ebpf_registry_helper.h:12
EBPF_ROOT_REGISTRY_PATH
#define EBPF_ROOT_REGISTRY_PATH
Definition: ebpf_windows.h:14
EBPF_HELPER_DATA_PROTOTYPE
#define EBPF_HELPER_DATA_PROTOTYPE
Definition: ebpf_windows.h:33
EBPF_SECTION_DATA_ATTACH_TYPE
#define EBPF_SECTION_DATA_ATTACH_TYPE
Definition: ebpf_windows.h:25
EBPF_DATA_BPF_PROG_TYPE
#define EBPF_DATA_BPF_PROG_TYPE
Definition: ebpf_windows.h:35
ebpf_helper_function_prototype_t
struct _ebpf_helper_function_prototype ebpf_helper_function_prototype_t
EBPF_SECTIONS_REGISTRY_PATH
#define EBPF_SECTIONS_REGISTRY_PATH
Definition: ebpf_windows.h:19
ebpf_registry_key_t
HANDLE ebpf_registry_key_t
Definition: ebpf_registry_helper.h:17
ebpf_windows.h
GUID_STRING_LENGTH
#define GUID_STRING_LENGTH
Definition: ebpf_registry_helper.h:13
EBPF_PROGRAM_DATA_REGISTRY_PATH
#define EBPF_PROGRAM_DATA_REGISTRY_PATH
Definition: ebpf_windows.h:20
_ebpf_program_section_info
Definition: ebpf_program_types.h:60
__return_type
#define __return_type
Definition: ebpf_registry_helper.h:8
close_registry_key
void close_registry_key(ebpf_registry_key_t key)
convert_guid_to_string
_Must_inspect_result_ ebpf_registry_result_t convert_guid_to_string(const GUID *guid, _Out_writes_all_(string_size) wchar_t *string, size_t string_size)
ebpf_program_type_t
GUID ebpf_program_type_t
Definition: ebpf_windows.h:38
EBPF_PROGRAM_DATA_NAME
#define EBPF_PROGRAM_DATA_NAME
Definition: ebpf_windows.h:27
create_registry_key_ansi
_Must_inspect_result_ ebpf_registry_result_t create_registry_key_ansi(ebpf_registry_key_t root_key, const char *sub_key, uint32_t flags, ebpf_registry_key_t *key)
bpf_attach_type
bpf_attach_type
Definition: ebpf_structs.h:239
ebpf_program_types.h
EBPF_PROGRAM_DATA_HELPER_COUNT
#define EBPF_PROGRAM_DATA_HELPER_COUNT
Definition: ebpf_windows.h:31
EBPF_SECTION_DATA_PROGRAM_TYPE
#define EBPF_SECTION_DATA_PROGRAM_TYPE
Definition: ebpf_windows.h:24
_ebpf_helper_function_prototype
Definition: ebpf_program_types.h:32
EBPF_DATA_BPF_ATTACH_TYPE
#define EBPF_DATA_BPF_ATTACH_TYPE
Definition: ebpf_windows.h:36
IS_SUCCESS
#define IS_SUCCESS(x)
Definition: ebpf_registry_helper.h:10
EBPF_PROVIDERS_REGISTRY_PATH
#define EBPF_PROVIDERS_REGISTRY_PATH
Definition: ebpf_windows.h:18
create_registry_key
_Must_inspect_result_ ebpf_registry_result_t create_registry_key(ebpf_registry_key_t root_key, const wchar_t *sub_key, uint32_t flags, ebpf_registry_key_t *key)
EBPF_PROGRAM_DATA_HELPERS_REGISTRY_PATH
#define EBPF_PROGRAM_DATA_HELPERS_REGISTRY_PATH
Definition: ebpf_windows.h:21
EBPF_GLOBAL_HELPERS_REGISTRY_PATH
#define EBPF_GLOBAL_HELPERS_REGISTRY_PATH
Definition: ebpf_windows.h:22
write_registry_value_binary
_Must_inspect_result_ ebpf_registry_result_t write_registry_value_binary(ebpf_registry_key_t key, const wchar_t *value_name, _In_reads_(value_size) uint8_t *value, size_t value_size)
write_registry_value_ansi_string
_Must_inspect_result_ ebpf_registry_result_t write_registry_value_ansi_string(ebpf_registry_key_t key, const wchar_t *value_name, const char *value)
ebpf_attach_type_t
GUID ebpf_attach_type_t
Definition: ebpf_windows.h:39
EBPF_ROOT_RELATIVE_PATH
#define EBPF_ROOT_RELATIVE_PATH
Definition: ebpf_windows.h:15