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