fix: relayd: unaligned access in trace_chunk_registry_ht_key_hash
[lttng-tools.git] / src / common / event-rule / user-tracepoint.cpp
1 /*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <common/credentials.hpp>
9 #include <common/error.hpp>
10 #include <common/hashtable/hashtable.hpp>
11 #include <common/hashtable/utils.hpp>
12 #include <common/macros.hpp>
13 #include <common/mi-lttng.hpp>
14 #include <common/optional.hpp>
15 #include <common/payload-view.hpp>
16 #include <common/payload.hpp>
17 #include <common/runas.hpp>
18 #include <common/string-utils/string-utils.hpp>
19
20 #include <lttng/event-rule/event-rule-internal.hpp>
21 #include <lttng/event-rule/user-tracepoint-internal.hpp>
22 #include <lttng/event.h>
23 #include <lttng/log-level-rule.h>
24
25 #define IS_USER_TRACEPOINT_EVENT_RULE(rule) \
26 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT)
27
28 static void lttng_event_rule_user_tracepoint_destroy(struct lttng_event_rule *rule)
29 {
30 struct lttng_event_rule_user_tracepoint *tracepoint;
31
32 if (rule == nullptr) {
33 return;
34 }
35
36 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
37
38 lttng_log_level_rule_destroy(tracepoint->log_level_rule);
39 lttng_dynamic_pointer_array_reset(&tracepoint->exclusions);
40 free(tracepoint->pattern);
41 free(tracepoint->filter_expression);
42 free(tracepoint->internal_filter.filter);
43 free(tracepoint->internal_filter.bytecode);
44 free(tracepoint);
45 }
46
47 static bool lttng_event_rule_user_tracepoint_validate(const struct lttng_event_rule *rule)
48 {
49 bool valid = false;
50 struct lttng_event_rule_user_tracepoint *tracepoint;
51
52 if (!rule) {
53 goto end;
54 }
55
56 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
57
58 /* Required field. */
59 if (!tracepoint->pattern) {
60 ERR("Invalid user tracepoint event rule: a pattern must be set.");
61 goto end;
62 }
63
64 valid = true;
65 end:
66 return valid;
67 }
68
69 static int lttng_event_rule_user_tracepoint_serialize(const struct lttng_event_rule *rule,
70 struct lttng_payload *payload)
71 {
72 int ret, i;
73 size_t pattern_len, filter_expression_len, exclusions_len, header_offset;
74 size_t size_before_log_level_rule;
75 struct lttng_event_rule_user_tracepoint *tracepoint;
76 struct lttng_event_rule_user_tracepoint_comm tracepoint_comm;
77 enum lttng_event_rule_status status;
78 unsigned int exclusion_count;
79 size_t exclusions_appended_len = 0;
80 struct lttng_event_rule_user_tracepoint_comm *header;
81
82 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
83 ret = -1;
84 goto end;
85 }
86
87 header_offset = payload->buffer.size;
88
89 DBG("Serializing user tracepoint event rule.");
90 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
91
92 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
93 rule, &exclusion_count);
94 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
95
96 pattern_len = strlen(tracepoint->pattern) + 1;
97
98 if (tracepoint->filter_expression != nullptr) {
99 filter_expression_len = strlen(tracepoint->filter_expression) + 1;
100 } else {
101 filter_expression_len = 0;
102 }
103
104 exclusions_len = 0;
105 for (i = 0; i < exclusion_count; i++) {
106 const char *exclusion;
107
108 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
109 rule, i, &exclusion);
110 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
111
112 /* Length field. */
113 exclusions_len += sizeof(uint32_t);
114 /* Payload (null terminated). */
115 exclusions_len += strlen(exclusion) + 1;
116 }
117
118 tracepoint_comm.pattern_len = pattern_len;
119 tracepoint_comm.filter_expression_len = filter_expression_len;
120 tracepoint_comm.exclusions_count = exclusion_count;
121 tracepoint_comm.exclusions_len = exclusions_len;
122
123 ret = lttng_dynamic_buffer_append(
124 &payload->buffer, &tracepoint_comm, sizeof(tracepoint_comm));
125 if (ret) {
126 goto end;
127 }
128
129 ret = lttng_dynamic_buffer_append(&payload->buffer, tracepoint->pattern, pattern_len);
130 if (ret) {
131 goto end;
132 }
133
134 ret = lttng_dynamic_buffer_append(
135 &payload->buffer, tracepoint->filter_expression, filter_expression_len);
136 if (ret) {
137 goto end;
138 }
139
140 size_before_log_level_rule = payload->buffer.size;
141
142 ret = lttng_log_level_rule_serialize(tracepoint->log_level_rule, payload);
143 if (ret < 0) {
144 goto end;
145 }
146
147 header = (typeof(header)) ((char *) payload->buffer.data + header_offset);
148 header->log_level_rule_len = payload->buffer.size - size_before_log_level_rule;
149
150 for (i = 0; i < exclusion_count; i++) {
151 size_t len;
152 uint32_t serialized_len;
153 const char *exclusion;
154
155 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
156 rule, i, &exclusion);
157 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
158
159 len = strlen(exclusion) + 1;
160
161 serialized_len = len;
162 /* Append exclusion length, includes the null terminator. */
163 ret = lttng_dynamic_buffer_append(
164 &payload->buffer, &serialized_len, sizeof(serialized_len));
165 if (ret) {
166 goto end;
167 }
168
169 exclusions_appended_len += sizeof(uint32_t);
170
171 /* Include the '\0' in the payload. */
172 ret = lttng_dynamic_buffer_append(&payload->buffer, exclusion, len);
173 if (ret) {
174 goto end;
175 }
176
177 exclusions_appended_len += len;
178 }
179
180 LTTNG_ASSERT(exclusions_len == exclusions_appended_len);
181
182 end:
183 return ret;
184 }
185
186 static bool lttng_event_rule_user_tracepoint_is_equal(const struct lttng_event_rule *_a,
187 const struct lttng_event_rule *_b)
188 {
189 int i;
190 bool is_equal = false;
191 struct lttng_event_rule_user_tracepoint *a, *b;
192 unsigned int count_a, count_b;
193 enum lttng_event_rule_status status;
194
195 a = lttng::utils::container_of(_a, &lttng_event_rule_user_tracepoint::parent);
196 b = lttng::utils::container_of(_b, &lttng_event_rule_user_tracepoint::parent);
197
198 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_a, &count_a);
199 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
200 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b, &count_b);
201 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
202
203 /* Quick checks. */
204 if (count_a != count_b) {
205 goto end;
206 }
207
208 if (!!a->filter_expression != !!b->filter_expression) {
209 goto end;
210 }
211
212 /* Long check. */
213 LTTNG_ASSERT(a->pattern);
214 LTTNG_ASSERT(b->pattern);
215 if (strcmp(a->pattern, b->pattern) != 0) {
216 goto end;
217 }
218
219 if (a->filter_expression && b->filter_expression) {
220 if (strcmp(a->filter_expression, b->filter_expression) != 0) {
221 goto end;
222 }
223 } else if (!!a->filter_expression != !!b->filter_expression) {
224 /* One is set; not the other. */
225 goto end;
226 }
227
228 if (!lttng_log_level_rule_is_equal(a->log_level_rule, b->log_level_rule)) {
229 goto end;
230 }
231
232 for (i = 0; i < count_a; i++) {
233 const char *exclusion_a, *exclusion_b;
234
235 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
236 _a, i, &exclusion_a);
237 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
238 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
239 _b, i, &exclusion_b);
240 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
241 if (strcmp(exclusion_a, exclusion_b) != 0) {
242 goto end;
243 }
244 }
245
246 is_equal = true;
247 end:
248 return is_equal;
249 }
250
251 static enum lttng_error_code
252 lttng_event_rule_user_tracepoint_generate_filter_bytecode(struct lttng_event_rule *rule,
253 const struct lttng_credentials *creds)
254 {
255 int ret;
256 enum lttng_error_code ret_code;
257 struct lttng_event_rule_user_tracepoint *tracepoint;
258 enum lttng_event_rule_status status;
259 const char *filter;
260 struct lttng_bytecode *bytecode = nullptr;
261
262 LTTNG_ASSERT(rule);
263
264 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
265
266 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
267 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
268 filter = nullptr;
269 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
270 ret_code = LTTNG_ERR_FILTER_INVAL;
271 goto end;
272 }
273
274 if (filter && filter[0] == '\0') {
275 ret_code = LTTNG_ERR_FILTER_INVAL;
276 goto error;
277 }
278
279 if (filter) {
280 tracepoint->internal_filter.filter = strdup(filter);
281 if (tracepoint->internal_filter.filter == nullptr) {
282 ret_code = LTTNG_ERR_NOMEM;
283 goto error;
284 }
285 } else {
286 tracepoint->internal_filter.filter = nullptr;
287 }
288
289 if (tracepoint->internal_filter.filter == nullptr) {
290 ret_code = LTTNG_OK;
291 goto end;
292 }
293
294 ret = run_as_generate_filter_bytecode(tracepoint->internal_filter.filter, creds, &bytecode);
295 if (ret) {
296 ret_code = LTTNG_ERR_FILTER_INVAL;
297 goto end;
298 }
299
300 tracepoint->internal_filter.bytecode = bytecode;
301 bytecode = nullptr;
302 ret_code = LTTNG_OK;
303
304 error:
305 end:
306 free(bytecode);
307 return ret_code;
308 }
309
310 static const char *
311 lttng_event_rule_user_tracepoint_get_internal_filter(const struct lttng_event_rule *rule)
312 {
313 struct lttng_event_rule_user_tracepoint *tracepoint;
314
315 LTTNG_ASSERT(rule);
316 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
317 return tracepoint->internal_filter.filter;
318 }
319
320 static const struct lttng_bytecode *
321 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode(const struct lttng_event_rule *rule)
322 {
323 struct lttng_event_rule_user_tracepoint *tracepoint;
324
325 LTTNG_ASSERT(rule);
326 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
327 return tracepoint->internal_filter.bytecode;
328 }
329
330 static enum lttng_event_rule_generate_exclusions_status
331 lttng_event_rule_user_tracepoint_generate_exclusions(const struct lttng_event_rule *rule,
332 struct lttng_event_exclusion **_exclusions)
333 {
334 unsigned int nb_exclusions = 0, i;
335 struct lttng_event_exclusion *exclusions;
336 enum lttng_event_rule_status event_rule_status;
337 enum lttng_event_rule_generate_exclusions_status ret_status;
338
339 LTTNG_ASSERT(_exclusions);
340
341 event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
342 rule, &nb_exclusions);
343 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
344 if (nb_exclusions == 0) {
345 /* Nothing to do. */
346 exclusions = nullptr;
347 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
348 goto end;
349 }
350
351 exclusions = zmalloc<lttng_event_exclusion>(sizeof(struct lttng_event_exclusion) +
352 (LTTNG_SYMBOL_NAME_LEN * nb_exclusions));
353 if (!exclusions) {
354 PERROR("Failed to allocate exclusions buffer");
355 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OUT_OF_MEMORY;
356 goto end;
357 }
358
359 exclusions->count = nb_exclusions;
360 for (i = 0; i < nb_exclusions; i++) {
361 int copy_ret;
362 const char *exclusion_str;
363
364 event_rule_status =
365 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
366 rule, i, &exclusion_str);
367 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
368
369 copy_ret = lttng_strncpy(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i),
370 exclusion_str,
371 sizeof(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i)));
372 if (copy_ret) {
373 free(exclusions);
374 exclusions = nullptr;
375 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_ERROR;
376 goto end;
377 }
378 }
379
380 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_OK;
381
382 end:
383 *_exclusions = exclusions;
384 return ret_status;
385 }
386
387 static void destroy_lttng_exclusions_element(void *ptr)
388 {
389 free(ptr);
390 }
391
392 static unsigned long lttng_event_rule_user_tracepoint_hash(const struct lttng_event_rule *rule)
393 {
394 unsigned long hash;
395 unsigned int i, exclusion_count;
396 enum lttng_event_rule_status status;
397 struct lttng_event_rule_user_tracepoint *tp_rule =
398 lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
399
400 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT, lttng_ht_seed);
401 hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
402
403 if (tp_rule->filter_expression) {
404 hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
405 }
406
407 if (tp_rule->log_level_rule) {
408 hash ^= lttng_log_level_rule_hash(tp_rule->log_level_rule);
409 }
410
411 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
412 rule, &exclusion_count);
413 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
414
415 for (i = 0; i < exclusion_count; i++) {
416 const char *exclusion;
417
418 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
419 rule, i, &exclusion);
420 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
421 hash ^= hash_key_str(exclusion, lttng_ht_seed);
422 }
423
424 return hash;
425 }
426
427 static enum lttng_error_code
428 lttng_event_rule_user_tracepoint_mi_serialize(const struct lttng_event_rule *rule,
429 struct mi_writer *writer)
430 {
431 int ret;
432 enum lttng_error_code ret_code;
433 enum lttng_event_rule_status status;
434 const char *filter = nullptr;
435 const char *name_pattern = nullptr;
436 const struct lttng_log_level_rule *log_level_rule = nullptr;
437 unsigned int exclusion_count = 0;
438
439 LTTNG_ASSERT(rule);
440 LTTNG_ASSERT(writer);
441 LTTNG_ASSERT(IS_USER_TRACEPOINT_EVENT_RULE(rule));
442
443 status = lttng_event_rule_user_tracepoint_get_name_pattern(rule, &name_pattern);
444 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
445 LTTNG_ASSERT(name_pattern);
446
447 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
448 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
449 status == LTTNG_EVENT_RULE_STATUS_UNSET);
450
451 status = lttng_event_rule_user_tracepoint_get_log_level_rule(rule, &log_level_rule);
452 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
453 status == LTTNG_EVENT_RULE_STATUS_UNSET);
454
455 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
456 rule, &exclusion_count);
457 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
458
459 /* Open event rule user tracepoint element. */
460 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_rule_user_tracepoint);
461 if (ret) {
462 goto mi_error;
463 }
464
465 /* Name pattern. */
466 ret = mi_lttng_writer_write_element_string(
467 writer, mi_lttng_element_event_rule_name_pattern, name_pattern);
468 if (ret) {
469 goto mi_error;
470 }
471
472 /* Filter expression. */
473 if (filter != nullptr) {
474 ret = mi_lttng_writer_write_element_string(
475 writer, mi_lttng_element_event_rule_filter_expression, filter);
476 if (ret) {
477 goto mi_error;
478 }
479 }
480
481 /* Log level rule. */
482 if (log_level_rule) {
483 ret_code = lttng_log_level_rule_mi_serialize(log_level_rule, writer);
484 if (ret_code != LTTNG_OK) {
485 goto end;
486 }
487 }
488
489 if (exclusion_count != 0) {
490 int i;
491
492 /* Open the exclusion list. */
493 ret = mi_lttng_writer_open_element(
494 writer,
495 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions);
496 if (ret) {
497 goto mi_error;
498 }
499
500 for (i = 0; i < exclusion_count; i++) {
501 const char *exclusion;
502
503 status =
504 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
505 rule, i, &exclusion);
506 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
507
508 ret = mi_lttng_writer_write_element_string(
509 writer,
510 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion,
511 exclusion);
512 if (ret) {
513 goto mi_error;
514 }
515 }
516
517 /* Close the list. */
518 ret = mi_lttng_writer_close_element(writer);
519 if (ret) {
520 goto mi_error;
521 }
522 }
523
524 /* Close event rule user tracepoint element. */
525 ret = mi_lttng_writer_close_element(writer);
526 if (ret) {
527 goto mi_error;
528 }
529
530 ret_code = LTTNG_OK;
531 goto end;
532
533 mi_error:
534 ret_code = LTTNG_ERR_MI_IO_FAIL;
535 end:
536 return ret_code;
537 }
538
539 struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void)
540 {
541 struct lttng_event_rule *rule = nullptr;
542 struct lttng_event_rule_user_tracepoint *tp_rule;
543 enum lttng_event_rule_status status;
544
545 tp_rule = zmalloc<lttng_event_rule_user_tracepoint>();
546 if (!tp_rule) {
547 goto end;
548 }
549
550 rule = &tp_rule->parent;
551 lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT);
552 tp_rule->parent.validate = lttng_event_rule_user_tracepoint_validate;
553 tp_rule->parent.serialize = lttng_event_rule_user_tracepoint_serialize;
554 tp_rule->parent.equal = lttng_event_rule_user_tracepoint_is_equal;
555 tp_rule->parent.destroy = lttng_event_rule_user_tracepoint_destroy;
556 tp_rule->parent.generate_filter_bytecode =
557 lttng_event_rule_user_tracepoint_generate_filter_bytecode;
558 tp_rule->parent.get_filter = lttng_event_rule_user_tracepoint_get_internal_filter;
559 tp_rule->parent.get_filter_bytecode =
560 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode;
561 tp_rule->parent.generate_exclusions = lttng_event_rule_user_tracepoint_generate_exclusions;
562 tp_rule->parent.hash = lttng_event_rule_user_tracepoint_hash;
563 tp_rule->parent.mi_serialize = lttng_event_rule_user_tracepoint_mi_serialize;
564
565 /* Not necessary for now. */
566 tp_rule->parent.generate_lttng_event = nullptr;
567
568 tp_rule->log_level_rule = nullptr;
569
570 lttng_dynamic_pointer_array_init(&tp_rule->exclusions, destroy_lttng_exclusions_element);
571
572 /* Default pattern is '*'. */
573 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, "*");
574 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
575 lttng_event_rule_destroy(rule);
576 rule = nullptr;
577 }
578
579 end:
580 return rule;
581 }
582
583 ssize_t lttng_event_rule_user_tracepoint_create_from_payload(struct lttng_payload_view *view,
584 struct lttng_event_rule **_event_rule)
585 {
586 ssize_t ret, offset = 0;
587 int i;
588 enum lttng_event_rule_status status;
589 const struct lttng_event_rule_user_tracepoint_comm *tracepoint_comm;
590 const char *pattern;
591 const char *filter_expression = nullptr;
592 const char **exclusions = nullptr;
593 const uint32_t *exclusion_len;
594 const char *exclusion;
595 struct lttng_buffer_view current_buffer_view;
596 struct lttng_event_rule *rule = nullptr;
597 struct lttng_log_level_rule *log_level_rule = nullptr;
598
599 if (!_event_rule) {
600 ret = -1;
601 goto end;
602 }
603
604 current_buffer_view =
605 lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*tracepoint_comm));
606 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
607 ERR("Failed to initialize from malformed event rule tracepoint: buffer too short to contain header.");
608 ret = -1;
609 goto end;
610 }
611
612 tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data;
613
614 rule = lttng_event_rule_user_tracepoint_create();
615 if (!rule) {
616 ERR("Failed to create event rule user tracepoint.");
617 ret = -1;
618 goto end;
619 }
620
621 /* Skip to payload. */
622 offset += current_buffer_view.size;
623
624 /* Map the pattern. */
625 current_buffer_view =
626 lttng_buffer_view_from_view(&view->buffer, offset, tracepoint_comm->pattern_len);
627
628 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
629 ret = -1;
630 goto end;
631 }
632
633 pattern = current_buffer_view.data;
634 if (!lttng_buffer_view_contains_string(
635 &current_buffer_view, pattern, tracepoint_comm->pattern_len)) {
636 ret = -1;
637 goto end;
638 }
639
640 /* Skip after the pattern. */
641 offset += tracepoint_comm->pattern_len;
642
643 if (!tracepoint_comm->filter_expression_len) {
644 goto skip_filter_expression;
645 }
646
647 /* Map the filter_expression. */
648 current_buffer_view = lttng_buffer_view_from_view(
649 &view->buffer, offset, tracepoint_comm->filter_expression_len);
650 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
651 ret = -1;
652 goto end;
653 }
654
655 filter_expression = current_buffer_view.data;
656 if (!lttng_buffer_view_contains_string(&current_buffer_view,
657 filter_expression,
658 tracepoint_comm->filter_expression_len)) {
659 ret = -1;
660 goto end;
661 }
662
663 /* Skip after the pattern. */
664 offset += tracepoint_comm->filter_expression_len;
665
666 skip_filter_expression:
667 if (!tracepoint_comm->log_level_rule_len) {
668 goto skip_log_level_rule;
669 }
670
671 {
672 /* Map the log level rule. */
673 struct lttng_payload_view current_payload_view = lttng_payload_view_from_view(
674 view, offset, tracepoint_comm->log_level_rule_len);
675
676 ret = lttng_log_level_rule_create_from_payload(&current_payload_view,
677 &log_level_rule);
678 if (ret < 0) {
679 ret = -1;
680 goto end;
681 }
682
683 LTTNG_ASSERT(ret == tracepoint_comm->log_level_rule_len);
684 }
685
686 /* Skip after the log level rule. */
687 offset += tracepoint_comm->log_level_rule_len;
688
689 skip_log_level_rule:
690 for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
691 current_buffer_view =
692 lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*exclusion_len));
693 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
694 ret = -1;
695 goto end;
696 }
697
698 exclusion_len = (typeof(exclusion_len)) current_buffer_view.data;
699 offset += sizeof(*exclusion_len);
700
701 current_buffer_view =
702 lttng_buffer_view_from_view(&view->buffer, offset, *exclusion_len);
703 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
704 ret = -1;
705 goto end;
706 }
707
708 exclusion = current_buffer_view.data;
709 if (!lttng_buffer_view_contains_string(
710 &current_buffer_view, exclusion, *exclusion_len)) {
711 ret = -1;
712 goto end;
713 }
714
715 status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule,
716 exclusion);
717 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
718 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
719 exclusion);
720 ret = -1;
721 goto end;
722 }
723
724 /* Skip to next exclusion. */
725 offset += *exclusion_len;
726 }
727
728 status = lttng_event_rule_user_tracepoint_set_name_pattern(rule, pattern);
729 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
730 ERR("Failed to set event rule user tracepoint pattern.");
731 ret = -1;
732 goto end;
733 }
734
735 if (filter_expression) {
736 status = lttng_event_rule_user_tracepoint_set_filter(rule, filter_expression);
737 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
738 ERR("Failed to set event rule user tracepoint pattern.");
739 ret = -1;
740 goto end;
741 }
742 }
743
744 if (log_level_rule) {
745 status = lttng_event_rule_user_tracepoint_set_log_level_rule(rule, log_level_rule);
746 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
747 ERR("Failed to set event rule user tracepoint log level rule.");
748 ret = -1;
749 goto end;
750 }
751 }
752
753 *_event_rule = rule;
754 rule = nullptr;
755 ret = offset;
756 end:
757 free(exclusions);
758 lttng_log_level_rule_destroy(log_level_rule);
759 lttng_event_rule_destroy(rule);
760 return ret;
761 }
762
763 enum lttng_event_rule_status
764 lttng_event_rule_user_tracepoint_set_name_pattern(struct lttng_event_rule *rule,
765 const char *pattern)
766 {
767 char *pattern_copy = nullptr;
768 struct lttng_event_rule_user_tracepoint *tracepoint;
769 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
770
771 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern || strlen(pattern) == 0) {
772 status = LTTNG_EVENT_RULE_STATUS_INVALID;
773 goto end;
774 }
775
776 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
777 pattern_copy = strdup(pattern);
778 if (!pattern_copy) {
779 status = LTTNG_EVENT_RULE_STATUS_ERROR;
780 goto end;
781 }
782
783 /* Normalize the pattern. */
784 strutils_normalize_star_glob_pattern(pattern_copy);
785
786 free(tracepoint->pattern);
787
788 tracepoint->pattern = pattern_copy;
789 pattern_copy = nullptr;
790 end:
791 return status;
792 }
793
794 enum lttng_event_rule_status
795 lttng_event_rule_user_tracepoint_get_name_pattern(const struct lttng_event_rule *rule,
796 const char **pattern)
797 {
798 struct lttng_event_rule_user_tracepoint *tracepoint;
799 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
800
801 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern) {
802 status = LTTNG_EVENT_RULE_STATUS_INVALID;
803 goto end;
804 }
805
806 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
807 if (!tracepoint->pattern) {
808 status = LTTNG_EVENT_RULE_STATUS_UNSET;
809 goto end;
810 }
811
812 *pattern = tracepoint->pattern;
813 end:
814 return status;
815 }
816
817 enum lttng_event_rule_status
818 lttng_event_rule_user_tracepoint_set_filter(struct lttng_event_rule *rule, const char *expression)
819 {
820 char *expression_copy = nullptr;
821 struct lttng_event_rule_user_tracepoint *tracepoint;
822 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
823
824 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression ||
825 strlen(expression) == 0) {
826 status = LTTNG_EVENT_RULE_STATUS_INVALID;
827 goto end;
828 }
829
830 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
831 expression_copy = strdup(expression);
832 if (!expression_copy) {
833 PERROR("Failed to copy filter expression");
834 status = LTTNG_EVENT_RULE_STATUS_ERROR;
835 goto end;
836 }
837
838 if (tracepoint->filter_expression) {
839 free(tracepoint->filter_expression);
840 }
841
842 tracepoint->filter_expression = expression_copy;
843 expression_copy = nullptr;
844 end:
845 return status;
846 }
847
848 enum lttng_event_rule_status
849 lttng_event_rule_user_tracepoint_get_filter(const struct lttng_event_rule *rule,
850 const char **expression)
851 {
852 struct lttng_event_rule_user_tracepoint *tracepoint;
853 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
854
855 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !expression) {
856 status = LTTNG_EVENT_RULE_STATUS_INVALID;
857 goto end;
858 }
859
860 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
861 if (!tracepoint->filter_expression) {
862 status = LTTNG_EVENT_RULE_STATUS_UNSET;
863 goto end;
864 }
865
866 *expression = tracepoint->filter_expression;
867 end:
868 return status;
869 }
870
871 static bool log_level_rule_valid(const struct lttng_log_level_rule *rule)
872 {
873 bool valid = false;
874 enum lttng_log_level_rule_status status;
875 int level;
876
877 switch (lttng_log_level_rule_get_type(rule)) {
878 case LTTNG_LOG_LEVEL_RULE_TYPE_EXACTLY:
879 status = lttng_log_level_rule_exactly_get_level(rule, &level);
880 break;
881 case LTTNG_LOG_LEVEL_RULE_TYPE_AT_LEAST_AS_SEVERE_AS:
882 status = lttng_log_level_rule_at_least_as_severe_as_get_level(rule, &level);
883 break;
884 default:
885 abort();
886 }
887
888 LTTNG_ASSERT(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
889
890 if (level < LTTNG_LOGLEVEL_EMERG) {
891 /* Invalid. */
892 goto end;
893 }
894 if (level > LTTNG_LOGLEVEL_DEBUG) {
895 /* Invalid. */
896 goto end;
897 }
898
899 valid = true;
900
901 end:
902 return valid;
903 }
904
905 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_log_level_rule(
906 struct lttng_event_rule *rule, const struct lttng_log_level_rule *log_level_rule)
907 {
908 struct lttng_event_rule_user_tracepoint *tracepoint;
909 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
910 struct lttng_log_level_rule *copy = nullptr;
911
912 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
913 status = LTTNG_EVENT_RULE_STATUS_INVALID;
914 goto end;
915 }
916
917 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
918
919 if (!log_level_rule_valid(log_level_rule)) {
920 status = LTTNG_EVENT_RULE_STATUS_INVALID;
921 goto end;
922 }
923
924 copy = lttng_log_level_rule_copy(log_level_rule);
925 if (copy == nullptr) {
926 status = LTTNG_EVENT_RULE_STATUS_ERROR;
927 goto end;
928 }
929
930 if (tracepoint->log_level_rule) {
931 lttng_log_level_rule_destroy(tracepoint->log_level_rule);
932 }
933
934 tracepoint->log_level_rule = copy;
935
936 end:
937 return status;
938 }
939
940 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_log_level_rule(
941 const struct lttng_event_rule *rule, const struct lttng_log_level_rule **log_level_rule)
942 {
943 struct lttng_event_rule_user_tracepoint *tracepoint;
944 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
945
946 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !log_level_rule) {
947 status = LTTNG_EVENT_RULE_STATUS_INVALID;
948 goto end;
949 }
950
951 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
952 if (tracepoint->log_level_rule == nullptr) {
953 status = LTTNG_EVENT_RULE_STATUS_UNSET;
954 goto end;
955 }
956
957 *log_level_rule = tracepoint->log_level_rule;
958 end:
959 return status;
960 }
961
962 enum lttng_event_rule_status
963 lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(struct lttng_event_rule *rule,
964 const char *exclusion)
965 {
966 int ret;
967 char *exclusion_copy = nullptr;
968 struct lttng_event_rule_user_tracepoint *tracepoint;
969 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
970
971 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !exclusion) {
972 status = LTTNG_EVENT_RULE_STATUS_INVALID;
973 goto end;
974 }
975
976 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
977
978 if (strlen(exclusion) >= LTTNG_SYMBOL_NAME_LEN) {
979 status = LTTNG_EVENT_RULE_STATUS_INVALID;
980 goto end;
981 }
982
983 exclusion_copy = strdup(exclusion);
984 if (!exclusion_copy) {
985 status = LTTNG_EVENT_RULE_STATUS_ERROR;
986 goto end;
987 }
988
989 ret = lttng_dynamic_pointer_array_add_pointer(&tracepoint->exclusions, exclusion_copy);
990 if (ret < 0) {
991 status = LTTNG_EVENT_RULE_STATUS_ERROR;
992 goto end;
993 }
994
995 exclusion_copy = nullptr;
996 end:
997 free(exclusion_copy);
998 return status;
999 }
1000
1001 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
1002 const struct lttng_event_rule *rule, unsigned int *count)
1003 {
1004 struct lttng_event_rule_user_tracepoint *tracepoint;
1005 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1006
1007 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !count) {
1008 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1009 goto end;
1010 }
1011
1012 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
1013 *count = lttng_dynamic_pointer_array_get_count(&tracepoint->exclusions);
1014 end:
1015 return status;
1016 }
1017
1018 enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
1019 const struct lttng_event_rule *rule, unsigned int index, const char **exclusion)
1020 {
1021 unsigned int count;
1022 struct lttng_event_rule_user_tracepoint *tracepoint;
1023 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
1024
1025 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !exclusion) {
1026 status = LTTNG_EVENT_RULE_STATUS_INVALID;
1027 goto end;
1028 }
1029
1030 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
1031 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule, &count) !=
1032 LTTNG_EVENT_RULE_STATUS_OK) {
1033 goto end;
1034 }
1035
1036 if (index >= count) {
1037 goto end;
1038 }
1039
1040 *exclusion = (const char *) lttng_dynamic_pointer_array_get_pointer(&tracepoint->exclusions,
1041 index);
1042 end:
1043 return status;
1044 }
This page took 0.069366 seconds and 4 git commands to generate.