2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/error.h>
10 #include <common/macros.h>
11 #include <common/payload.h>
12 #include <common/payload-view.h>
13 #include <common/runas.h>
14 #include <lttng/event-rule/event-rule-internal.h>
15 #include <lttng/event-rule/syscall-internal.h>
17 #define IS_SYSCALL_EVENT_RULE(rule) \
18 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL)
20 static void lttng_event_rule_syscall_destroy(struct lttng_event_rule
*rule
)
22 struct lttng_event_rule_syscall
*syscall
;
28 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
30 free(syscall
->pattern
);
31 free(syscall
->filter_expression
);
32 free(syscall
->internal_filter
.filter
);
33 free(syscall
->internal_filter
.bytecode
);
37 static bool lttng_event_rule_syscall_validate(
38 const struct lttng_event_rule
*rule
)
41 struct lttng_event_rule_syscall
*syscall
;
47 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
50 if (!syscall
->pattern
) {
51 ERR("Invalid syscall event rule: a pattern must be set.");
60 static int lttng_event_rule_syscall_serialize(
61 const struct lttng_event_rule
*rule
,
62 struct lttng_payload
*payload
)
65 size_t pattern_len
, filter_expression_len
;
66 struct lttng_event_rule_syscall
*syscall
;
67 struct lttng_event_rule_syscall_comm syscall_comm
;
69 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
74 DBG("Serializing syscall event rule");
75 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
77 pattern_len
= strlen(syscall
->pattern
) + 1;
79 if (syscall
->filter_expression
!= NULL
) {
80 filter_expression_len
= strlen(syscall
->filter_expression
) + 1;
82 filter_expression_len
= 0;
85 syscall_comm
.pattern_len
= pattern_len
;
86 syscall_comm
.filter_expression_len
= filter_expression_len
;
88 ret
= lttng_dynamic_buffer_append(
89 &payload
->buffer
, &syscall_comm
, sizeof(syscall_comm
));
94 ret
= lttng_dynamic_buffer_append(
95 &payload
->buffer
, syscall
->pattern
, pattern_len
);
100 ret
= lttng_dynamic_buffer_append(&payload
->buffer
,
101 syscall
->filter_expression
, filter_expression_len
);
106 static bool lttng_event_rule_syscall_is_equal(const struct lttng_event_rule
*_a
,
107 const struct lttng_event_rule
*_b
)
109 bool is_equal
= false;
110 struct lttng_event_rule_syscall
*a
, *b
;
112 a
= container_of(_a
, struct lttng_event_rule_syscall
, parent
);
113 b
= container_of(_b
, struct lttng_event_rule_syscall
, parent
);
115 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
121 if (strcmp(a
->pattern
, b
->pattern
)) {
125 if (a
->filter_expression
&& b
->filter_expression
) {
126 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
129 } else if (!!a
->filter_expression
!= !!b
->filter_expression
) {
130 /* One is set and not the other. */
139 static enum lttng_error_code
lttng_event_rule_syscall_generate_filter_bytecode(
140 struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
143 enum lttng_error_code ret_code
= LTTNG_OK
;
144 struct lttng_event_rule_syscall
*syscall
;
145 enum lttng_event_rule_status status
;
147 struct lttng_filter_bytecode
*bytecode
= NULL
;
151 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
153 /* Generate the filter bytecode. */
154 status
= lttng_event_rule_syscall_get_filter(rule
, &filter
);
155 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
157 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
158 ret_code
= LTTNG_ERR_FILTER_INVAL
;
162 if (filter
&& filter
[0] == '\0') {
163 ret_code
= LTTNG_ERR_FILTER_INVAL
;
167 if (filter
== NULL
) {
173 syscall
->internal_filter
.filter
= strdup(filter
);
174 if (syscall
->internal_filter
.filter
== NULL
) {
175 ret_code
= LTTNG_ERR_NOMEM
;
179 ret
= run_as_generate_filter_bytecode(
180 syscall
->internal_filter
.filter
, uid
, gid
, &bytecode
);
182 ret_code
= LTTNG_ERR_FILTER_INVAL
;
185 syscall
->internal_filter
.bytecode
= bytecode
;
193 static const char *lttng_event_rule_syscall_get_internal_filter(
194 const struct lttng_event_rule
*rule
)
196 struct lttng_event_rule_syscall
*syscall
;
199 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
201 return syscall
->internal_filter
.filter
;
204 static const struct lttng_filter_bytecode
*
205 lttng_event_rule_syscall_get_internal_filter_bytecode(
206 const struct lttng_event_rule
*rule
)
208 struct lttng_event_rule_syscall
*syscall
;
211 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
213 return syscall
->internal_filter
.bytecode
;
216 static struct lttng_event_exclusion
*
217 lttng_event_rule_syscall_generate_exclusions(
218 const struct lttng_event_rule
*rule
)
224 struct lttng_event_rule
*lttng_event_rule_syscall_create()
226 struct lttng_event_rule
*rule
= NULL
;
227 struct lttng_event_rule_syscall
*syscall_rule
;
229 syscall_rule
= zmalloc(sizeof(struct lttng_event_rule_syscall
));
234 rule
= &syscall_rule
->parent
;
235 lttng_event_rule_init(
236 &syscall_rule
->parent
, LTTNG_EVENT_RULE_TYPE_SYSCALL
);
237 syscall_rule
->parent
.validate
= lttng_event_rule_syscall_validate
;
238 syscall_rule
->parent
.serialize
= lttng_event_rule_syscall_serialize
;
239 syscall_rule
->parent
.equal
= lttng_event_rule_syscall_is_equal
;
240 syscall_rule
->parent
.destroy
= lttng_event_rule_syscall_destroy
;
241 syscall_rule
->parent
.generate_filter_bytecode
=
242 lttng_event_rule_syscall_generate_filter_bytecode
;
243 syscall_rule
->parent
.get_filter
=
244 lttng_event_rule_syscall_get_internal_filter
;
245 syscall_rule
->parent
.get_filter_bytecode
=
246 lttng_event_rule_syscall_get_internal_filter_bytecode
;
247 syscall_rule
->parent
.generate_exclusions
=
248 lttng_event_rule_syscall_generate_exclusions
;
254 ssize_t
lttng_event_rule_syscall_create_from_payload(
255 struct lttng_payload_view
*view
,
256 struct lttng_event_rule
**_event_rule
)
258 ssize_t ret
, offset
= 0;
259 enum lttng_event_rule_status status
;
260 const struct lttng_event_rule_syscall_comm
*syscall_comm
;
262 const char *filter_expression
= NULL
;
263 struct lttng_buffer_view current_buffer_view
;
264 struct lttng_event_rule
*rule
= NULL
;
271 if (view
->buffer
.size
< sizeof(*syscall_comm
)) {
272 ERR("Failed to initialize from malformed event rule syscall: buffer too short to contain header");
277 current_buffer_view
= lttng_buffer_view_from_view(
278 &view
->buffer
, offset
, sizeof(*syscall_comm
));
279 syscall_comm
= (typeof(syscall_comm
)) current_buffer_view
.data
;
286 rule
= lttng_event_rule_syscall_create();
288 ERR("Failed to create event rule syscall");
293 /* Skip to payload. */
294 offset
+= current_buffer_view
.size
;
296 /* Map the pattern. */
297 current_buffer_view
= lttng_buffer_view_from_view(
298 &view
->buffer
, offset
, syscall_comm
->pattern_len
);
299 pattern
= current_buffer_view
.data
;
305 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
306 syscall_comm
->pattern_len
)) {
311 /* Skip after the pattern. */
312 offset
+= syscall_comm
->pattern_len
;
314 if (!syscall_comm
->filter_expression_len
) {
315 goto skip_filter_expression
;
318 /* Map the filter_expression. */
319 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
320 syscall_comm
->filter_expression_len
);
321 filter_expression
= current_buffer_view
.data
;
322 if (!filter_expression
) {
327 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
329 syscall_comm
->filter_expression_len
)) {
334 /* Skip after the pattern. */
335 offset
+= syscall_comm
->filter_expression_len
;
337 skip_filter_expression
:
339 status
= lttng_event_rule_syscall_set_pattern(rule
, pattern
);
340 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
341 ERR("Failed to set event rule syscall pattern");
346 if (filter_expression
) {
347 status
= lttng_event_rule_syscall_set_filter(
348 rule
, filter_expression
);
349 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
350 ERR("Failed to set event rule syscall pattern");
360 lttng_event_rule_destroy(rule
);
364 enum lttng_event_rule_status
lttng_event_rule_syscall_set_pattern(
365 struct lttng_event_rule
*rule
, const char *pattern
)
367 char *pattern_copy
= NULL
;
368 struct lttng_event_rule_syscall
*syscall
;
369 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
371 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
||
372 strlen(pattern
) == 0) {
373 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
377 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
378 pattern_copy
= strdup(pattern
);
380 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
384 if (syscall
->pattern
) {
385 free(syscall
->pattern
);
388 syscall
->pattern
= pattern_copy
;
394 enum lttng_event_rule_status
lttng_event_rule_syscall_get_pattern(
395 const struct lttng_event_rule
*rule
, const char **pattern
)
397 struct lttng_event_rule_syscall
*syscall
;
398 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
400 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
) {
401 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
405 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
406 if (!syscall
->pattern
) {
407 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
411 *pattern
= syscall
->pattern
;
416 enum lttng_event_rule_status
lttng_event_rule_syscall_set_filter(
417 struct lttng_event_rule
*rule
, const char *expression
)
419 char *expression_copy
= NULL
;
420 struct lttng_event_rule_syscall
*syscall
;
421 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
423 /* TODO: validate that the passed expression is valid. */
425 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
||
426 strlen(expression
) == 0) {
427 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
431 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
432 expression_copy
= strdup(expression
);
433 if (!expression_copy
) {
434 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
438 if (syscall
->filter_expression
) {
439 free(syscall
->filter_expression
);
442 syscall
->filter_expression
= expression_copy
;
443 expression_copy
= NULL
;
448 enum lttng_event_rule_status
lttng_event_rule_syscall_get_filter(
449 const struct lttng_event_rule
*rule
, const char **expression
)
451 struct lttng_event_rule_syscall
*syscall
;
452 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
454 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
) {
455 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
459 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
460 if (!syscall
->filter_expression
) {
461 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
465 *expression
= syscall
->filter_expression
;