2 * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <lttng/event-rule/event-rule-internal.h>
19 #include <lttng/event-rule/syscall-internal.h>
20 #include <common/macros.h>
21 #include <common/error.h>
22 #include <common/runas.h>
25 #define IS_SYSCALL_EVENT_RULE(rule) ( \
26 lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_SYSCALL \
30 void lttng_event_rule_syscall_destroy(struct lttng_event_rule
*rule
)
32 struct lttng_event_rule_syscall
*syscall
;
38 syscall
= container_of(rule
, struct lttng_event_rule_syscall
,
41 free(syscall
->pattern
);
42 free(syscall
->filter_expression
);
43 free(syscall
->internal_filter
.filter
);
44 free(syscall
->internal_filter
.bytecode
);
49 bool lttng_event_rule_syscall_validate(
50 const struct lttng_event_rule
*rule
)
53 struct lttng_event_rule_syscall
*syscall
;
59 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
62 if (!syscall
->pattern
) {
63 ERR("Invalid syscall event rule: a pattern must be set.");
73 int lttng_event_rule_syscall_serialize(
74 const struct lttng_event_rule
*rule
,
75 struct lttng_dynamic_buffer
*buf
,
79 size_t pattern_len
, filter_expression_len
;
80 struct lttng_event_rule_syscall
*syscall
;
81 struct lttng_event_rule_syscall_comm syscall_comm
;
83 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
)) {
88 DBG("Serializing syscall event rule");
89 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
91 pattern_len
= strlen(syscall
->pattern
) + 1;
93 if (syscall
->filter_expression
!= NULL
) {
94 filter_expression_len
= strlen(syscall
->filter_expression
) + 1;
96 filter_expression_len
= 0;
99 syscall_comm
.pattern_len
= pattern_len
;
100 syscall_comm
.filter_expression_len
= filter_expression_len
;
102 ret
= lttng_dynamic_buffer_append(
103 buf
, &syscall_comm
, sizeof(syscall_comm
));
107 ret
= lttng_dynamic_buffer_append(buf
, syscall
->pattern
, pattern_len
);
111 ret
= lttng_dynamic_buffer_append(
112 buf
, syscall
->filter_expression
, filter_expression_len
);
118 /* Nothing to send */
126 bool lttng_event_rule_syscall_is_equal(const struct lttng_event_rule
*_a
,
127 const struct lttng_event_rule
*_b
)
129 bool is_equal
= false;
130 struct lttng_event_rule_syscall
*a
, *b
;
132 a
= container_of(_a
, struct lttng_event_rule_syscall
, parent
);
133 b
= container_of(_b
, struct lttng_event_rule_syscall
, parent
);
135 if (!!a
->filter_expression
!= !!b
->filter_expression
) {
140 /* syscall is invalid if this is not true */
143 if (strcmp(a
->pattern
, b
->pattern
)) {
147 if (a
->filter_expression
&& b
->filter_expression
) {
148 if (strcmp(a
->filter_expression
, b
->filter_expression
)) {
159 enum lttng_error_code
lttng_event_rule_syscall_populate(struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
162 enum lttng_error_code ret_code
= LTTNG_OK
;
163 struct lttng_event_rule_syscall
*syscall
;
164 enum lttng_event_rule_status status
;
166 struct lttng_filter_bytecode
*bytecode
= NULL
;
170 syscall
= container_of(rule
, struct lttng_event_rule_syscall
,
173 /* Generate the filter bytecode */
174 status
= lttng_event_rule_syscall_get_filter(rule
, &filter
);
175 if (status
== LTTNG_EVENT_RULE_STATUS_UNSET
) {
177 } else if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
178 ret_code
= LTTNG_ERR_FILTER_INVAL
;
182 if (filter
&& filter
[0] == '\0') {
183 ret_code
= LTTNG_ERR_FILTER_INVAL
;
187 if (filter
== NULL
) {
193 syscall
->internal_filter
.filter
= strdup(filter
);
194 if (syscall
->internal_filter
.filter
== NULL
) {
195 ret_code
= LTTNG_ERR_NOMEM
;
199 ret
= run_as_generate_filter_bytecode(syscall
->internal_filter
.filter
, uid
, gid
, &bytecode
);
201 ret_code
= LTTNG_ERR_FILTER_INVAL
;
204 syscall
->internal_filter
.bytecode
= bytecode
;
213 static const char *lttng_event_rule_syscall_get_internal_filter(
214 const struct lttng_event_rule
*rule
)
216 struct lttng_event_rule_syscall
*syscall
;
219 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
220 return syscall
->internal_filter
.filter
;
223 static const struct lttng_filter_bytecode
*
224 lttng_event_rule_syscall_get_internal_filter_bytecode(
225 const struct lttng_event_rule
*rule
)
227 struct lttng_event_rule_syscall
*syscall
;
230 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
231 return syscall
->internal_filter
.bytecode
;
234 static struct lttng_event_exclusion
*
235 lttng_event_rule_syscall_generate_exclusions(struct lttng_event_rule
*rule
)
241 struct lttng_event_rule
*lttng_event_rule_syscall_create()
243 struct lttng_event_rule_syscall
*rule
;
245 rule
= zmalloc(sizeof(struct lttng_event_rule_syscall
));
250 lttng_event_rule_init(&rule
->parent
, LTTNG_EVENT_RULE_TYPE_SYSCALL
);
251 rule
->parent
.validate
= lttng_event_rule_syscall_validate
;
252 rule
->parent
.serialize
= lttng_event_rule_syscall_serialize
;
253 rule
->parent
.equal
= lttng_event_rule_syscall_is_equal
;
254 rule
->parent
.destroy
= lttng_event_rule_syscall_destroy
;
255 rule
->parent
.populate
= lttng_event_rule_syscall_populate
;
256 rule
->parent
.get_filter
= lttng_event_rule_syscall_get_internal_filter
;
257 rule
->parent
.get_filter_bytecode
=
258 lttng_event_rule_syscall_get_internal_filter_bytecode
;
259 rule
->parent
.generate_exclusions
=
260 lttng_event_rule_syscall_generate_exclusions
;
261 return &rule
->parent
;
265 ssize_t
lttng_event_rule_syscall_create_from_buffer(
266 const struct lttng_buffer_view
*view
,
267 struct lttng_event_rule
**_event_rule
)
269 ssize_t ret
, offset
= 0;
270 enum lttng_event_rule_status status
;
271 const struct lttng_event_rule_syscall_comm
*syscall_comm
;
273 const char *filter_expression
= NULL
;
274 struct lttng_buffer_view current_view
;
275 struct lttng_event_rule
*rule
= NULL
;
282 if (view
->size
< sizeof(*syscall_comm
)) {
283 ERR("Failed to initialize from malformed event rule syscall: buffer too short to contain header");
288 current_view
= lttng_buffer_view_from_view(
289 view
, offset
, sizeof(*syscall_comm
));
290 syscall_comm
= (typeof(syscall_comm
)) current_view
.data
;
297 rule
= lttng_event_rule_syscall_create();
299 ERR("Failed to create event rule syscall");
304 /* Skip to payload */
305 offset
+= current_view
.size
;
307 /* Map the pattern */
308 current_view
= lttng_buffer_view_from_view(
309 view
, offset
, syscall_comm
->pattern_len
);
310 pattern
= current_view
.data
;
316 if (syscall_comm
->pattern_len
== 1 ||
317 pattern
[syscall_comm
->pattern_len
- 1] != '\0' ||
318 strlen(pattern
) != syscall_comm
->pattern_len
- 1) {
320 * Check that the pattern is not NULL, is NULL-terminated, and
321 * does not contain a NULL before the last byte.
327 /* Skip after the pattern */
328 offset
+= syscall_comm
->pattern_len
;
330 if (!syscall_comm
->filter_expression_len
) {
331 goto skip_filter_expression
;
334 /* Map the filter_expression */
335 current_view
= lttng_buffer_view_from_view(
336 view
, offset
, syscall_comm
->filter_expression_len
);
337 filter_expression
= current_view
.data
;
338 if (!filter_expression
) {
343 if (syscall_comm
->filter_expression_len
== 1 ||
344 filter_expression
[syscall_comm
->filter_expression_len
-
346 strlen(filter_expression
) !=
347 syscall_comm
->filter_expression_len
-
350 * Check that the filter expression is not NULL, is
351 * NULL-terminated, and does not contain a NULL before the last
358 /* Skip after the pattern */
359 offset
+= syscall_comm
->filter_expression_len
;
361 skip_filter_expression
:
363 status
= lttng_event_rule_syscall_set_pattern(rule
, pattern
);
364 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
365 ERR("Failed to set event rule syscall pattern");
370 if (filter_expression
) {
371 status
= lttng_event_rule_syscall_set_filter(
372 rule
, filter_expression
);
373 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
374 ERR("Failed to set event rule syscall pattern");
384 lttng_event_rule_destroy(rule
);
388 enum lttng_event_rule_status
lttng_event_rule_syscall_set_pattern(
389 struct lttng_event_rule
*rule
, const char *pattern
)
391 char *pattern_copy
= NULL
;
392 struct lttng_event_rule_syscall
*syscall
;
393 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
395 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
||
396 strlen(pattern
) == 0) {
397 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
401 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
402 pattern_copy
= strdup(pattern
);
404 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
408 if (syscall
->pattern
) {
409 free(syscall
->pattern
);
412 syscall
->pattern
= pattern_copy
;
418 enum lttng_event_rule_status
lttng_event_rule_syscall_get_pattern(
419 const struct lttng_event_rule
*rule
, const char **pattern
)
421 struct lttng_event_rule_syscall
*syscall
;
422 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
424 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !pattern
) {
425 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
429 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
430 if (!syscall
->pattern
) {
431 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
435 *pattern
= syscall
->pattern
;
440 enum lttng_event_rule_status
lttng_event_rule_syscall_set_filter(
441 struct lttng_event_rule
*rule
, const char *expression
)
443 char *expression_copy
= NULL
;
444 struct lttng_event_rule_syscall
*syscall
;
445 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
447 /* TODO: validate that the passed expression is valid */
449 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
||
450 strlen(expression
) == 0) {
451 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
455 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
456 expression_copy
= strdup(expression
);
457 if (!expression_copy
) {
458 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
462 if (syscall
->filter_expression
) {
463 free(syscall
->filter_expression
);
466 syscall
->filter_expression
= expression_copy
;
467 expression_copy
= NULL
;
472 enum lttng_event_rule_status
lttng_event_rule_syscall_get_filter(
473 const struct lttng_event_rule
*rule
, const char **expression
)
475 struct lttng_event_rule_syscall
*syscall
;
476 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
478 if (!rule
|| !IS_SYSCALL_EVENT_RULE(rule
) || !expression
) {
479 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
483 syscall
= container_of(rule
, struct lttng_event_rule_syscall
, parent
);
484 if (!syscall
->filter_expression
) {
485 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
489 *expression
= syscall
->filter_expression
;