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/macros.h>
12 #include <common/payload.h>
13 #include <common/payload-view.h>
14 #include <common/runas.h>
15 #include <lttng/event-rule/event-rule-internal.h>
16 #include <lttng/event-rule/syscall-internal.h>
18 #define IS_SYSCALL_EVENT_RULE(rule) \
19 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL)
21 static void lttng_event_rule_syscall_destroy(struct lttng_event_rule
*rule
)
23 struct lttng_event_rule_syscall
*syscall
;
29 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
31 free(syscall
->pattern
);
32 free(syscall
->filter_expression
);
33 free(syscall
->internal_filter
.filter
);
34 free(syscall
->internal_filter
.bytecode
);
38 static bool lttng_event_rule_syscall_validate(
39 const struct lttng_event_rule
*rule
)
42 struct lttng_event_rule_syscall
*syscall
;
48 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
51 if (!syscall
->pattern
) {
52 ERR("Invalid syscall event rule: a pattern must be set.");
61 static int lttng_event_rule_syscall_serialize(
62 const struct lttng_event_rule
*rule
,
63 struct lttng_payload
*payload
)
66 size_t pattern_len
, filter_expression_len
;
67 struct lttng_event_rule_syscall
*syscall
;
68 struct lttng_event_rule_syscall_comm syscall_comm
;
70 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
75 DBG("Serializing syscall event rule");
76 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
78 pattern_len
= strlen(syscall
->pattern
) + 1;
80 if (syscall
->filter_expression
!= NULL
) {
81 filter_expression_len
= strlen(syscall
->filter_expression
) + 1;
83 filter_expression_len
= 0;
86 syscall_comm
.pattern_len
= pattern_len
;
87 syscall_comm
.filter_expression_len
= filter_expression_len
;
89 ret
= lttng_dynamic_buffer_append(
90 &payload
->buffer
, &syscall_comm
, sizeof(syscall_comm
));
95 ret
= lttng_dynamic_buffer_append(
96 &payload
->buffer
, syscall
->pattern
, pattern_len
);
101 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
102 syscall
->filter_expression
, filter_expression_len
);
107 static bool lttng_event_rule_syscall_is_equal(const struct lttng_event_rule
*_a
,
108 const struct lttng_event_rule
*_b
)
110 bool is_equal
= false;
111 struct lttng_event_rule_syscall
*a
, *b
;
113 a
= container_of(_a
, struct lttng_event_rule_syscall
, parent
);
114 b
= container_of(_b
, struct lttng_event_rule_syscall
, parent
);
116 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
122 if (strcmp(a
->pattern
, b
->pattern
)) {
126 if (a
->filter_expression
&& b
->filter_expression
) {
127 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
130 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
131 /* One is set and not the other. */
140 static enum lttng_error_code
lttng_event_rule_syscall_generate_filter_bytecode(
141 struct lttng_event_rule
*rule
,
142 const struct lttng_credentials
*creds
)
145 enum lttng_error_code ret_code
= LTTNG_OK
;
146 struct lttng_event_rule_syscall
*syscall
;
147 enum lttng_event_rule_status status
;
149 struct lttng_filter_bytecode
*bytecode
= NULL
;
153 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
155 /* Generate the filter bytecode. */
156 status
= lttng_event_rule_syscall_get_filter(rule
, &filter
);
157 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
159 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
160 ret_code
= LTTNG_ERR_FILTER_INVAL
;
164 if (filter
&& filter
[0] == '\0') {
165 ret_code
= LTTNG_ERR_FILTER_INVAL
;
169 if (filter
== NULL
) {
175 syscall
->internal_filter
.filter
= strdup(filter
);
176 if (syscall
->internal_filter
.filter
== NULL
) {
177 ret_code
= LTTNG_ERR_NOMEM
;
181 ret
= run_as_generate_filter_bytecode(
182 syscall
->internal_filter
.filter
, creds
, &bytecode
);
184 ret_code
= LTTNG_ERR_FILTER_INVAL
;
187 syscall
->internal_filter
.bytecode
= bytecode
;
195 static const char *lttng_event_rule_syscall_get_internal_filter(
196 const struct lttng_event_rule
*rule
)
198 struct lttng_event_rule_syscall
*syscall
;
201 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
203 return syscall
->internal_filter
.filter
;
206 static const struct lttng_filter_bytecode
*
207 lttng_event_rule_syscall_get_internal_filter_bytecode(
208 const struct lttng_event_rule
*rule
)
210 struct lttng_event_rule_syscall
*syscall
;
213 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
215 return syscall
->internal_filter
.bytecode
;
218 static struct lttng_event_exclusion
*
219 lttng_event_rule_syscall_generate_exclusions(
220 const struct lttng_event_rule
*rule
)
226 struct lttng_event_rule
*lttng_event_rule_syscall_create()
228 struct lttng_event_rule
*rule
= NULL
;
229 struct lttng_event_rule_syscall
*syscall_rule
;
231 syscall_rule
= zmalloc(sizeof(struct lttng_event_rule_syscall
));
236 rule
= &syscall_rule
->parent
;
237 lttng_event_rule_init(
238 &syscall_rule
->parent
, LTTNG_EVENT_RULE_TYPE_SYSCALL
);
239 syscall_rule
->parent
.validate
= lttng_event_rule_syscall_validate
;
240 syscall_rule
->parent
.serialize
= lttng_event_rule_syscall_serialize
;
241 syscall_rule
->parent
.equal
= lttng_event_rule_syscall_is_equal
;
242 syscall_rule
->parent
.destroy
= lttng_event_rule_syscall_destroy
;
243 syscall_rule
->parent
.generate_filter_bytecode
=
244 lttng_event_rule_syscall_generate_filter_bytecode
;
245 syscall_rule
->parent
.get_filter
=
246 lttng_event_rule_syscall_get_internal_filter
;
247 syscall_rule
->parent
.get_filter_bytecode
=
248 lttng_event_rule_syscall_get_internal_filter_bytecode
;
249 syscall_rule
->parent
.generate_exclusions
=
250 lttng_event_rule_syscall_generate_exclusions
;
256 ssize_t
lttng_event_rule_syscall_create_from_payload(
257 struct lttng_payload_view
*view
,
258 struct lttng_event_rule
**_event_rule
)
260 ssize_t ret
, offset
= 0;
261 enum lttng_event_rule_status status
;
262 const struct lttng_event_rule_syscall_comm
*syscall_comm
;
264 const char *filter_expression
= NULL
;
265 struct lttng_buffer_view current_buffer_view
;
266 struct lttng_event_rule
*rule
= NULL
;
273 if (view
->buffer
.size
< sizeof(*syscall_comm
)) {
274 ERR("Failed to initialize from malformed event rule syscall: buffer too short to contain header");
279 current_buffer_view
= lttng_buffer_view_from_view(
280 &view
->buffer
, offset
, sizeof(*syscall_comm
));
281 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
286 syscall_comm
= (typeof(syscall_comm
)) current_buffer_view
.data
;
287 rule
= lttng_event_rule_syscall_create();
289 ERR("Failed to create event rule syscall");
294 /* Skip to payload. */
295 offset
+= current_buffer_view
.size
;
297 /* Map the pattern. */
298 current_buffer_view
= lttng_buffer_view_from_view(
299 &view
->buffer
, offset
, syscall_comm
->pattern_len
);
300 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
305 pattern
= current_buffer_view
.data
;
306 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
307 syscall_comm
->pattern_len
)) {
312 /* Skip after the pattern. */
313 offset
+= syscall_comm
->pattern_len
;
315 if (!syscall_comm
->filter_expression_len
) {
316 goto skip_filter_expression
;
319 /* Map the filter_expression. */
320 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
321 syscall_comm
->filter_expression_len
);
322 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
327 filter_expression
= current_buffer_view
.data
;
328 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
330 syscall_comm
->filter_expression_len
)) {
335 /* Skip after the pattern. */
336 offset
+= syscall_comm
->filter_expression_len
;
338 skip_filter_expression
:
340 status
= lttng_event_rule_syscall_set_pattern(rule
, pattern
);
341 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
342 ERR("Failed to set event rule syscall pattern");
347 if (filter_expression
) {
348 status
= lttng_event_rule_syscall_set_filter(
349 rule
, filter_expression
);
350 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
351 ERR("Failed to set event rule syscall pattern");
361 lttng_event_rule_destroy(rule
);
365 enum lttng_event_rule_status
lttng_event_rule_syscall_set_pattern(
366 struct lttng_event_rule
*rule
, const char *pattern
)
368 char *pattern_copy
= NULL
;
369 struct lttng_event_rule_syscall
*syscall
;
370 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
372 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
||
373 strlen(pattern
) == 0) {
374 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
378 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
379 pattern_copy
= strdup(pattern
);
381 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
385 if (syscall
->pattern
) {
386 free(syscall
->pattern
);
389 syscall
->pattern
= pattern_copy
;
395 enum lttng_event_rule_status
lttng_event_rule_syscall_get_pattern(
396 const struct lttng_event_rule
*rule
, const char **pattern
)
398 struct lttng_event_rule_syscall
*syscall
;
399 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
401 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
) {
402 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
406 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
407 if (!syscall
->pattern
) {
408 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
412 *pattern
= syscall
->pattern
;
417 enum lttng_event_rule_status
lttng_event_rule_syscall_set_filter(
418 struct lttng_event_rule
*rule
, const char *expression
)
420 char *expression_copy
= NULL
;
421 struct lttng_event_rule_syscall
*syscall
;
422 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
424 /* TODO: validate that the passed expression is valid. */
426 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
||
427 strlen(expression
) == 0) {
428 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
432 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
433 expression_copy
= strdup(expression
);
434 if (!expression_copy
) {
435 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
439 if (syscall
->filter_expression
) {
440 free(syscall
->filter_expression
);
443 syscall
->filter_expression
= expression_copy
;
444 expression_copy
= NULL
;
449 enum lttng_event_rule_status
lttng_event_rule_syscall_get_filter(
450 const struct lttng_event_rule
*rule
, const char **expression
)
452 struct lttng_event_rule_syscall
*syscall
;
453 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
455 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
) {
456 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
460 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
461 if (!syscall
->filter_expression
) {
462 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
466 *expression
= syscall
->filter_expression
;