Commit | Line | Data |
---|---|---|
e6a39346 JR |
1 | /* |
2 | * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com> | |
3 | * | |
4 | * SPDX-License-Identifier: LGPL-2.1-only | |
5 | * | |
6 | */ | |
7 | ||
c9e313bc SM |
8 | #include <common/credentials.hpp> |
9 | #include <common/error.hpp> | |
10 | #include <common/hashtable/hashtable.hpp> | |
11 | #include <common/hashtable/utils.hpp> | |
12 | #include <common/macros.hpp> | |
13 | #include <common/mi-lttng.hpp> | |
14 | #include <common/payload-view.hpp> | |
15 | #include <common/payload.hpp> | |
16 | #include <common/runas.hpp> | |
17 | #include <common/string-utils/string-utils.hpp> | |
28ab034a | 18 | |
c9e313bc SM |
19 | #include <lttng/event-rule/event-rule-internal.hpp> |
20 | #include <lttng/event-rule/kernel-syscall-internal.hpp> | |
e6a39346 JR |
21 | |
22 | #define IS_SYSCALL_EVENT_RULE(rule) \ | |
4f7da553 | 23 | (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL) |
e6a39346 | 24 | |
4f7da553 | 25 | static void lttng_event_rule_kernel_syscall_destroy(struct lttng_event_rule *rule) |
e6a39346 | 26 | { |
4f7da553 | 27 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 | 28 | |
cd9adb8b | 29 | if (rule == nullptr) { |
e6a39346 JR |
30 | return; |
31 | } | |
32 | ||
0114db0e | 33 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
34 | |
35 | free(syscall->pattern); | |
36 | free(syscall->filter_expression); | |
37 | free(syscall->internal_filter.filter); | |
38 | free(syscall->internal_filter.bytecode); | |
39 | free(syscall); | |
40 | } | |
41 | ||
28ab034a | 42 | static bool lttng_event_rule_kernel_syscall_validate(const struct lttng_event_rule *rule) |
e6a39346 JR |
43 | { |
44 | bool valid = false; | |
4f7da553 | 45 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 JR |
46 | |
47 | if (!rule) { | |
48 | goto end; | |
49 | } | |
50 | ||
0114db0e | 51 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
52 | |
53 | /* Required field. */ | |
54 | if (!syscall->pattern) { | |
55 | ERR("Invalid syscall event rule: a pattern must be set."); | |
56 | goto end; | |
57 | } | |
58 | ||
59 | valid = true; | |
60 | end: | |
61 | return valid; | |
62 | } | |
63 | ||
28ab034a JG |
64 | static int lttng_event_rule_kernel_syscall_serialize(const struct lttng_event_rule *rule, |
65 | struct lttng_payload *payload) | |
e6a39346 JR |
66 | { |
67 | int ret; | |
68 | size_t pattern_len, filter_expression_len; | |
4f7da553 JR |
69 | struct lttng_event_rule_kernel_syscall *syscall; |
70 | struct lttng_event_rule_kernel_syscall_comm syscall_comm; | |
e6a39346 JR |
71 | |
72 | if (!rule || !IS_SYSCALL_EVENT_RULE(rule)) { | |
73 | ret = -1; | |
74 | goto end; | |
75 | } | |
76 | ||
77 | DBG("Serializing syscall event rule"); | |
0114db0e | 78 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
79 | |
80 | pattern_len = strlen(syscall->pattern) + 1; | |
81 | ||
cd9adb8b | 82 | if (syscall->filter_expression != nullptr) { |
e6a39346 JR |
83 | filter_expression_len = strlen(syscall->filter_expression) + 1; |
84 | } else { | |
85 | filter_expression_len = 0; | |
86 | } | |
87 | ||
88 | syscall_comm.pattern_len = pattern_len; | |
89 | syscall_comm.filter_expression_len = filter_expression_len; | |
f6a5af19 | 90 | syscall_comm.emission_site = syscall->emission_site; |
e6a39346 | 91 | |
28ab034a | 92 | ret = lttng_dynamic_buffer_append(&payload->buffer, &syscall_comm, sizeof(syscall_comm)); |
e6a39346 JR |
93 | if (ret) { |
94 | goto end; | |
95 | } | |
96 | ||
28ab034a | 97 | ret = lttng_dynamic_buffer_append(&payload->buffer, syscall->pattern, pattern_len); |
e6a39346 JR |
98 | if (ret) { |
99 | goto end; | |
100 | } | |
101 | ||
28ab034a JG |
102 | ret = lttng_dynamic_buffer_append( |
103 | &payload->buffer, syscall->filter_expression, filter_expression_len); | |
e6a39346 JR |
104 | end: |
105 | return ret; | |
106 | } | |
107 | ||
4f7da553 | 108 | static bool lttng_event_rule_kernel_syscall_is_equal(const struct lttng_event_rule *_a, |
28ab034a | 109 | const struct lttng_event_rule *_b) |
e6a39346 JR |
110 | { |
111 | bool is_equal = false; | |
4f7da553 | 112 | struct lttng_event_rule_kernel_syscall *a, *b; |
e6a39346 | 113 | |
0114db0e JG |
114 | a = lttng::utils::container_of(_a, <tng_event_rule_kernel_syscall::parent); |
115 | b = lttng::utils::container_of(_b, <tng_event_rule_kernel_syscall::parent); | |
e6a39346 JR |
116 | |
117 | if (!!a->filter_expression != !!b->filter_expression) { | |
118 | goto end; | |
119 | } | |
120 | ||
a0377dfe FD |
121 | LTTNG_ASSERT(a->pattern); |
122 | LTTNG_ASSERT(b->pattern); | |
5c7248cd | 123 | if (strcmp(a->pattern, b->pattern) != 0) { |
e6a39346 JR |
124 | goto end; |
125 | } | |
126 | ||
127 | if (a->filter_expression && b->filter_expression) { | |
5c7248cd | 128 | if (strcmp(a->filter_expression, b->filter_expression) != 0) { |
e6a39346 JR |
129 | goto end; |
130 | } | |
131 | } else if (!!a->filter_expression != !!b->filter_expression) { | |
132 | /* One is set and not the other. */ | |
133 | goto end; | |
134 | } | |
135 | ||
8ab63dfb JG |
136 | if (a->emission_site != b->emission_site) { |
137 | goto end; | |
138 | } | |
139 | ||
e6a39346 JR |
140 | is_equal = true; |
141 | end: | |
142 | return is_equal; | |
143 | } | |
144 | ||
28ab034a JG |
145 | static enum lttng_error_code |
146 | lttng_event_rule_kernel_syscall_generate_filter_bytecode(struct lttng_event_rule *rule, | |
147 | const struct lttng_credentials *creds) | |
e6a39346 JR |
148 | { |
149 | int ret; | |
150 | enum lttng_error_code ret_code = LTTNG_OK; | |
4f7da553 | 151 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 JR |
152 | enum lttng_event_rule_status status; |
153 | const char *filter; | |
cd9adb8b | 154 | struct lttng_bytecode *bytecode = nullptr; |
e6a39346 | 155 | |
a0377dfe | 156 | LTTNG_ASSERT(rule); |
e6a39346 | 157 | |
0114db0e | 158 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
159 | |
160 | /* Generate the filter bytecode. */ | |
4f7da553 | 161 | status = lttng_event_rule_kernel_syscall_get_filter(rule, &filter); |
e6a39346 | 162 | if (status == LTTNG_EVENT_RULE_STATUS_UNSET) { |
cd9adb8b | 163 | filter = nullptr; |
e6a39346 JR |
164 | } else if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
165 | ret_code = LTTNG_ERR_FILTER_INVAL; | |
166 | goto end; | |
167 | } | |
168 | ||
169 | if (filter && filter[0] == '\0') { | |
170 | ret_code = LTTNG_ERR_FILTER_INVAL; | |
171 | goto end; | |
172 | } | |
173 | ||
cd9adb8b | 174 | if (filter == nullptr) { |
e6a39346 JR |
175 | /* Nothing to do. */ |
176 | ret = LTTNG_OK; | |
177 | goto end; | |
178 | } | |
179 | ||
180 | syscall->internal_filter.filter = strdup(filter); | |
cd9adb8b | 181 | if (syscall->internal_filter.filter == nullptr) { |
e6a39346 JR |
182 | ret_code = LTTNG_ERR_NOMEM; |
183 | goto end; | |
184 | } | |
185 | ||
28ab034a | 186 | ret = run_as_generate_filter_bytecode(syscall->internal_filter.filter, creds, &bytecode); |
e6a39346 JR |
187 | if (ret) { |
188 | ret_code = LTTNG_ERR_FILTER_INVAL; | |
189 | } | |
190 | ||
191 | syscall->internal_filter.bytecode = bytecode; | |
cd9adb8b | 192 | bytecode = nullptr; |
e6a39346 JR |
193 | |
194 | end: | |
195 | free(bytecode); | |
196 | return ret_code; | |
197 | } | |
198 | ||
28ab034a JG |
199 | static const char * |
200 | lttng_event_rule_kernel_syscall_get_internal_filter(const struct lttng_event_rule *rule) | |
e6a39346 | 201 | { |
4f7da553 | 202 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 | 203 | |
a0377dfe | 204 | LTTNG_ASSERT(rule); |
0114db0e | 205 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
206 | |
207 | return syscall->internal_filter.filter; | |
208 | } | |
209 | ||
2b00d462 | 210 | static const struct lttng_bytecode * |
28ab034a | 211 | lttng_event_rule_kernel_syscall_get_internal_filter_bytecode(const struct lttng_event_rule *rule) |
e6a39346 | 212 | { |
4f7da553 | 213 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 | 214 | |
a0377dfe | 215 | LTTNG_ASSERT(rule); |
0114db0e | 216 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
217 | |
218 | return syscall->internal_filter.bytecode; | |
219 | } | |
220 | ||
993578ff | 221 | static enum lttng_event_rule_generate_exclusions_status |
28ab034a JG |
222 | lttng_event_rule_kernel_syscall_generate_exclusions(const struct lttng_event_rule *rule |
223 | __attribute__((unused)), | |
224 | struct lttng_event_exclusion **exclusions) | |
e6a39346 | 225 | { |
993578ff | 226 | /* Unsupported. */ |
cd9adb8b | 227 | *exclusions = nullptr; |
993578ff | 228 | return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE; |
e6a39346 JR |
229 | } |
230 | ||
28ab034a | 231 | static unsigned long lttng_event_rule_kernel_syscall_hash(const struct lttng_event_rule *rule) |
959e3c66 JR |
232 | { |
233 | unsigned long hash; | |
4f7da553 | 234 | struct lttng_event_rule_kernel_syscall *syscall_rule = |
28ab034a | 235 | lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
959e3c66 | 236 | |
28ab034a | 237 | hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL, lttng_ht_seed); |
959e3c66 JR |
238 | hash ^= hash_key_str(syscall_rule->pattern, lttng_ht_seed); |
239 | if (syscall_rule->filter_expression) { | |
28ab034a | 240 | hash ^= hash_key_str(syscall_rule->filter_expression, lttng_ht_seed); |
959e3c66 JR |
241 | } |
242 | ||
243 | return hash; | |
244 | } | |
245 | ||
28ab034a JG |
246 | static enum lttng_error_code |
247 | lttng_event_rule_kernel_syscall_mi_serialize(const struct lttng_event_rule *rule, | |
248 | struct mi_writer *writer) | |
6a751b95 JR |
249 | { |
250 | int ret; | |
251 | enum lttng_error_code ret_code; | |
252 | enum lttng_event_rule_status status; | |
253 | ||
254 | enum lttng_event_rule_kernel_syscall_emission_site site_type; | |
cd9adb8b JG |
255 | const char *filter = nullptr; |
256 | const char *name_pattern = nullptr; | |
257 | const char *site_type_str = nullptr; | |
6a751b95 | 258 | |
a0377dfe FD |
259 | LTTNG_ASSERT(rule); |
260 | LTTNG_ASSERT(writer); | |
261 | LTTNG_ASSERT(IS_SYSCALL_EVENT_RULE(rule)); | |
6a751b95 | 262 | |
28ab034a | 263 | status = lttng_event_rule_kernel_syscall_get_name_pattern(rule, &name_pattern); |
a0377dfe FD |
264 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
265 | LTTNG_ASSERT(name_pattern); | |
6a751b95 JR |
266 | |
267 | status = lttng_event_rule_kernel_syscall_get_filter(rule, &filter); | |
a0377dfe | 268 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK || |
28ab034a | 269 | status == LTTNG_EVENT_RULE_STATUS_UNSET); |
6a751b95 JR |
270 | |
271 | site_type = lttng_event_rule_kernel_syscall_get_emission_site(rule); | |
272 | ||
273 | switch (site_type) { | |
274 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT: | |
275 | site_type_str = mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit; | |
276 | break; | |
277 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY: | |
278 | site_type_str = mi_lttng_event_rule_kernel_syscall_emission_site_entry; | |
279 | break; | |
280 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT: | |
281 | site_type_str = mi_lttng_event_rule_kernel_syscall_emission_site_exit; | |
282 | break; | |
283 | default: | |
284 | abort(); | |
285 | break; | |
286 | } | |
287 | ||
288 | /* Open event rule kernel syscall element. */ | |
28ab034a | 289 | ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_rule_kernel_syscall); |
6a751b95 JR |
290 | if (ret) { |
291 | goto mi_error; | |
292 | } | |
293 | ||
294 | /* Emission site. */ | |
28ab034a JG |
295 | ret = mi_lttng_writer_write_element_string( |
296 | writer, mi_lttng_element_event_rule_kernel_syscall_emission_site, site_type_str); | |
6a751b95 JR |
297 | if (ret) { |
298 | goto mi_error; | |
299 | } | |
300 | ||
301 | /* Name pattern. */ | |
28ab034a JG |
302 | ret = mi_lttng_writer_write_element_string( |
303 | writer, mi_lttng_element_event_rule_name_pattern, name_pattern); | |
6a751b95 JR |
304 | if (ret) { |
305 | goto mi_error; | |
306 | } | |
307 | ||
308 | /* Filter. */ | |
cd9adb8b | 309 | if (filter != nullptr) { |
28ab034a JG |
310 | ret = mi_lttng_writer_write_element_string( |
311 | writer, mi_lttng_element_event_rule_filter_expression, filter); | |
6a751b95 JR |
312 | if (ret) { |
313 | goto mi_error; | |
314 | } | |
315 | } | |
316 | ||
317 | /* Close event rule kernel syscall. */ | |
318 | ret = mi_lttng_writer_close_element(writer); | |
319 | if (ret) { | |
320 | goto mi_error; | |
321 | } | |
322 | ||
323 | ret_code = LTTNG_OK; | |
324 | goto end; | |
325 | ||
326 | mi_error: | |
327 | ret_code = LTTNG_ERR_MI_IO_FAIL; | |
328 | end: | |
329 | return ret_code; | |
330 | } | |
331 | ||
4f7da553 | 332 | struct lttng_event_rule *lttng_event_rule_kernel_syscall_create( |
28ab034a | 333 | enum lttng_event_rule_kernel_syscall_emission_site emission_site) |
e6a39346 | 334 | { |
cd9adb8b | 335 | struct lttng_event_rule *rule = nullptr; |
4f7da553 | 336 | struct lttng_event_rule_kernel_syscall *syscall_rule; |
67d38b93 | 337 | enum lttng_event_rule_status status; |
e6a39346 | 338 | |
57739a6b | 339 | /* Validate the emission site type */ |
f6a5af19 | 340 | switch (emission_site) { |
4f7da553 JR |
341 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT: |
342 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY: | |
343 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT: | |
57739a6b JR |
344 | break; |
345 | default: | |
346 | /* Invalid emission type */ | |
347 | goto end; | |
348 | } | |
349 | ||
64803277 | 350 | syscall_rule = zmalloc<lttng_event_rule_kernel_syscall>(); |
e6a39346 JR |
351 | if (!syscall_rule) { |
352 | goto end; | |
353 | } | |
354 | ||
355 | rule = &syscall_rule->parent; | |
28ab034a | 356 | lttng_event_rule_init(&syscall_rule->parent, LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL); |
4f7da553 JR |
357 | syscall_rule->parent.validate = lttng_event_rule_kernel_syscall_validate; |
358 | syscall_rule->parent.serialize = lttng_event_rule_kernel_syscall_serialize; | |
359 | syscall_rule->parent.equal = lttng_event_rule_kernel_syscall_is_equal; | |
360 | syscall_rule->parent.destroy = lttng_event_rule_kernel_syscall_destroy; | |
e6a39346 | 361 | syscall_rule->parent.generate_filter_bytecode = |
28ab034a JG |
362 | lttng_event_rule_kernel_syscall_generate_filter_bytecode; |
363 | syscall_rule->parent.get_filter = lttng_event_rule_kernel_syscall_get_internal_filter; | |
e6a39346 | 364 | syscall_rule->parent.get_filter_bytecode = |
28ab034a | 365 | lttng_event_rule_kernel_syscall_get_internal_filter_bytecode; |
e6a39346 | 366 | syscall_rule->parent.generate_exclusions = |
28ab034a | 367 | lttng_event_rule_kernel_syscall_generate_exclusions; |
4f7da553 | 368 | syscall_rule->parent.hash = lttng_event_rule_kernel_syscall_hash; |
6a751b95 | 369 | syscall_rule->parent.mi_serialize = lttng_event_rule_kernel_syscall_mi_serialize; |
67d38b93 JR |
370 | |
371 | /* Default pattern is '*'. */ | |
4f7da553 | 372 | status = lttng_event_rule_kernel_syscall_set_name_pattern(rule, "*"); |
67d38b93 JR |
373 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
374 | lttng_event_rule_destroy(rule); | |
cd9adb8b | 375 | rule = nullptr; |
67d38b93 JR |
376 | } |
377 | ||
57739a6b | 378 | /* Emission site type */ |
f6a5af19 | 379 | syscall_rule->emission_site = emission_site; |
57739a6b | 380 | |
e6a39346 JR |
381 | end: |
382 | return rule; | |
383 | } | |
384 | ||
28ab034a JG |
385 | ssize_t lttng_event_rule_kernel_syscall_create_from_payload(struct lttng_payload_view *view, |
386 | struct lttng_event_rule **_event_rule) | |
e6a39346 JR |
387 | { |
388 | ssize_t ret, offset = 0; | |
389 | enum lttng_event_rule_status status; | |
4f7da553 | 390 | const struct lttng_event_rule_kernel_syscall_comm *syscall_comm; |
e6a39346 | 391 | const char *pattern; |
cd9adb8b | 392 | const char *filter_expression = nullptr; |
e6a39346 | 393 | struct lttng_buffer_view current_buffer_view; |
cd9adb8b | 394 | struct lttng_event_rule *rule = nullptr; |
e6a39346 JR |
395 | |
396 | if (!_event_rule) { | |
397 | ret = -1; | |
398 | goto end; | |
399 | } | |
400 | ||
401 | if (view->buffer.size < sizeof(*syscall_comm)) { | |
402 | ERR("Failed to initialize from malformed event rule syscall: buffer too short to contain header"); | |
403 | ret = -1; | |
404 | goto end; | |
405 | } | |
406 | ||
28ab034a JG |
407 | current_buffer_view = |
408 | lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*syscall_comm)); | |
3e6e0df2 | 409 | if (!lttng_buffer_view_is_valid(¤t_buffer_view)) { |
e6a39346 JR |
410 | ret = -1; |
411 | goto end; | |
412 | } | |
413 | ||
3e6e0df2 | 414 | syscall_comm = (typeof(syscall_comm)) current_buffer_view.data; |
28ab034a JG |
415 | rule = lttng_event_rule_kernel_syscall_create( |
416 | (lttng_event_rule_kernel_syscall_emission_site) syscall_comm->emission_site); | |
e6a39346 JR |
417 | if (!rule) { |
418 | ERR("Failed to create event rule syscall"); | |
419 | ret = -1; | |
420 | goto end; | |
421 | } | |
422 | ||
423 | /* Skip to payload. */ | |
424 | offset += current_buffer_view.size; | |
425 | ||
426 | /* Map the pattern. */ | |
28ab034a JG |
427 | current_buffer_view = |
428 | lttng_buffer_view_from_view(&view->buffer, offset, syscall_comm->pattern_len); | |
3e6e0df2 | 429 | if (!lttng_buffer_view_is_valid(¤t_buffer_view)) { |
e6a39346 JR |
430 | ret = -1; |
431 | goto end; | |
432 | } | |
433 | ||
3e6e0df2 | 434 | pattern = current_buffer_view.data; |
28ab034a JG |
435 | if (!lttng_buffer_view_contains_string( |
436 | ¤t_buffer_view, pattern, syscall_comm->pattern_len)) { | |
e6a39346 JR |
437 | ret = -1; |
438 | goto end; | |
439 | } | |
440 | ||
441 | /* Skip after the pattern. */ | |
442 | offset += syscall_comm->pattern_len; | |
443 | ||
444 | if (!syscall_comm->filter_expression_len) { | |
445 | goto skip_filter_expression; | |
446 | } | |
447 | ||
448 | /* Map the filter_expression. */ | |
28ab034a JG |
449 | current_buffer_view = lttng_buffer_view_from_view( |
450 | &view->buffer, offset, syscall_comm->filter_expression_len); | |
3e6e0df2 | 451 | if (!lttng_buffer_view_is_valid(¤t_buffer_view)) { |
e6a39346 JR |
452 | ret = -1; |
453 | goto end; | |
454 | } | |
455 | ||
3e6e0df2 | 456 | filter_expression = current_buffer_view.data; |
28ab034a JG |
457 | if (!lttng_buffer_view_contains_string( |
458 | ¤t_buffer_view, filter_expression, syscall_comm->filter_expression_len)) { | |
e6a39346 JR |
459 | ret = -1; |
460 | goto end; | |
461 | } | |
462 | ||
463 | /* Skip after the pattern. */ | |
464 | offset += syscall_comm->filter_expression_len; | |
465 | ||
466 | skip_filter_expression: | |
467 | ||
4f7da553 | 468 | status = lttng_event_rule_kernel_syscall_set_name_pattern(rule, pattern); |
e6a39346 JR |
469 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
470 | ERR("Failed to set event rule syscall pattern"); | |
471 | ret = -1; | |
472 | goto end; | |
473 | } | |
474 | ||
475 | if (filter_expression) { | |
28ab034a | 476 | status = lttng_event_rule_kernel_syscall_set_filter(rule, filter_expression); |
e6a39346 JR |
477 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
478 | ERR("Failed to set event rule syscall pattern"); | |
479 | ret = -1; | |
480 | goto end; | |
481 | } | |
482 | } | |
483 | ||
484 | *_event_rule = rule; | |
cd9adb8b | 485 | rule = nullptr; |
e6a39346 JR |
486 | ret = offset; |
487 | end: | |
488 | lttng_event_rule_destroy(rule); | |
489 | return ret; | |
490 | } | |
491 | ||
28ab034a JG |
492 | enum lttng_event_rule_status |
493 | lttng_event_rule_kernel_syscall_set_name_pattern(struct lttng_event_rule *rule, const char *pattern) | |
e6a39346 | 494 | { |
cd9adb8b | 495 | char *pattern_copy = nullptr; |
4f7da553 | 496 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 JR |
497 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; |
498 | ||
28ab034a | 499 | if (!rule || !IS_SYSCALL_EVENT_RULE(rule) || !pattern || strlen(pattern) == 0) { |
e6a39346 JR |
500 | status = LTTNG_EVENT_RULE_STATUS_INVALID; |
501 | goto end; | |
502 | } | |
503 | ||
0114db0e | 504 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
505 | pattern_copy = strdup(pattern); |
506 | if (!pattern_copy) { | |
507 | status = LTTNG_EVENT_RULE_STATUS_ERROR; | |
508 | goto end; | |
509 | } | |
510 | ||
40fd2ccf JR |
511 | strutils_normalize_star_glob_pattern(pattern_copy); |
512 | ||
513 | free(syscall->pattern); | |
e6a39346 JR |
514 | |
515 | syscall->pattern = pattern_copy; | |
cd9adb8b | 516 | pattern_copy = nullptr; |
e6a39346 JR |
517 | end: |
518 | return status; | |
519 | } | |
520 | ||
28ab034a JG |
521 | enum lttng_event_rule_status |
522 | lttng_event_rule_kernel_syscall_get_name_pattern(const struct lttng_event_rule *rule, | |
523 | const char **pattern) | |
e6a39346 | 524 | { |
4f7da553 | 525 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 JR |
526 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; |
527 | ||
528 | if (!rule || !IS_SYSCALL_EVENT_RULE(rule) || !pattern) { | |
529 | status = LTTNG_EVENT_RULE_STATUS_INVALID; | |
530 | goto end; | |
531 | } | |
532 | ||
0114db0e | 533 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
534 | if (!syscall->pattern) { |
535 | status = LTTNG_EVENT_RULE_STATUS_UNSET; | |
536 | goto end; | |
537 | } | |
538 | ||
539 | *pattern = syscall->pattern; | |
540 | end: | |
541 | return status; | |
542 | } | |
543 | ||
28ab034a JG |
544 | enum lttng_event_rule_status |
545 | lttng_event_rule_kernel_syscall_set_filter(struct lttng_event_rule *rule, const char *expression) | |
e6a39346 | 546 | { |
cd9adb8b | 547 | char *expression_copy = nullptr; |
4f7da553 | 548 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 JR |
549 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; |
550 | ||
551 | /* TODO: validate that the passed expression is valid. */ | |
552 | ||
28ab034a | 553 | if (!rule || !IS_SYSCALL_EVENT_RULE(rule) || !expression || strlen(expression) == 0) { |
e6a39346 JR |
554 | status = LTTNG_EVENT_RULE_STATUS_INVALID; |
555 | goto end; | |
556 | } | |
557 | ||
0114db0e | 558 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
559 | expression_copy = strdup(expression); |
560 | if (!expression_copy) { | |
561 | status = LTTNG_EVENT_RULE_STATUS_ERROR; | |
562 | goto end; | |
563 | } | |
564 | ||
565 | if (syscall->filter_expression) { | |
566 | free(syscall->filter_expression); | |
567 | } | |
568 | ||
569 | syscall->filter_expression = expression_copy; | |
cd9adb8b | 570 | expression_copy = nullptr; |
e6a39346 JR |
571 | end: |
572 | return status; | |
573 | } | |
574 | ||
28ab034a JG |
575 | enum lttng_event_rule_status |
576 | lttng_event_rule_kernel_syscall_get_filter(const struct lttng_event_rule *rule, | |
577 | const char **expression) | |
e6a39346 | 578 | { |
4f7da553 | 579 | struct lttng_event_rule_kernel_syscall *syscall; |
e6a39346 JR |
580 | enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK; |
581 | ||
582 | if (!rule || !IS_SYSCALL_EVENT_RULE(rule) || !expression) { | |
583 | status = LTTNG_EVENT_RULE_STATUS_INVALID; | |
584 | goto end; | |
585 | } | |
586 | ||
0114db0e | 587 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
e6a39346 JR |
588 | if (!syscall->filter_expression) { |
589 | status = LTTNG_EVENT_RULE_STATUS_UNSET; | |
590 | goto end; | |
591 | } | |
592 | ||
593 | *expression = syscall->filter_expression; | |
594 | end: | |
595 | return status; | |
596 | } | |
4f7da553 | 597 | extern enum lttng_event_rule_kernel_syscall_emission_site |
28ab034a | 598 | lttng_event_rule_kernel_syscall_get_emission_site(const struct lttng_event_rule *rule) |
57739a6b | 599 | { |
4f7da553 JR |
600 | enum lttng_event_rule_kernel_syscall_emission_site emission_site = |
601 | LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_UNKNOWN; | |
602 | struct lttng_event_rule_kernel_syscall *syscall; | |
57739a6b JR |
603 | |
604 | if (!rule || !IS_SYSCALL_EVENT_RULE(rule)) { | |
605 | goto end; | |
606 | } | |
607 | ||
0114db0e | 608 | syscall = lttng::utils::container_of(rule, <tng_event_rule_kernel_syscall::parent); |
f6a5af19 | 609 | emission_site = syscall->emission_site; |
57739a6b JR |
610 | |
611 | end: | |
f6a5af19 | 612 | return emission_site; |
57739a6b JR |
613 | } |
614 | ||
4f7da553 | 615 | const char *lttng_event_rule_kernel_syscall_emission_site_str( |
28ab034a | 616 | enum lttng_event_rule_kernel_syscall_emission_site emission_site) |
57739a6b | 617 | { |
f6a5af19 | 618 | switch (emission_site) { |
4f7da553 | 619 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY: |
57739a6b | 620 | return "entry"; |
4f7da553 | 621 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT: |
57739a6b | 622 | return "entry+exit"; |
4f7da553 | 623 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT: |
57739a6b JR |
624 | return "exit"; |
625 | default: | |
626 | return "???"; | |
627 | } | |
628 | } |