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