2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/credentials.h>
10 #include <common/error.h>
11 #include <common/hashtable/hashtable.h>
12 #include <common/hashtable/utils.h>
13 #include <common/macros.h>
14 #include <common/mi-lttng.h>
15 #include <common/payload-view.h>
16 #include <common/payload.h>
17 #include <common/runas.h>
18 #include <common/string-utils/string-utils.h>
19 #include <lttng/event-rule/event-rule-internal.h>
20 #include <lttng/event-rule/kernel-syscall-internal.h>
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
;
33 syscall
= container_of(rule
, struct lttng_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(
43 const struct lttng_event_rule
*rule
)
46 struct lttng_event_rule_kernel_syscall
*syscall
;
52 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
55 if (!syscall
->pattern
) {
56 ERR("Invalid syscall event rule: a pattern must be set.");
65 static int lttng_event_rule_kernel_syscall_serialize(
66 const struct lttng_event_rule
*rule
,
67 struct lttng_payload
*payload
)
70 size_t pattern_len
, filter_expression_len
;
71 struct lttng_event_rule_kernel_syscall
*syscall
;
72 struct lttng_event_rule_kernel_syscall_comm syscall_comm
;
74 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
79 DBG("Serializing syscall event rule");
80 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
82 pattern_len
= strlen(syscall
->pattern
) + 1;
84 if (syscall
->filter_expression
!= NULL
) {
85 filter_expression_len
= strlen(syscall
->filter_expression
) + 1;
87 filter_expression_len
= 0;
90 syscall_comm
.pattern_len
= pattern_len
;
91 syscall_comm
.filter_expression_len
= filter_expression_len
;
92 syscall_comm
.emission_site
= syscall
->emission_site
;
94 ret
= lttng_dynamic_buffer_append(
95 &payload
->buffer
, &syscall_comm
, sizeof(syscall_comm
));
100 ret
= lttng_dynamic_buffer_append(
101 &payload
->buffer
, syscall
->pattern
, pattern_len
);
106 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
107 syscall
->filter_expression
, filter_expression_len
);
112 static bool lttng_event_rule_kernel_syscall_is_equal(const struct lttng_event_rule
*_a
,
113 const struct lttng_event_rule
*_b
)
115 bool is_equal
= false;
116 struct lttng_event_rule_kernel_syscall
*a
, *b
;
118 a
= container_of(_a
, struct lttng_event_rule_kernel_syscall
, parent
);
119 b
= container_of(_b
, struct lttng_event_rule_kernel_syscall
, parent
);
121 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
127 if (strcmp(a
->pattern
, b
->pattern
)) {
131 if (a
->filter_expression
&& b
->filter_expression
) {
132 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
135 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
136 /* One is set and not the other. */
145 static enum lttng_error_code
lttng_event_rule_kernel_syscall_generate_filter_bytecode(
146 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
= NULL
;
158 syscall
= container_of(rule
, struct lttng_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
== NULL
) {
180 syscall
->internal_filter
.filter
= strdup(filter
);
181 if (syscall
->internal_filter
.filter
== NULL
) {
182 ret_code
= LTTNG_ERR_NOMEM
;
186 ret
= run_as_generate_filter_bytecode(
187 syscall
->internal_filter
.filter
, creds
, &bytecode
);
189 ret_code
= LTTNG_ERR_FILTER_INVAL
;
192 syscall
->internal_filter
.bytecode
= bytecode
;
200 static const char *lttng_event_rule_kernel_syscall_get_internal_filter(
201 const struct lttng_event_rule
*rule
)
203 struct lttng_event_rule_kernel_syscall
*syscall
;
206 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
208 return syscall
->internal_filter
.filter
;
211 static const struct lttng_bytecode
*
212 lttng_event_rule_kernel_syscall_get_internal_filter_bytecode(
213 const struct lttng_event_rule
*rule
)
215 struct lttng_event_rule_kernel_syscall
*syscall
;
218 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
220 return syscall
->internal_filter
.bytecode
;
223 static enum lttng_event_rule_generate_exclusions_status
224 lttng_event_rule_kernel_syscall_generate_exclusions(const struct lttng_event_rule
*rule
,
225 struct lttng_event_exclusion
**exclusions
)
229 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
233 lttng_event_rule_kernel_syscall_hash(
234 const struct lttng_event_rule
*rule
)
237 struct lttng_event_rule_kernel_syscall
*syscall_rule
=
238 container_of(rule
, typeof(*syscall_rule
), parent
);
240 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL
,
242 hash
^= hash_key_str(syscall_rule
->pattern
, lttng_ht_seed
);
243 if (syscall_rule
->filter_expression
) {
244 hash
^= hash_key_str(syscall_rule
->filter_expression
,
251 static enum lttng_error_code
lttng_event_rule_kernel_syscall_mi_serialize(
252 const struct lttng_event_rule
*rule
, struct mi_writer
*writer
)
255 enum lttng_error_code ret_code
;
256 enum lttng_event_rule_status status
;
258 enum lttng_event_rule_kernel_syscall_emission_site site_type
;
259 const char *filter
= NULL
;
260 const char *name_pattern
= NULL
;
261 const char *site_type_str
= NULL
;
265 assert(IS_SYSCALL_EVENT_RULE(rule
));
267 status
= lttng_event_rule_kernel_syscall_get_name_pattern(
268 rule
, &name_pattern
);
269 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
270 assert(name_pattern
);
272 status
= lttng_event_rule_kernel_syscall_get_filter(rule
, &filter
);
273 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
||
274 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
276 site_type
= lttng_event_rule_kernel_syscall_get_emission_site(rule
);
279 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT
:
280 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit
;
282 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
283 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_entry
;
285 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
:
286 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_exit
;
293 /* Open event rule kernel syscall element. */
294 ret
= mi_lttng_writer_open_element(
295 writer
, mi_lttng_element_event_rule_kernel_syscall
);
301 ret
= mi_lttng_writer_write_element_string(writer
,
302 mi_lttng_element_event_rule_kernel_syscall_emission_site
,
309 ret
= mi_lttng_writer_write_element_string(writer
,
310 mi_lttng_element_event_rule_name_pattern
, name_pattern
);
316 if (filter
!= NULL
) {
317 ret
= mi_lttng_writer_write_element_string(writer
,
318 mi_lttng_element_event_rule_filter_expression
,
325 /* Close event rule kernel syscall. */
326 ret
= mi_lttng_writer_close_element(writer
);
335 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
340 struct lttng_event_rule
*lttng_event_rule_kernel_syscall_create(
341 enum lttng_event_rule_kernel_syscall_emission_site
344 struct lttng_event_rule
*rule
= NULL
;
345 struct lttng_event_rule_kernel_syscall
*syscall_rule
;
346 enum lttng_event_rule_status status
;
348 /* Validate the emission site type */
349 switch (emission_site
) {
350 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT
:
351 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
352 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
:
355 /* Invalid emission type */
359 syscall_rule
= zmalloc(sizeof(struct lttng_event_rule_kernel_syscall
));
364 rule
= &syscall_rule
->parent
;
365 lttng_event_rule_init(
366 &syscall_rule
->parent
, LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL
);
367 syscall_rule
->parent
.validate
= lttng_event_rule_kernel_syscall_validate
;
368 syscall_rule
->parent
.serialize
= lttng_event_rule_kernel_syscall_serialize
;
369 syscall_rule
->parent
.equal
= lttng_event_rule_kernel_syscall_is_equal
;
370 syscall_rule
->parent
.destroy
= lttng_event_rule_kernel_syscall_destroy
;
371 syscall_rule
->parent
.generate_filter_bytecode
=
372 lttng_event_rule_kernel_syscall_generate_filter_bytecode
;
373 syscall_rule
->parent
.get_filter
=
374 lttng_event_rule_kernel_syscall_get_internal_filter
;
375 syscall_rule
->parent
.get_filter_bytecode
=
376 lttng_event_rule_kernel_syscall_get_internal_filter_bytecode
;
377 syscall_rule
->parent
.generate_exclusions
=
378 lttng_event_rule_kernel_syscall_generate_exclusions
;
379 syscall_rule
->parent
.hash
= lttng_event_rule_kernel_syscall_hash
;
380 syscall_rule
->parent
.mi_serialize
= lttng_event_rule_kernel_syscall_mi_serialize
;
382 /* Default pattern is '*'. */
383 status
= lttng_event_rule_kernel_syscall_set_name_pattern(rule
, "*");
384 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
385 lttng_event_rule_destroy(rule
);
389 /* Emission site type */
390 syscall_rule
->emission_site
= emission_site
;
397 ssize_t
lttng_event_rule_kernel_syscall_create_from_payload(
398 struct lttng_payload_view
*view
,
399 struct lttng_event_rule
**_event_rule
)
401 ssize_t ret
, offset
= 0;
402 enum lttng_event_rule_status status
;
403 const struct lttng_event_rule_kernel_syscall_comm
*syscall_comm
;
405 const char *filter_expression
= NULL
;
406 struct lttng_buffer_view current_buffer_view
;
407 struct lttng_event_rule
*rule
= NULL
;
414 if (view
->buffer
.size
< sizeof(*syscall_comm
)) {
415 ERR("Failed to initialize from malformed event rule syscall: buffer too short to contain header");
420 current_buffer_view
= lttng_buffer_view_from_view(
421 &view
->buffer
, offset
, sizeof(*syscall_comm
));
422 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
427 syscall_comm
= (typeof(syscall_comm
)) current_buffer_view
.data
;
428 rule
= lttng_event_rule_kernel_syscall_create(syscall_comm
->emission_site
);
430 ERR("Failed to create event rule syscall");
435 /* Skip to payload. */
436 offset
+= current_buffer_view
.size
;
438 /* Map the pattern. */
439 current_buffer_view
= lttng_buffer_view_from_view(
440 &view
->buffer
, offset
, syscall_comm
->pattern_len
);
441 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
446 pattern
= current_buffer_view
.data
;
447 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
448 syscall_comm
->pattern_len
)) {
453 /* Skip after the pattern. */
454 offset
+= syscall_comm
->pattern_len
;
456 if (!syscall_comm
->filter_expression_len
) {
457 goto skip_filter_expression
;
460 /* Map the filter_expression. */
461 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
462 syscall_comm
->filter_expression_len
);
463 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
468 filter_expression
= current_buffer_view
.data
;
469 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
471 syscall_comm
->filter_expression_len
)) {
476 /* Skip after the pattern. */
477 offset
+= syscall_comm
->filter_expression_len
;
479 skip_filter_expression
:
481 status
= lttng_event_rule_kernel_syscall_set_name_pattern(rule
, pattern
);
482 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
483 ERR("Failed to set event rule syscall pattern");
488 if (filter_expression
) {
489 status
= lttng_event_rule_kernel_syscall_set_filter(
490 rule
, filter_expression
);
491 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
492 ERR("Failed to set event rule syscall pattern");
502 lttng_event_rule_destroy(rule
);
506 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_set_name_pattern(
507 struct lttng_event_rule
*rule
, const char *pattern
)
509 char *pattern_copy
= NULL
;
510 struct lttng_event_rule_kernel_syscall
*syscall
;
511 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
513 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
||
514 strlen(pattern
) == 0) {
515 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
519 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
520 pattern_copy
= strdup(pattern
);
522 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
526 strutils_normalize_star_glob_pattern(pattern_copy
);
528 free(syscall
->pattern
);
530 syscall
->pattern
= pattern_copy
;
536 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_get_name_pattern(
537 const struct lttng_event_rule
*rule
, const char **pattern
)
539 struct lttng_event_rule_kernel_syscall
*syscall
;
540 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
542 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
) {
543 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
547 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
548 if (!syscall
->pattern
) {
549 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
553 *pattern
= syscall
->pattern
;
558 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_set_filter(
559 struct lttng_event_rule
*rule
, const char *expression
)
561 char *expression_copy
= NULL
;
562 struct lttng_event_rule_kernel_syscall
*syscall
;
563 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
565 /* TODO: validate that the passed expression is valid. */
567 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
||
568 strlen(expression
) == 0) {
569 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
573 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
574 expression_copy
= strdup(expression
);
575 if (!expression_copy
) {
576 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
580 if (syscall
->filter_expression
) {
581 free(syscall
->filter_expression
);
584 syscall
->filter_expression
= expression_copy
;
585 expression_copy
= NULL
;
590 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_get_filter(
591 const struct lttng_event_rule
*rule
, const char **expression
)
593 struct lttng_event_rule_kernel_syscall
*syscall
;
594 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
596 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
) {
597 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
601 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
602 if (!syscall
->filter_expression
) {
603 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
607 *expression
= syscall
->filter_expression
;
611 extern enum lttng_event_rule_kernel_syscall_emission_site
612 lttng_event_rule_kernel_syscall_get_emission_site(
613 const struct lttng_event_rule
*rule
)
615 enum lttng_event_rule_kernel_syscall_emission_site emission_site
=
616 LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_UNKNOWN
;
617 struct lttng_event_rule_kernel_syscall
*syscall
;
619 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
623 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
624 emission_site
= syscall
->emission_site
;
627 return emission_site
;
631 const char *lttng_event_rule_kernel_syscall_emission_site_str(
632 enum lttng_event_rule_kernel_syscall_emission_site emission_site
)
634 switch (emission_site
) {
635 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
637 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT
:
639 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
: