Fix: truncated len in lttng_event_rule_user_tracepoint_serialize()
[lttng-tools.git] / src / common / event-rule / user-tracepoint.cpp
CommitLineData
0a23a07d
JR
1/*
2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
c9e313bc
SM
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>
28ab034a 19
c9e313bc
SM
20#include <lttng/event-rule/event-rule-internal.hpp>
21#include <lttng/event-rule/user-tracepoint-internal.hpp>
0a23a07d 22#include <lttng/event.h>
6a751b95 23#include <lttng/log-level-rule.h>
0a23a07d
JR
24
25#define IS_USER_TRACEPOINT_EVENT_RULE(rule) \
26 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT)
27
28static void lttng_event_rule_user_tracepoint_destroy(struct lttng_event_rule *rule)
29{
30 struct lttng_event_rule_user_tracepoint *tracepoint;
31
cd9adb8b 32 if (rule == nullptr) {
0a23a07d
JR
33 return;
34 }
35
28ab034a 36 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
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
28ab034a 47static bool lttng_event_rule_user_tracepoint_validate(const struct lttng_event_rule *rule)
0a23a07d
JR
48{
49 bool valid = false;
50 struct lttng_event_rule_user_tracepoint *tracepoint;
51
52 if (!rule) {
53 goto end;
54 }
55
28ab034a 56 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
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;
65end:
66 return valid;
67}
68
28ab034a
JG
69static int lttng_event_rule_user_tracepoint_serialize(const struct lttng_event_rule *rule,
70 struct lttng_payload *payload)
0a23a07d
JR
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.");
28ab034a 90 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d 91
28ab034a
JG
92 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
93 rule, &exclusion_count);
a0377dfe 94 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
95
96 pattern_len = strlen(tracepoint->pattern) + 1;
97
cd9adb8b 98 if (tracepoint->filter_expression != nullptr) {
28ab034a 99 filter_expression_len = strlen(tracepoint->filter_expression) + 1;
0a23a07d
JR
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(
28ab034a 109 rule, i, &exclusion);
a0377dfe 110 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
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
28ab034a
JG
123 ret = lttng_dynamic_buffer_append(
124 &payload->buffer, &tracepoint_comm, sizeof(tracepoint_comm));
0a23a07d
JR
125 if (ret) {
126 goto end;
127 }
128
28ab034a 129 ret = lttng_dynamic_buffer_append(&payload->buffer, tracepoint->pattern, pattern_len);
0a23a07d
JR
130 if (ret) {
131 goto end;
132 }
133
28ab034a
JG
134 ret = lttng_dynamic_buffer_append(
135 &payload->buffer, tracepoint->filter_expression, filter_expression_len);
0a23a07d
JR
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);
28ab034a 148 header->log_level_rule_len = payload->buffer.size - size_before_log_level_rule;
0a23a07d
JR
149
150 for (i = 0; i < exclusion_count; i++) {
151 size_t len;
7cb80419 152 uint32_t serialized_len;
0a23a07d
JR
153 const char *exclusion;
154
155 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
28ab034a 156 rule, i, &exclusion);
a0377dfe 157 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
158
159 len = strlen(exclusion) + 1;
7cb80419
MJ
160
161 serialized_len = len;
0a23a07d 162 /* Append exclusion length, includes the null terminator. */
7cb80419 163 ret = lttng_dynamic_buffer_append(&payload->buffer, &serialized_len, sizeof(serialized_len));
0a23a07d
JR
164 if (ret) {
165 goto end;
166 }
167
168 exclusions_appended_len += sizeof(uint32_t);
169
170 /* Include the '\0' in the payload. */
28ab034a 171 ret = lttng_dynamic_buffer_append(&payload->buffer, exclusion, len);
0a23a07d
JR
172 if (ret) {
173 goto end;
174 }
175
176 exclusions_appended_len += len;
177 }
178
a0377dfe 179 LTTNG_ASSERT(exclusions_len == exclusions_appended_len);
0a23a07d
JR
180
181end:
182 return ret;
183}
184
28ab034a
JG
185static bool lttng_event_rule_user_tracepoint_is_equal(const struct lttng_event_rule *_a,
186 const struct lttng_event_rule *_b)
0a23a07d
JR
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
0114db0e
JG
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);
0a23a07d
JR
196
197 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_a, &count_a);
a0377dfe 198 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d 199 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(_b, &count_b);
a0377dfe 200 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
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. */
a0377dfe
FD
212 LTTNG_ASSERT(a->pattern);
213 LTTNG_ASSERT(b->pattern);
5c7248cd 214 if (strcmp(a->pattern, b->pattern) != 0) {
0a23a07d
JR
215 goto end;
216 }
217
218 if (a->filter_expression && b->filter_expression) {
5c7248cd 219 if (strcmp(a->filter_expression, b->filter_expression) != 0) {
0a23a07d
JR
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
28ab034a 227 if (!lttng_log_level_rule_is_equal(a->log_level_rule, b->log_level_rule)) {
0a23a07d
JR
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(
28ab034a 235 _a, i, &exclusion_a);
a0377dfe 236 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d 237 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
28ab034a 238 _b, i, &exclusion_b);
a0377dfe 239 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
5c7248cd 240 if (strcmp(exclusion_a, exclusion_b) != 0) {
0a23a07d
JR
241 goto end;
242 }
243 }
244
245 is_equal = true;
246end:
247 return is_equal;
248}
249
250static enum lttng_error_code
28ab034a
JG
251lttng_event_rule_user_tracepoint_generate_filter_bytecode(struct lttng_event_rule *rule,
252 const struct lttng_credentials *creds)
0a23a07d
JR
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;
cd9adb8b 259 struct lttng_bytecode *bytecode = nullptr;
0a23a07d 260
a0377dfe 261 LTTNG_ASSERT(rule);
0a23a07d 262
28ab034a 263 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
264
265 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
266 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
cd9adb8b 267 filter = nullptr;
0a23a07d
JR
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);
cd9adb8b 280 if (tracepoint->internal_filter.filter == nullptr) {
0a23a07d
JR
281 ret_code = LTTNG_ERR_NOMEM;
282 goto error;
283 }
284 } else {
cd9adb8b 285 tracepoint->internal_filter.filter = nullptr;
0a23a07d
JR
286 }
287
cd9adb8b 288 if (tracepoint->internal_filter.filter == nullptr) {
0a23a07d
JR
289 ret_code = LTTNG_OK;
290 goto end;
291 }
292
28ab034a 293 ret = run_as_generate_filter_bytecode(tracepoint->internal_filter.filter, creds, &bytecode);
0a23a07d
JR
294 if (ret) {
295 ret_code = LTTNG_ERR_FILTER_INVAL;
296 goto end;
297 }
298
299 tracepoint->internal_filter.bytecode = bytecode;
cd9adb8b 300 bytecode = nullptr;
0a23a07d
JR
301 ret_code = LTTNG_OK;
302
303error:
304end:
305 free(bytecode);
306 return ret_code;
307}
308
28ab034a
JG
309static const char *
310lttng_event_rule_user_tracepoint_get_internal_filter(const struct lttng_event_rule *rule)
0a23a07d
JR
311{
312 struct lttng_event_rule_user_tracepoint *tracepoint;
313
a0377dfe 314 LTTNG_ASSERT(rule);
28ab034a 315 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
316 return tracepoint->internal_filter.filter;
317}
318
319static const struct lttng_bytecode *
28ab034a 320lttng_event_rule_user_tracepoint_get_internal_filter_bytecode(const struct lttng_event_rule *rule)
0a23a07d
JR
321{
322 struct lttng_event_rule_user_tracepoint *tracepoint;
323
a0377dfe 324 LTTNG_ASSERT(rule);
28ab034a 325 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
326 return tracepoint->internal_filter.bytecode;
327}
328
329static enum lttng_event_rule_generate_exclusions_status
28ab034a
JG
330lttng_event_rule_user_tracepoint_generate_exclusions(const struct lttng_event_rule *rule,
331 struct lttng_event_exclusion **_exclusions)
0a23a07d
JR
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
a0377dfe 338 LTTNG_ASSERT(_exclusions);
0a23a07d
JR
339
340 event_rule_status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
28ab034a 341 rule, &nb_exclusions);
a0377dfe 342 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
343 if (nb_exclusions == 0) {
344 /* Nothing to do. */
cd9adb8b 345 exclusions = nullptr;
0a23a07d
JR
346 ret_status = LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
347 goto end;
348 }
349
28ab034a
JG
350 exclusions = zmalloc<lttng_event_exclusion>(sizeof(struct lttng_event_exclusion) +
351 (LTTNG_SYMBOL_NAME_LEN * nb_exclusions));
0a23a07d
JR
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 =
28ab034a
JG
364 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
365 rule, i, &exclusion_str);
a0377dfe 366 LTTNG_ASSERT(event_rule_status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d 367
28ab034a
JG
368 copy_ret = lttng_strncpy(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i),
369 exclusion_str,
370 sizeof(LTTNG_EVENT_EXCLUSION_NAME_AT(exclusions, i)));
0a23a07d
JR
371 if (copy_ret) {
372 free(exclusions);
cd9adb8b 373 exclusions = nullptr;
0a23a07d
JR
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
381end:
382 *_exclusions = exclusions;
383 return ret_status;
384}
385
386static void destroy_lttng_exclusions_element(void *ptr)
387{
388 free(ptr);
389}
390
28ab034a 391static unsigned long lttng_event_rule_user_tracepoint_hash(const struct lttng_event_rule *rule)
0a23a07d
JR
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 =
28ab034a 397 lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d 398
28ab034a 399 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USER_TRACEPOINT, lttng_ht_seed);
0a23a07d
JR
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
28ab034a
JG
410 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
411 rule, &exclusion_count);
a0377dfe 412 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
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(
28ab034a 418 rule, i, &exclusion);
a0377dfe 419 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
0a23a07d
JR
420 hash ^= hash_key_str(exclusion, lttng_ht_seed);
421 }
422
423 return hash;
424}
425
28ab034a
JG
426static enum lttng_error_code
427lttng_event_rule_user_tracepoint_mi_serialize(const struct lttng_event_rule *rule,
428 struct mi_writer *writer)
6a751b95
JR
429{
430 int ret;
431 enum lttng_error_code ret_code;
432 enum lttng_event_rule_status status;
cd9adb8b
JG
433 const char *filter = nullptr;
434 const char *name_pattern = nullptr;
435 const struct lttng_log_level_rule *log_level_rule = nullptr;
6a751b95
JR
436 unsigned int exclusion_count = 0;
437
a0377dfe
FD
438 LTTNG_ASSERT(rule);
439 LTTNG_ASSERT(writer);
440 LTTNG_ASSERT(IS_USER_TRACEPOINT_EVENT_RULE(rule));
6a751b95 441
28ab034a 442 status = lttng_event_rule_user_tracepoint_get_name_pattern(rule, &name_pattern);
a0377dfe
FD
443 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
444 LTTNG_ASSERT(name_pattern);
6a751b95
JR
445
446 status = lttng_event_rule_user_tracepoint_get_filter(rule, &filter);
a0377dfe 447 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
28ab034a 448 status == LTTNG_EVENT_RULE_STATUS_UNSET);
6a751b95 449
28ab034a 450 status = lttng_event_rule_user_tracepoint_get_log_level_rule(rule, &log_level_rule);
a0377dfe 451 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
28ab034a 452 status == LTTNG_EVENT_RULE_STATUS_UNSET);
6a751b95
JR
453
454 status = lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
28ab034a 455 rule, &exclusion_count);
a0377dfe 456 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
6a751b95
JR
457
458 /* Open event rule user tracepoint element. */
28ab034a 459 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_rule_user_tracepoint);
6a751b95
JR
460 if (ret) {
461 goto mi_error;
462 }
463
464 /* Name pattern. */
28ab034a
JG
465 ret = mi_lttng_writer_write_element_string(
466 writer, mi_lttng_element_event_rule_name_pattern, name_pattern);
6a751b95
JR
467 if (ret) {
468 goto mi_error;
469 }
470
471 /* Filter expression. */
cd9adb8b 472 if (filter != nullptr) {
28ab034a
JG
473 ret = mi_lttng_writer_write_element_string(
474 writer, mi_lttng_element_event_rule_filter_expression, filter);
6a751b95
JR
475 if (ret) {
476 goto mi_error;
477 }
478 }
479
480 /* Log level rule. */
481 if (log_level_rule) {
28ab034a 482 ret_code = lttng_log_level_rule_mi_serialize(log_level_rule, writer);
6a751b95
JR
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. */
28ab034a
JG
492 ret = mi_lttng_writer_open_element(
493 writer,
494 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusions);
6a751b95
JR
495 if (ret) {
496 goto mi_error;
497 }
498
499 for (i = 0; i < exclusion_count; i++) {
500 const char *exclusion;
501
28ab034a
JG
502 status =
503 lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
6a751b95 504 rule, i, &exclusion);
a0377dfe 505 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
6a751b95 506
28ab034a
JG
507 ret = mi_lttng_writer_write_element_string(
508 writer,
509 mi_lttng_element_event_rule_user_tracepoint_name_pattern_exclusion,
510 exclusion);
6a751b95
JR
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
532mi_error:
533 ret_code = LTTNG_ERR_MI_IO_FAIL;
534end:
535 return ret_code;
536}
537
0a23a07d
JR
538struct lttng_event_rule *lttng_event_rule_user_tracepoint_create(void)
539{
cd9adb8b 540 struct lttng_event_rule *rule = nullptr;
0a23a07d
JR
541 struct lttng_event_rule_user_tracepoint *tp_rule;
542 enum lttng_event_rule_status status;
543
64803277 544 tp_rule = zmalloc<lttng_event_rule_user_tracepoint>();
0a23a07d
JR
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 =
28ab034a
JG
556 lttng_event_rule_user_tracepoint_generate_filter_bytecode;
557 tp_rule->parent.get_filter = lttng_event_rule_user_tracepoint_get_internal_filter;
0a23a07d 558 tp_rule->parent.get_filter_bytecode =
28ab034a
JG
559 lttng_event_rule_user_tracepoint_get_internal_filter_bytecode;
560 tp_rule->parent.generate_exclusions = lttng_event_rule_user_tracepoint_generate_exclusions;
0a23a07d 561 tp_rule->parent.hash = lttng_event_rule_user_tracepoint_hash;
6a751b95 562 tp_rule->parent.mi_serialize = lttng_event_rule_user_tracepoint_mi_serialize;
0a23a07d
JR
563
564 /* Not necessary for now. */
cd9adb8b 565 tp_rule->parent.generate_lttng_event = nullptr;
0a23a07d 566
cd9adb8b 567 tp_rule->log_level_rule = nullptr;
0a23a07d 568
28ab034a 569 lttng_dynamic_pointer_array_init(&tp_rule->exclusions, destroy_lttng_exclusions_element);
0a23a07d
JR
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);
cd9adb8b 575 rule = nullptr;
0a23a07d
JR
576 }
577
578end:
579 return rule;
580}
581
28ab034a
JG
582ssize_t lttng_event_rule_user_tracepoint_create_from_payload(struct lttng_payload_view *view,
583 struct lttng_event_rule **_event_rule)
0a23a07d
JR
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;
cd9adb8b
JG
590 const char *filter_expression = nullptr;
591 const char **exclusions = nullptr;
0a23a07d
JR
592 const uint32_t *exclusion_len;
593 const char *exclusion;
594 struct lttng_buffer_view current_buffer_view;
cd9adb8b
JG
595 struct lttng_event_rule *rule = nullptr;
596 struct lttng_log_level_rule *log_level_rule = nullptr;
0a23a07d
JR
597
598 if (!_event_rule) {
599 ret = -1;
600 goto end;
601 }
602
28ab034a
JG
603 current_buffer_view =
604 lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*tracepoint_comm));
0a23a07d
JR
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. */
28ab034a
JG
624 current_buffer_view =
625 lttng_buffer_view_from_view(&view->buffer, offset, tracepoint_comm->pattern_len);
0a23a07d
JR
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;
28ab034a
JG
633 if (!lttng_buffer_view_contains_string(
634 &current_buffer_view, pattern, tracepoint_comm->pattern_len)) {
0a23a07d
JR
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. */
28ab034a
JG
647 current_buffer_view = lttng_buffer_view_from_view(
648 &view->buffer, offset, tracepoint_comm->filter_expression_len);
0a23a07d
JR
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,
28ab034a
JG
656 filter_expression,
657 tracepoint_comm->filter_expression_len)) {
0a23a07d
JR
658 ret = -1;
659 goto end;
660 }
661
662 /* Skip after the pattern. */
663 offset += tracepoint_comm->filter_expression_len;
664
665skip_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. */
28ab034a
JG
672 struct lttng_payload_view current_payload_view = lttng_payload_view_from_view(
673 view, offset, tracepoint_comm->log_level_rule_len);
0a23a07d 674
28ab034a
JG
675 ret = lttng_log_level_rule_create_from_payload(&current_payload_view,
676 &log_level_rule);
0a23a07d
JR
677 if (ret < 0) {
678 ret = -1;
679 goto end;
680 }
681
a0377dfe 682 LTTNG_ASSERT(ret == tracepoint_comm->log_level_rule_len);
0a23a07d
JR
683 }
684
685 /* Skip after the log level rule. */
686 offset += tracepoint_comm->log_level_rule_len;
687
688skip_log_level_rule:
689 for (i = 0; i < tracepoint_comm->exclusions_count; i++) {
28ab034a
JG
690 current_buffer_view =
691 lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*exclusion_len));
0a23a07d
JR
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
28ab034a
JG
700 current_buffer_view =
701 lttng_buffer_view_from_view(&view->buffer, offset, *exclusion_len);
0a23a07d
JR
702 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
703 ret = -1;
704 goto end;
705 }
706
707 exclusion = current_buffer_view.data;
28ab034a
JG
708 if (!lttng_buffer_view_contains_string(
709 &current_buffer_view, exclusion, *exclusion_len)) {
0a23a07d
JR
710 ret = -1;
711 goto end;
712 }
713
28ab034a
JG
714 status = lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(rule,
715 exclusion);
0a23a07d
JR
716 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
717 ERR("Failed to add event rule user tracepoint exclusion \"%s\".",
28ab034a 718 exclusion);
0a23a07d
JR
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) {
28ab034a 735 status = lttng_event_rule_user_tracepoint_set_filter(rule, filter_expression);
0a23a07d
JR
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) {
28ab034a 744 status = lttng_event_rule_user_tracepoint_set_log_level_rule(rule, log_level_rule);
0a23a07d
JR
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;
cd9adb8b 753 rule = nullptr;
0a23a07d
JR
754 ret = offset;
755end:
756 free(exclusions);
757 lttng_log_level_rule_destroy(log_level_rule);
758 lttng_event_rule_destroy(rule);
759 return ret;
760}
761
28ab034a
JG
762enum lttng_event_rule_status
763lttng_event_rule_user_tracepoint_set_name_pattern(struct lttng_event_rule *rule,
764 const char *pattern)
0a23a07d 765{
cd9adb8b 766 char *pattern_copy = nullptr;
0a23a07d
JR
767 struct lttng_event_rule_user_tracepoint *tracepoint;
768 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
769
28ab034a 770 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !pattern || strlen(pattern) == 0) {
0a23a07d
JR
771 status = LTTNG_EVENT_RULE_STATUS_INVALID;
772 goto end;
773 }
774
28ab034a 775 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
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;
cd9adb8b 788 pattern_copy = nullptr;
0a23a07d
JR
789end:
790 return status;
791}
792
28ab034a
JG
793enum lttng_event_rule_status
794lttng_event_rule_user_tracepoint_get_name_pattern(const struct lttng_event_rule *rule,
795 const char **pattern)
0a23a07d
JR
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
28ab034a 805 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
806 if (!tracepoint->pattern) {
807 status = LTTNG_EVENT_RULE_STATUS_UNSET;
808 goto end;
809 }
810
811 *pattern = tracepoint->pattern;
812end:
813 return status;
814}
815
28ab034a
JG
816enum lttng_event_rule_status
817lttng_event_rule_user_tracepoint_set_filter(struct lttng_event_rule *rule, const char *expression)
0a23a07d 818{
cd9adb8b 819 char *expression_copy = nullptr;
0a23a07d
JR
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 ||
28ab034a 824 strlen(expression) == 0) {
0a23a07d
JR
825 status = LTTNG_EVENT_RULE_STATUS_INVALID;
826 goto end;
827 }
828
28ab034a 829 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
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;
cd9adb8b 842 expression_copy = nullptr;
0a23a07d
JR
843end:
844 return status;
845}
846
28ab034a
JG
847enum lttng_event_rule_status
848lttng_event_rule_user_tracepoint_get_filter(const struct lttng_event_rule *rule,
849 const char **expression)
0a23a07d
JR
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
28ab034a 859 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
860 if (!tracepoint->filter_expression) {
861 status = LTTNG_EVENT_RULE_STATUS_UNSET;
862 goto end;
863 }
864
865 *expression = tracepoint->filter_expression;
866end:
867 return status;
868}
869
870static 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:
28ab034a 881 status = lttng_log_level_rule_at_least_as_severe_as_get_level(rule, &level);
0a23a07d
JR
882 break;
883 default:
884 abort();
885 }
886
a0377dfe 887 LTTNG_ASSERT(status == LTTNG_LOG_LEVEL_RULE_STATUS_OK);
0a23a07d
JR
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
900end:
901 return valid;
902}
903
904enum lttng_event_rule_status lttng_event_rule_user_tracepoint_set_log_level_rule(
28ab034a 905 struct lttng_event_rule *rule, const struct lttng_log_level_rule *log_level_rule)
0a23a07d
JR
906{
907 struct lttng_event_rule_user_tracepoint *tracepoint;
908 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
cd9adb8b 909 struct lttng_log_level_rule *copy = nullptr;
0a23a07d
JR
910
911 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule)) {
912 status = LTTNG_EVENT_RULE_STATUS_INVALID;
913 goto end;
914 }
915
28ab034a 916 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
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);
cd9adb8b 924 if (copy == nullptr) {
0a23a07d
JR
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
935end:
936 return status;
937}
938
939enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_log_level_rule(
28ab034a 940 const struct lttng_event_rule *rule, const struct lttng_log_level_rule **log_level_rule)
0a23a07d
JR
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
28ab034a 950 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
cd9adb8b 951 if (tracepoint->log_level_rule == nullptr) {
0a23a07d
JR
952 status = LTTNG_EVENT_RULE_STATUS_UNSET;
953 goto end;
954 }
955
956 *log_level_rule = tracepoint->log_level_rule;
957end:
958 return status;
959}
960
28ab034a
JG
961enum lttng_event_rule_status
962lttng_event_rule_user_tracepoint_add_name_pattern_exclusion(struct lttng_event_rule *rule,
963 const char *exclusion)
0a23a07d
JR
964{
965 int ret;
cd9adb8b 966 char *exclusion_copy = nullptr;
0a23a07d
JR
967 struct lttng_event_rule_user_tracepoint *tracepoint;
968 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
969
28ab034a 970 if (!rule || !IS_USER_TRACEPOINT_EVENT_RULE(rule) || !exclusion) {
0a23a07d
JR
971 status = LTTNG_EVENT_RULE_STATUS_INVALID;
972 goto end;
973 }
974
28ab034a 975 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
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
28ab034a 988 ret = lttng_dynamic_pointer_array_add_pointer(&tracepoint->exclusions, exclusion_copy);
0a23a07d
JR
989 if (ret < 0) {
990 status = LTTNG_EVENT_RULE_STATUS_ERROR;
991 goto end;
992 }
993
cd9adb8b 994 exclusion_copy = nullptr;
0a23a07d
JR
995end:
996 free(exclusion_copy);
997 return status;
998}
999
1000enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(
28ab034a 1001 const struct lttng_event_rule *rule, unsigned int *count)
0a23a07d
JR
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
28ab034a 1011 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d
JR
1012 *count = lttng_dynamic_pointer_array_get_count(&tracepoint->exclusions);
1013end:
1014 return status;
1015}
1016
1017enum lttng_event_rule_status lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_at_index(
28ab034a 1018 const struct lttng_event_rule *rule, unsigned int index, const char **exclusion)
0a23a07d
JR
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
28ab034a 1029 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_user_tracepoint::parent);
0a23a07d 1030 if (lttng_event_rule_user_tracepoint_get_name_pattern_exclusion_count(rule, &count) !=
28ab034a 1031 LTTNG_EVENT_RULE_STATUS_OK) {
0a23a07d
JR
1032 goto end;
1033 }
1034
1035 if (index >= count) {
1036 goto end;
1037 }
1038
28ab034a
JG
1039 *exclusion = (const char *) lttng_dynamic_pointer_array_get_pointer(&tracepoint->exclusions,
1040 index);
0a23a07d
JR
1041end:
1042 return status;
1043}
This page took 0.086191 seconds and 4 git commands to generate.