2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
8 #include <common/credentials.h>
9 #include <common/error.h>
10 #include <common/hashtable/hashtable.h>
11 #include <common/hashtable/utils.h>
12 #include <common/macros.h>
13 #include <common/mi-lttng.h>
14 #include <common/payload-view.h>
15 #include <common/payload.h>
16 #include <common/runas.h>
17 #include <common/string-utils/string-utils.h>
18 #include <lttng/event-rule/event-rule-internal.h>
19 #include <lttng/event-rule/kernel-syscall-internal.h>
21 #define IS_SYSCALL_EVENT_RULE(rule) \
22 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL)
24 static void lttng_event_rule_kernel_syscall_destroy(struct lttng_event_rule
*rule
)
26 struct lttng_event_rule_kernel_syscall
*syscall
;
32 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
34 free(syscall
->pattern
);
35 free(syscall
->filter_expression
);
36 free(syscall
->internal_filter
.filter
);
37 free(syscall
->internal_filter
.bytecode
);
41 static bool lttng_event_rule_kernel_syscall_validate(
42 const struct lttng_event_rule
*rule
)
45 struct lttng_event_rule_kernel_syscall
*syscall
;
51 syscall
= container_of(rule
, struct lttng_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(
65 const struct lttng_event_rule
*rule
,
66 struct lttng_payload
*payload
)
69 size_t pattern_len
, filter_expression_len
;
70 struct lttng_event_rule_kernel_syscall
*syscall
;
71 struct lttng_event_rule_kernel_syscall_comm syscall_comm
;
73 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
78 DBG("Serializing syscall event rule");
79 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
81 pattern_len
= strlen(syscall
->pattern
) + 1;
83 if (syscall
->filter_expression
!= NULL
) {
84 filter_expression_len
= strlen(syscall
->filter_expression
) + 1;
86 filter_expression_len
= 0;
89 syscall_comm
.pattern_len
= pattern_len
;
90 syscall_comm
.filter_expression_len
= filter_expression_len
;
91 syscall_comm
.emission_site
= syscall
->emission_site
;
93 ret
= lttng_dynamic_buffer_append(
94 &payload
->buffer
, &syscall_comm
, sizeof(syscall_comm
));
99 ret
= lttng_dynamic_buffer_append(
100 &payload
->buffer
, syscall
->pattern
, pattern_len
);
105 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
106 syscall
->filter_expression
, filter_expression_len
);
111 static bool lttng_event_rule_kernel_syscall_is_equal(const struct lttng_event_rule
*_a
,
112 const struct lttng_event_rule
*_b
)
114 bool is_equal
= false;
115 struct lttng_event_rule_kernel_syscall
*a
, *b
;
117 a
= container_of(_a
, struct lttng_event_rule_kernel_syscall
, parent
);
118 b
= container_of(_b
, struct lttng_event_rule_kernel_syscall
, parent
);
120 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
124 LTTNG_ASSERT(a
->pattern
);
125 LTTNG_ASSERT(b
->pattern
);
126 if (strcmp(a
->pattern
, b
->pattern
)) {
130 if (a
->filter_expression
&& b
->filter_expression
) {
131 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
134 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
135 /* One is set and not the other. */
144 static enum lttng_error_code
lttng_event_rule_kernel_syscall_generate_filter_bytecode(
145 struct lttng_event_rule
*rule
,
146 const struct lttng_credentials
*creds
)
149 enum lttng_error_code ret_code
= LTTNG_OK
;
150 struct lttng_event_rule_kernel_syscall
*syscall
;
151 enum lttng_event_rule_status status
;
153 struct lttng_bytecode
*bytecode
= NULL
;
157 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
159 /* Generate the filter bytecode. */
160 status
= lttng_event_rule_kernel_syscall_get_filter(rule
, &filter
);
161 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
163 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
164 ret_code
= LTTNG_ERR_FILTER_INVAL
;
168 if (filter
&& filter
[0] == '\0') {
169 ret_code
= LTTNG_ERR_FILTER_INVAL
;
173 if (filter
== NULL
) {
179 syscall
->internal_filter
.filter
= strdup(filter
);
180 if (syscall
->internal_filter
.filter
== NULL
) {
181 ret_code
= LTTNG_ERR_NOMEM
;
185 ret
= run_as_generate_filter_bytecode(
186 syscall
->internal_filter
.filter
, creds
, &bytecode
);
188 ret_code
= LTTNG_ERR_FILTER_INVAL
;
191 syscall
->internal_filter
.bytecode
= bytecode
;
199 static const char *lttng_event_rule_kernel_syscall_get_internal_filter(
200 const struct lttng_event_rule
*rule
)
202 struct lttng_event_rule_kernel_syscall
*syscall
;
205 syscall
= container_of(rule
, struct lttng_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(
212 const struct lttng_event_rule
*rule
)
214 struct lttng_event_rule_kernel_syscall
*syscall
;
217 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
219 return syscall
->internal_filter
.bytecode
;
222 static enum lttng_event_rule_generate_exclusions_status
223 lttng_event_rule_kernel_syscall_generate_exclusions(const struct lttng_event_rule
*rule
,
224 struct lttng_event_exclusion
**exclusions
)
228 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
232 lttng_event_rule_kernel_syscall_hash(
233 const struct lttng_event_rule
*rule
)
236 struct lttng_event_rule_kernel_syscall
*syscall_rule
=
237 container_of(rule
, typeof(*syscall_rule
), parent
);
239 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL
,
241 hash
^= hash_key_str(syscall_rule
->pattern
, lttng_ht_seed
);
242 if (syscall_rule
->filter_expression
) {
243 hash
^= hash_key_str(syscall_rule
->filter_expression
,
250 static enum lttng_error_code
lttng_event_rule_kernel_syscall_mi_serialize(
251 const struct lttng_event_rule
*rule
, struct mi_writer
*writer
)
254 enum lttng_error_code ret_code
;
255 enum lttng_event_rule_status status
;
257 enum lttng_event_rule_kernel_syscall_emission_site site_type
;
258 const char *filter
= NULL
;
259 const char *name_pattern
= NULL
;
260 const char *site_type_str
= NULL
;
263 LTTNG_ASSERT(writer
);
264 LTTNG_ASSERT(IS_SYSCALL_EVENT_RULE(rule
));
266 status
= lttng_event_rule_kernel_syscall_get_name_pattern(
267 rule
, &name_pattern
);
268 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
269 LTTNG_ASSERT(name_pattern
);
271 status
= lttng_event_rule_kernel_syscall_get_filter(rule
, &filter
);
272 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
||
273 status
== LTTNG_EVENT_RULE_STATUS_UNSET
);
275 site_type
= lttng_event_rule_kernel_syscall_get_emission_site(rule
);
278 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT
:
279 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_entry_exit
;
281 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
282 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_entry
;
284 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
:
285 site_type_str
= mi_lttng_event_rule_kernel_syscall_emission_site_exit
;
292 /* Open event rule kernel syscall element. */
293 ret
= mi_lttng_writer_open_element(
294 writer
, mi_lttng_element_event_rule_kernel_syscall
);
300 ret
= mi_lttng_writer_write_element_string(writer
,
301 mi_lttng_element_event_rule_kernel_syscall_emission_site
,
308 ret
= mi_lttng_writer_write_element_string(writer
,
309 mi_lttng_element_event_rule_name_pattern
, name_pattern
);
315 if (filter
!= NULL
) {
316 ret
= mi_lttng_writer_write_element_string(writer
,
317 mi_lttng_element_event_rule_filter_expression
,
324 /* Close event rule kernel syscall. */
325 ret
= mi_lttng_writer_close_element(writer
);
334 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
339 struct lttng_event_rule
*lttng_event_rule_kernel_syscall_create(
340 enum lttng_event_rule_kernel_syscall_emission_site
343 struct lttng_event_rule
*rule
= NULL
;
344 struct lttng_event_rule_kernel_syscall
*syscall_rule
;
345 enum lttng_event_rule_status status
;
347 /* Validate the emission site type */
348 switch (emission_site
) {
349 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT
:
350 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
351 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
:
354 /* Invalid emission type */
358 syscall_rule
= (lttng_event_rule_kernel_syscall
*) zmalloc(sizeof(struct lttng_event_rule_kernel_syscall
));
363 rule
= &syscall_rule
->parent
;
364 lttng_event_rule_init(
365 &syscall_rule
->parent
, LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL
);
366 syscall_rule
->parent
.validate
= lttng_event_rule_kernel_syscall_validate
;
367 syscall_rule
->parent
.serialize
= lttng_event_rule_kernel_syscall_serialize
;
368 syscall_rule
->parent
.equal
= lttng_event_rule_kernel_syscall_is_equal
;
369 syscall_rule
->parent
.destroy
= lttng_event_rule_kernel_syscall_destroy
;
370 syscall_rule
->parent
.generate_filter_bytecode
=
371 lttng_event_rule_kernel_syscall_generate_filter_bytecode
;
372 syscall_rule
->parent
.get_filter
=
373 lttng_event_rule_kernel_syscall_get_internal_filter
;
374 syscall_rule
->parent
.get_filter_bytecode
=
375 lttng_event_rule_kernel_syscall_get_internal_filter_bytecode
;
376 syscall_rule
->parent
.generate_exclusions
=
377 lttng_event_rule_kernel_syscall_generate_exclusions
;
378 syscall_rule
->parent
.hash
= lttng_event_rule_kernel_syscall_hash
;
379 syscall_rule
->parent
.mi_serialize
= lttng_event_rule_kernel_syscall_mi_serialize
;
381 /* Default pattern is '*'. */
382 status
= lttng_event_rule_kernel_syscall_set_name_pattern(rule
, "*");
383 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
384 lttng_event_rule_destroy(rule
);
388 /* Emission site type */
389 syscall_rule
->emission_site
= emission_site
;
395 ssize_t
lttng_event_rule_kernel_syscall_create_from_payload(
396 struct lttng_payload_view
*view
,
397 struct lttng_event_rule
**_event_rule
)
399 ssize_t ret
, offset
= 0;
400 enum lttng_event_rule_status status
;
401 const struct lttng_event_rule_kernel_syscall_comm
*syscall_comm
;
403 const char *filter_expression
= NULL
;
404 struct lttng_buffer_view current_buffer_view
;
405 struct lttng_event_rule
*rule
= NULL
;
412 if (view
->buffer
.size
< sizeof(*syscall_comm
)) {
413 ERR("Failed to initialize from malformed event rule syscall: buffer too short to contain header");
418 current_buffer_view
= lttng_buffer_view_from_view(
419 &view
->buffer
, offset
, sizeof(*syscall_comm
));
420 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
425 syscall_comm
= (typeof(syscall_comm
)) current_buffer_view
.data
;
426 rule
= lttng_event_rule_kernel_syscall_create((lttng_event_rule_kernel_syscall_emission_site
) syscall_comm
->emission_site
);
428 ERR("Failed to create event rule syscall");
433 /* Skip to payload. */
434 offset
+= current_buffer_view
.size
;
436 /* Map the pattern. */
437 current_buffer_view
= lttng_buffer_view_from_view(
438 &view
->buffer
, offset
, syscall_comm
->pattern_len
);
439 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
444 pattern
= current_buffer_view
.data
;
445 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
446 syscall_comm
->pattern_len
)) {
451 /* Skip after the pattern. */
452 offset
+= syscall_comm
->pattern_len
;
454 if (!syscall_comm
->filter_expression_len
) {
455 goto skip_filter_expression
;
458 /* Map the filter_expression. */
459 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
460 syscall_comm
->filter_expression_len
);
461 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
466 filter_expression
= current_buffer_view
.data
;
467 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
469 syscall_comm
->filter_expression_len
)) {
474 /* Skip after the pattern. */
475 offset
+= syscall_comm
->filter_expression_len
;
477 skip_filter_expression
:
479 status
= lttng_event_rule_kernel_syscall_set_name_pattern(rule
, pattern
);
480 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
481 ERR("Failed to set event rule syscall pattern");
486 if (filter_expression
) {
487 status
= lttng_event_rule_kernel_syscall_set_filter(
488 rule
, filter_expression
);
489 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
490 ERR("Failed to set event rule syscall pattern");
500 lttng_event_rule_destroy(rule
);
504 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_set_name_pattern(
505 struct lttng_event_rule
*rule
, const char *pattern
)
507 char *pattern_copy
= NULL
;
508 struct lttng_event_rule_kernel_syscall
*syscall
;
509 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
511 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
||
512 strlen(pattern
) == 0) {
513 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
517 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
518 pattern_copy
= strdup(pattern
);
520 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
524 strutils_normalize_star_glob_pattern(pattern_copy
);
526 free(syscall
->pattern
);
528 syscall
->pattern
= pattern_copy
;
534 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_get_name_pattern(
535 const struct lttng_event_rule
*rule
, const char **pattern
)
537 struct lttng_event_rule_kernel_syscall
*syscall
;
538 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
540 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
) {
541 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
545 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
546 if (!syscall
->pattern
) {
547 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
551 *pattern
= syscall
->pattern
;
556 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_set_filter(
557 struct lttng_event_rule
*rule
, const char *expression
)
559 char *expression_copy
= NULL
;
560 struct lttng_event_rule_kernel_syscall
*syscall
;
561 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
563 /* TODO: validate that the passed expression is valid. */
565 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
||
566 strlen(expression
) == 0) {
567 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
571 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
572 expression_copy
= strdup(expression
);
573 if (!expression_copy
) {
574 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
578 if (syscall
->filter_expression
) {
579 free(syscall
->filter_expression
);
582 syscall
->filter_expression
= expression_copy
;
583 expression_copy
= NULL
;
588 enum lttng_event_rule_status
lttng_event_rule_kernel_syscall_get_filter(
589 const struct lttng_event_rule
*rule
, const char **expression
)
591 struct lttng_event_rule_kernel_syscall
*syscall
;
592 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
594 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
) {
595 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
599 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
600 if (!syscall
->filter_expression
) {
601 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
605 *expression
= syscall
->filter_expression
;
609 extern enum lttng_event_rule_kernel_syscall_emission_site
610 lttng_event_rule_kernel_syscall_get_emission_site(
611 const struct lttng_event_rule
*rule
)
613 enum lttng_event_rule_kernel_syscall_emission_site emission_site
=
614 LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_UNKNOWN
;
615 struct lttng_event_rule_kernel_syscall
*syscall
;
617 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
621 syscall
= container_of(rule
, struct lttng_event_rule_kernel_syscall
, parent
);
622 emission_site
= syscall
->emission_site
;
625 return emission_site
;
628 const char *lttng_event_rule_kernel_syscall_emission_site_str(
629 enum lttng_event_rule_kernel_syscall_emission_site emission_site
)
631 switch (emission_site
) {
632 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY
:
634 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT
:
636 case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT
: