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 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
284 syscall_comm
= (typeof(syscall_comm
)) current_buffer_view
.data
;
285 rule
= lttng_event_rule_syscall_create();
287 ERR("Failed to create event rule syscall");
292 /* Skip to payload. */
293 offset
+= current_buffer_view
.size
;
295 /* Map the pattern. */
296 current_buffer_view
= lttng_buffer_view_from_view(
297 &view
->buffer
, offset
, syscall_comm
->pattern_len
);
298 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
303 pattern
= current_buffer_view
.data
;
304 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, pattern
,
305 syscall_comm
->pattern_len
)) {
310 /* Skip after the pattern. */
311 offset
+= syscall_comm
->pattern_len
;
313 if (!syscall_comm
->filter_expression_len
) {
314 goto skip_filter_expression
;
317 /* Map the filter_expression. */
318 current_buffer_view
= lttng_buffer_view_from_view(&view
->buffer
, offset
,
319 syscall_comm
->filter_expression_len
);
320 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
325 filter_expression
= current_buffer_view
.data
;
326 if (!lttng_buffer_view_contains_string(¤t_buffer_view
,
328 syscall_comm
->filter_expression_len
)) {
333 /* Skip after the pattern. */
334 offset
+= syscall_comm
->filter_expression_len
;
336 skip_filter_expression
:
338 status
= lttng_event_rule_syscall_set_pattern(rule
, pattern
);
339 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
340 ERR("Failed to set event rule syscall pattern");
345 if (filter_expression
) {
346 status
= lttng_event_rule_syscall_set_filter(
347 rule
, filter_expression
);
348 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
349 ERR("Failed to set event rule syscall pattern");
359 lttng_event_rule_destroy(rule
);
363 enum lttng_event_rule_status
lttng_event_rule_syscall_set_pattern(
364 struct lttng_event_rule
*rule
, const char *pattern
)
366 char *pattern_copy
= NULL
;
367 struct lttng_event_rule_syscall
*syscall
;
368 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
370 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
||
371 strlen(pattern
) == 0) {
372 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
376 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
377 pattern_copy
= strdup(pattern
);
379 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
383 if (syscall
->pattern
) {
384 free(syscall
->pattern
);
387 syscall
->pattern
= pattern_copy
;
393 enum lttng_event_rule_status
lttng_event_rule_syscall_get_pattern(
394 const struct lttng_event_rule
*rule
, const char **pattern
)
396 struct lttng_event_rule_syscall
*syscall
;
397 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
399 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
) {
400 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
404 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
405 if (!syscall
->pattern
) {
406 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
410 *pattern
= syscall
->pattern
;
415 enum lttng_event_rule_status
lttng_event_rule_syscall_set_filter(
416 struct lttng_event_rule
*rule
, const char *expression
)
418 char *expression_copy
= NULL
;
419 struct lttng_event_rule_syscall
*syscall
;
420 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
422 /* TODO: validate that the passed expression is valid. */
424 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
||
425 strlen(expression
) == 0) {
426 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
430 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
431 expression_copy
= strdup(expression
);
432 if (!expression_copy
) {
433 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
437 if (syscall
->filter_expression
) {
438 free(syscall
->filter_expression
);
441 syscall
->filter_expression
= expression_copy
;
442 expression_copy
= NULL
;
447 enum lttng_event_rule_status
lttng_event_rule_syscall_get_filter(
448 const struct lttng_event_rule
*rule
, const char **expression
)
450 struct lttng_event_rule_syscall
*syscall
;
451 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
453 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
) {
454 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
458 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
459 if (!syscall
->filter_expression
) {
460 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
464 *expression
= syscall
->filter_expression
;