2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
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>
19 #include <lttng/event-rule/event-rule-internal.hpp>
20 #include <lttng/event-rule/kernel-syscall-internal.hpp>
22 #define IS_SYSCALL_EVENT_RULE(rule) \
23 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL)
25 static void lttng_event_rule_kernel_syscall_destroy(struct lttng_event_rule
*rule
)
27 struct lttng_event_rule_kernel_syscall
*syscall
;
29 if (rule
== nullptr) {
33 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
35 free(syscall
->pattern
);
36 free(syscall
->filter_expression
);
37 free(syscall
->internal_filter
.filter
);
38 free(syscall
->internal_filter
.bytecode
);
42 static bool lttng_event_rule_kernel_syscall_validate(const struct lttng_event_rule
*rule
)
45 struct lttng_event_rule_kernel_syscall
*syscall
;
51 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
54 if (!syscall
->pattern
) {
55 ERR("Invalid syscall event rule: a pattern must be set.");
64 static int lttng_event_rule_kernel_syscall_serialize(const struct lttng_event_rule
*rule
,
65 struct lttng_payload
*payload
)
68 size_t pattern_len
, filter_expression_len
;
69 struct lttng_event_rule_kernel_syscall
*syscall
;
70 struct lttng_event_rule_kernel_syscall_comm syscall_comm
;
72 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
77 DBG("Serializing syscall event rule");
78 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
80 pattern_len
= strlen(syscall
->pattern
) + 1;
82 if (syscall
->filter_expression
!= nullptr) {
83 filter_expression_len
= strlen(syscall
->filter_expression
) + 1;
85 filter_expression_len
= 0;
88 syscall_comm
.pattern_len
= pattern_len
;
89 syscall_comm
.filter_expression_len
= filter_expression_len
;
90 syscall_comm
.emission_site
= syscall
->emission_site
;
92 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &syscall_comm
, sizeof(syscall_comm
));
97 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, syscall
->pattern
, pattern_len
);
102 ret
= lttng_dynamic_buffer_append(
103 &payload
->buffer
, syscall
->filter_expression
, filter_expression_len
);
108 static bool lttng_event_rule_kernel_syscall_is_equal(const struct lttng_event_rule
*_a
,
109 const struct lttng_event_rule
*_b
)
111 bool is_equal
= false;
112 struct lttng_event_rule_kernel_syscall
*a
, *b
;
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
);
117 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
121 LTTNG_ASSERT(a
->pattern
);
122 LTTNG_ASSERT(b
->pattern
);
123 if (strcmp(a
->pattern
, b
->pattern
) != 0) {
127 if (a
->filter_expression
&& b
->filter_expression
) {
128 if (strcmp(a
->filter_expression
, b
->filter_expression
) != 0) {
131 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
132 /* One is set and not the other. */
136 if (a
->emission_site
!= b
->emission_site
) {
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
)
150 enum lttng_error_code ret_code
= LTTNG_OK
;
151 struct lttng_event_rule_kernel_syscall
*syscall
;
152 enum lttng_event_rule_status status
;
154 struct lttng_bytecode
*bytecode
= nullptr;
158 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
160 /* Generate the filter bytecode. */
161 status
= lttng_event_rule_kernel_syscall_get_filter(rule
, &filter
);
162 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
164 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
165 ret_code
= LTTNG_ERR_FILTER_INVAL
;
169 if (filter
&& filter
[0] == '\0') {
170 ret_code
= LTTNG_ERR_FILTER_INVAL
;
174 if (filter
== nullptr) {
180 syscall
->internal_filter
.filter
= strdup(filter
);
181 if (syscall
->internal_filter
.filter
== nullptr) {
182 ret_code
= LTTNG_ERR_NOMEM
;
186 ret
= run_as_generate_filter_bytecode(syscall
->internal_filter
.filter
, creds
, &bytecode
);
188 ret_code
= LTTNG_ERR_FILTER_INVAL
;
191 syscall
->internal_filter
.bytecode
= bytecode
;
200 lttng_event_rule_kernel_syscall_get_internal_filter(const struct lttng_event_rule
*rule
)
202 struct lttng_event_rule_kernel_syscall
*syscall
;
205 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
207 return syscall
->internal_filter
.filter
;
210 static const struct lttng_bytecode
*
211 lttng_event_rule_kernel_syscall_get_internal_filter_bytecode(const struct lttng_event_rule
*rule
)
213 struct lttng_event_rule_kernel_syscall
*syscall
;
216 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
218 return syscall
->internal_filter
.bytecode
;
221 static enum lttng_event_rule_generate_exclusions_status
222 lttng_event_rule_kernel_syscall_generate_exclusions(const struct lttng_event_rule
*rule
223 __attribute__((unused
)),
224 struct lttng_event_exclusion
**exclusions
)
227 *exclusions
= nullptr;
228 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
231 static unsigned long lttng_event_rule_kernel_syscall_hash(const struct lttng_event_rule
*rule
)
234 struct lttng_event_rule_kernel_syscall
*syscall_rule
=
235 lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
237 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL
, lttng_ht_seed
);
238 hash
^= hash_key_str(syscall_rule
->pattern
, lttng_ht_seed
);
239 if (syscall_rule
->filter_expression
) {
240 hash
^= hash_key_str(syscall_rule
->filter_expression
, lttng_ht_seed
);
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
)
251 enum lttng_error_code ret_code
;
252 enum lttng_event_rule_status status
;
254 enum lttng_event_rule_kernel_syscall_emission_site site_type
;
255 const char *filter
= nullptr;
256 const char *name_pattern
= nullptr;
257 const char *site_type_str
= nullptr;
260 LTTNG_ASSERT(writer
);
261 LTTNG_ASSERT(IS_SYSCALL_EVENT_RULE(rule
));
263 status
= lttng_event_rule_kernel_syscall_get_name_pattern(rule
, &name_pattern
);
264 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
265 LTTNG_ASSERT(name_pattern
);
267 status
= lttng_event_rule_kernel_syscall_get_filter(rule
, &filter
);
268 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
||
269 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
271 site_type
= lttng_event_rule_kernel_syscall_get_emission_site(rule
);
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
;
277 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
278 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_entry
;
280 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
:
281 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_exit
;
288 /* Open event rule kernel syscall element. */
289 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_rule_kernel_syscall
);
295 ret
= mi_lttng_writer_write_element_string(
296 writer
, mi_lttng_element_event_rule_kernel_syscall_emission_site
, site_type_str
);
302 ret
= mi_lttng_writer_write_element_string(
303 writer
, mi_lttng_element_event_rule_name_pattern
, name_pattern
);
309 if (filter
!= nullptr) {
310 ret
= mi_lttng_writer_write_element_string(
311 writer
, mi_lttng_element_event_rule_filter_expression
, filter
);
317 /* Close event rule kernel syscall. */
318 ret
= mi_lttng_writer_close_element(writer
);
327 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
332 struct lttng_event_rule
*lttng_event_rule_kernel_syscall_create(
333 enum lttng_event_rule_kernel_syscall_emission_site emission_site
)
335 struct lttng_event_rule
*rule
= nullptr;
336 struct lttng_event_rule_kernel_syscall
*syscall_rule
;
337 enum lttng_event_rule_status status
;
339 /* Validate the emission site type */
340 switch (emission_site
) {
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
:
346 /* Invalid emission type */
350 syscall_rule
= zmalloc
<lttng_event_rule_kernel_syscall
>();
355 rule
= &syscall_rule
->parent
;
356 lttng_event_rule_init(&syscall_rule
->parent
, LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL
);
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
;
361 syscall_rule
->parent
.generate_filter_bytecode
=
362 lttng_event_rule_kernel_syscall_generate_filter_bytecode
;
363 syscall_rule
->parent
.get_filter
= lttng_event_rule_kernel_syscall_get_internal_filter
;
364 syscall_rule
->parent
.get_filter_bytecode
=
365 lttng_event_rule_kernel_syscall_get_internal_filter_bytecode
;
366 syscall_rule
->parent
.generate_exclusions
=
367 lttng_event_rule_kernel_syscall_generate_exclusions
;
368 syscall_rule
->parent
.hash
= lttng_event_rule_kernel_syscall_hash
;
369 syscall_rule
->parent
.mi_serialize
= lttng_event_rule_kernel_syscall_mi_serialize
;
371 /* Default pattern is '*'. */
372 status
= lttng_event_rule_kernel_syscall_set_name_pattern(rule
, "*");
373 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
374 lttng_event_rule_destroy(rule
);
378 /* Emission site type */
379 syscall_rule
->emission_site
= emission_site
;
385 ssize_t
lttng_event_rule_kernel_syscall_create_from_payload(struct lttng_payload_view
*view
,
386 struct lttng_event_rule
**_event_rule
)
388 ssize_t ret
, offset
= 0;
389 enum lttng_event_rule_status status
;
390 const struct lttng_event_rule_kernel_syscall_comm
*syscall_comm
;
392 const char *filter_expression
= nullptr;
393 struct lttng_buffer_view current_buffer_view
;
394 struct lttng_event_rule
*rule
= nullptr;
401 if (view
->buffer
.size
< sizeof(*syscall_comm
)) {
402 ERR("Failed to initialize from malformed event rule syscall: buffer too short to contain header");
407 current_buffer_view
=
408 lttng_buffer_view_from_view(&view
->buffer
, offset
, sizeof(*syscall_comm
));
409 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
414 syscall_comm
= (typeof(syscall_comm
)) current_buffer_view
.data
;
415 rule
= lttng_event_rule_kernel_syscall_create(
416 (lttng_event_rule_kernel_syscall_emission_site
) syscall_comm
->emission_site
);
418 ERR("Failed to create event rule syscall");
423 /* Skip to payload. */
424 offset
+= current_buffer_view
.size
;
426 /* Map the pattern. */
427 current_buffer_view
=
428 lttng_buffer_view_from_view(&view
->buffer
, offset
, syscall_comm
->pattern_len
);
429 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
434 pattern
= current_buffer_view
.data
;
435 if (!lttng_buffer_view_contains_string(
436 ¤t_buffer_view
, pattern
, syscall_comm
->pattern_len
)) {
441 /* Skip after the pattern. */
442 offset
+= syscall_comm
->pattern_len
;
444 if (!syscall_comm
->filter_expression_len
) {
445 goto skip_filter_expression
;
448 /* Map the filter_expression. */
449 current_buffer_view
= lttng_buffer_view_from_view(
450 &view
->buffer
, offset
, syscall_comm
->filter_expression_len
);
451 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
456 filter_expression
= current_buffer_view
.data
;
457 if (!lttng_buffer_view_contains_string(
458 ¤t_buffer_view
, filter_expression
, syscall_comm
->filter_expression_len
)) {
463 /* Skip after the pattern. */
464 offset
+= syscall_comm
->filter_expression_len
;
466 skip_filter_expression
:
468 status
= lttng_event_rule_kernel_syscall_set_name_pattern(rule
, pattern
);
469 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
470 ERR("Failed to set event rule syscall pattern");
475 if (filter_expression
) {
476 status
= lttng_event_rule_kernel_syscall_set_filter(rule
, filter_expression
);
477 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
478 ERR("Failed to set event rule syscall pattern");
488 lttng_event_rule_destroy(rule
);
492 enum lttng_event_rule_status
493 lttng_event_rule_kernel_syscall_set_name_pattern(struct lttng_event_rule
*rule
, const char *pattern
)
495 char *pattern_copy
= nullptr;
496 struct lttng_event_rule_kernel_syscall
*syscall
;
497 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
499 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
|| strlen(pattern
) == 0) {
500 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
504 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
505 pattern_copy
= strdup(pattern
);
507 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
511 strutils_normalize_star_glob_pattern(pattern_copy
);
513 free(syscall
->pattern
);
515 syscall
->pattern
= pattern_copy
;
516 pattern_copy
= nullptr;
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
)
525 struct lttng_event_rule_kernel_syscall
*syscall
;
526 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
528 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
) {
529 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
533 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
534 if (!syscall
->pattern
) {
535 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
539 *pattern
= syscall
->pattern
;
544 enum lttng_event_rule_status
545 lttng_event_rule_kernel_syscall_set_filter(struct lttng_event_rule
*rule
, const char *expression
)
547 char *expression_copy
= nullptr;
548 struct lttng_event_rule_kernel_syscall
*syscall
;
549 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
551 /* TODO: validate that the passed expression is valid. */
553 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
|| strlen(expression
) == 0) {
554 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
558 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
559 expression_copy
= strdup(expression
);
560 if (!expression_copy
) {
561 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
565 if (syscall
->filter_expression
) {
566 free(syscall
->filter_expression
);
569 syscall
->filter_expression
= expression_copy
;
570 expression_copy
= nullptr;
575 enum lttng_event_rule_status
576 lttng_event_rule_kernel_syscall_get_filter(const struct lttng_event_rule
*rule
,
577 const char **expression
)
579 struct lttng_event_rule_kernel_syscall
*syscall
;
580 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
582 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
) {
583 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
587 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
588 if (!syscall
->filter_expression
) {
589 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
593 *expression
= syscall
->filter_expression
;
597 extern enum lttng_event_rule_kernel_syscall_emission_site
598 lttng_event_rule_kernel_syscall_get_emission_site(const struct lttng_event_rule
*rule
)
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
;
604 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
608 syscall
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_syscall::parent
);
609 emission_site
= syscall
->emission_site
;
612 return emission_site
;
615 const char *lttng_event_rule_kernel_syscall_emission_site_str(
616 enum lttng_event_rule_kernel_syscall_emission_site emission_site
)
618 switch (emission_site
) {
619 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
621 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT
:
623 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
: