clang-tidy: add Chrome-inspired checks
[lttng-tools.git] / src / common / event-rule / kernel-tracepoint.cpp
CommitLineData
af0818ef
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/kernel-tracepoint-internal.hpp>
af0818ef
JR
22#include <lttng/event.h>
23
24#define IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) \
25 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT)
26
27static void lttng_event_rule_kernel_tracepoint_destroy(struct lttng_event_rule *rule)
28{
29 struct lttng_event_rule_kernel_tracepoint *tracepoint;
30
cd9adb8b 31 if (rule == nullptr) {
af0818ef
JR
32 return;
33 }
34
28ab034a 35 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
36
37 free(tracepoint->pattern);
38 free(tracepoint->filter_expression);
39 free(tracepoint->internal_filter.filter);
40 free(tracepoint->internal_filter.bytecode);
41 free(tracepoint);
42}
43
28ab034a 44static bool lttng_event_rule_kernel_tracepoint_validate(const struct lttng_event_rule *rule)
af0818ef
JR
45{
46 bool valid = false;
47 struct lttng_event_rule_kernel_tracepoint *tracepoint;
48
49 if (!rule) {
50 goto end;
51 }
52
28ab034a 53 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
54
55 /* Required field. */
56 if (!tracepoint->pattern) {
57 ERR("Invalid kernel tracepoint event rule: a pattern must be set.");
58 goto end;
59 }
60
61 valid = true;
62end:
63 return valid;
64}
65
28ab034a
JG
66static int lttng_event_rule_kernel_tracepoint_serialize(const struct lttng_event_rule *rule,
67 struct lttng_payload *payload)
af0818ef
JR
68{
69 int ret;
70 size_t pattern_len, filter_expression_len;
71 struct lttng_event_rule_kernel_tracepoint *tracepoint;
72 struct lttng_event_rule_kernel_tracepoint_comm tracepoint_comm;
73
74 if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule)) {
75 ret = -1;
76 goto end;
77 }
78
79 DBG("Serializing kernel tracepoint event rule.");
28ab034a 80 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
81
82 pattern_len = strlen(tracepoint->pattern) + 1;
83
cd9adb8b 84 if (tracepoint->filter_expression != nullptr) {
28ab034a 85 filter_expression_len = strlen(tracepoint->filter_expression) + 1;
af0818ef
JR
86 } else {
87 filter_expression_len = 0;
88 }
89
90 tracepoint_comm.pattern_len = pattern_len;
91 tracepoint_comm.filter_expression_len = filter_expression_len;
92
28ab034a
JG
93 ret = lttng_dynamic_buffer_append(
94 &payload->buffer, &tracepoint_comm, sizeof(tracepoint_comm));
af0818ef
JR
95 if (ret) {
96 goto end;
97 }
98
28ab034a 99 ret = lttng_dynamic_buffer_append(&payload->buffer, tracepoint->pattern, pattern_len);
af0818ef
JR
100 if (ret) {
101 goto end;
102 }
103
28ab034a
JG
104 ret = lttng_dynamic_buffer_append(
105 &payload->buffer, tracepoint->filter_expression, filter_expression_len);
af0818ef
JR
106 if (ret) {
107 goto end;
108 }
109
110end:
111 return ret;
112}
113
28ab034a
JG
114static bool lttng_event_rule_kernel_tracepoint_is_equal(const struct lttng_event_rule *_a,
115 const struct lttng_event_rule *_b)
af0818ef
JR
116{
117 bool is_equal = false;
118 struct lttng_event_rule_kernel_tracepoint *a, *b;
119
0114db0e
JG
120 a = lttng::utils::container_of(_a, &lttng_event_rule_kernel_tracepoint::parent);
121 b = lttng::utils::container_of(_b, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
122
123 if (!!a->filter_expression != !!b->filter_expression) {
124 goto end;
125 }
126
127 /* Long check. */
a0377dfe
FD
128 LTTNG_ASSERT(a->pattern);
129 LTTNG_ASSERT(b->pattern);
af0818ef
JR
130 if (strcmp(a->pattern, b->pattern)) {
131 goto end;
132 }
133
134 if (a->filter_expression && b->filter_expression) {
135 if (strcmp(a->filter_expression, b->filter_expression)) {
136 goto end;
137 }
138 } else if (!!a->filter_expression != !!b->filter_expression) {
139 /* One is set; not the other. */
140 goto end;
141 }
142
143 is_equal = true;
144end:
145 return is_equal;
146}
147
148static enum lttng_error_code
28ab034a
JG
149lttng_event_rule_kernel_tracepoint_generate_filter_bytecode(struct lttng_event_rule *rule,
150 const struct lttng_credentials *creds)
af0818ef
JR
151{
152 int ret;
153 enum lttng_error_code ret_code;
154 struct lttng_event_rule_kernel_tracepoint *tracepoint;
155 enum lttng_event_rule_status status;
156 const char *filter;
cd9adb8b 157 struct lttng_bytecode *bytecode = nullptr;
af0818ef 158
a0377dfe 159 LTTNG_ASSERT(rule);
af0818ef 160
28ab034a 161 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
162
163 status = lttng_event_rule_kernel_tracepoint_get_filter(rule, &filter);
164 if (status == LTTNG_EVENT_RULE_STATUS_UNSET) {
cd9adb8b 165 filter = nullptr;
af0818ef
JR
166 } else if (status != LTTNG_EVENT_RULE_STATUS_OK) {
167 ret_code = LTTNG_ERR_FILTER_INVAL;
168 goto end;
169 }
170
171 if (filter && filter[0] == '\0') {
172 ret_code = LTTNG_ERR_FILTER_INVAL;
173 goto error;
174 }
175
176 if (filter) {
177 tracepoint->internal_filter.filter = strdup(filter);
cd9adb8b 178 if (tracepoint->internal_filter.filter == nullptr) {
af0818ef
JR
179 ret_code = LTTNG_ERR_NOMEM;
180 goto error;
181 }
182 } else {
cd9adb8b 183 tracepoint->internal_filter.filter = nullptr;
af0818ef
JR
184 }
185
cd9adb8b 186 if (tracepoint->internal_filter.filter == nullptr) {
af0818ef
JR
187 ret_code = LTTNG_OK;
188 goto end;
189 }
190
28ab034a 191 ret = run_as_generate_filter_bytecode(tracepoint->internal_filter.filter, creds, &bytecode);
af0818ef
JR
192 if (ret) {
193 ret_code = LTTNG_ERR_FILTER_INVAL;
194 goto end;
195 }
196
197 tracepoint->internal_filter.bytecode = bytecode;
cd9adb8b 198 bytecode = nullptr;
af0818ef
JR
199 ret_code = LTTNG_OK;
200
201error:
202end:
203 free(bytecode);
204 return ret_code;
205}
206
28ab034a
JG
207static const char *
208lttng_event_rule_kernel_tracepoint_get_internal_filter(const struct lttng_event_rule *rule)
af0818ef
JR
209{
210 struct lttng_event_rule_kernel_tracepoint *tracepoint;
211
a0377dfe 212 LTTNG_ASSERT(rule);
28ab034a 213 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
214 return tracepoint->internal_filter.filter;
215}
216
217static const struct lttng_bytecode *
28ab034a 218lttng_event_rule_kernel_tracepoint_get_internal_filter_bytecode(const struct lttng_event_rule *rule)
af0818ef
JR
219{
220 struct lttng_event_rule_kernel_tracepoint *tracepoint;
221
a0377dfe 222 LTTNG_ASSERT(rule);
28ab034a 223 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
224 return tracepoint->internal_filter.bytecode;
225}
226
227static enum lttng_event_rule_generate_exclusions_status
28ab034a
JG
228lttng_event_rule_kernel_tracepoint_generate_exclusions(const struct lttng_event_rule *rule
229 __attribute__((unused)),
230 struct lttng_event_exclusion **_exclusions)
af0818ef
JR
231{
232 /* Unsupported. */
cd9adb8b 233 *_exclusions = nullptr;
af0818ef
JR
234 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
235}
236
28ab034a 237static unsigned long lttng_event_rule_kernel_tracepoint_hash(const struct lttng_event_rule *rule)
af0818ef
JR
238{
239 unsigned long hash;
28ab034a
JG
240 struct lttng_event_rule_kernel_tracepoint *tp_rule =
241 lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef 242
28ab034a 243 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT, lttng_ht_seed);
af0818ef
JR
244 hash ^= hash_key_str(tp_rule->pattern, lttng_ht_seed);
245
246 if (tp_rule->filter_expression) {
247 hash ^= hash_key_str(tp_rule->filter_expression, lttng_ht_seed);
248 }
249
250 return hash;
251}
252
28ab034a
JG
253static enum lttng_error_code
254lttng_event_rule_kernel_tracepoint_mi_serialize(const struct lttng_event_rule *rule,
255 struct mi_writer *writer)
6a751b95
JR
256{
257 int ret;
258 enum lttng_error_code ret_code;
259 enum lttng_event_rule_status status;
cd9adb8b
JG
260 const char *filter = nullptr;
261 const char *name_pattern = nullptr;
6a751b95 262
a0377dfe
FD
263 LTTNG_ASSERT(rule);
264 LTTNG_ASSERT(writer);
265 LTTNG_ASSERT(IS_KERNEL_TRACEPOINT_EVENT_RULE(rule));
6a751b95 266
28ab034a 267 status = lttng_event_rule_kernel_tracepoint_get_name_pattern(rule, &name_pattern);
a0377dfe
FD
268 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
269 LTTNG_ASSERT(name_pattern);
6a751b95
JR
270
271 status = lttng_event_rule_kernel_tracepoint_get_filter(rule, &filter);
a0377dfe 272 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK ||
28ab034a 273 status == LTTNG_EVENT_RULE_STATUS_UNSET);
6a751b95
JR
274
275 /* Open event rule kernel tracepoint element. */
28ab034a 276 ret = mi_lttng_writer_open_element(writer, mi_lttng_element_event_rule_kernel_tracepoint);
6a751b95
JR
277 if (ret) {
278 goto mi_error;
279 }
280
281 /* Name pattern. */
28ab034a
JG
282 ret = mi_lttng_writer_write_element_string(
283 writer, mi_lttng_element_event_rule_name_pattern, name_pattern);
6a751b95
JR
284 if (ret) {
285 goto mi_error;
286 }
287
288 /* Filter. */
cd9adb8b 289 if (filter != nullptr) {
28ab034a
JG
290 ret = mi_lttng_writer_write_element_string(
291 writer, mi_lttng_element_event_rule_filter_expression, filter);
6a751b95
JR
292 if (ret) {
293 goto mi_error;
294 }
295 }
296
297 /* Close event rule kernel tracepoint element. */
298 ret = mi_lttng_writer_close_element(writer);
299 if (ret) {
300 goto mi_error;
301 }
302
303 ret_code = LTTNG_OK;
304 goto end;
305
306mi_error:
307 ret_code = LTTNG_ERR_MI_IO_FAIL;
308end:
309 return ret_code;
310}
311
af0818ef
JR
312struct lttng_event_rule *lttng_event_rule_kernel_tracepoint_create(void)
313{
cd9adb8b 314 struct lttng_event_rule *rule = nullptr;
af0818ef
JR
315 struct lttng_event_rule_kernel_tracepoint *tp_rule;
316 enum lttng_event_rule_status status;
317
64803277 318 tp_rule = zmalloc<lttng_event_rule_kernel_tracepoint>();
af0818ef
JR
319 if (!tp_rule) {
320 goto end;
321 }
322
323 rule = &tp_rule->parent;
324 lttng_event_rule_init(&tp_rule->parent, LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT);
325 tp_rule->parent.validate = lttng_event_rule_kernel_tracepoint_validate;
326 tp_rule->parent.serialize = lttng_event_rule_kernel_tracepoint_serialize;
327 tp_rule->parent.equal = lttng_event_rule_kernel_tracepoint_is_equal;
328 tp_rule->parent.destroy = lttng_event_rule_kernel_tracepoint_destroy;
329 tp_rule->parent.generate_filter_bytecode =
28ab034a
JG
330 lttng_event_rule_kernel_tracepoint_generate_filter_bytecode;
331 tp_rule->parent.get_filter = lttng_event_rule_kernel_tracepoint_get_internal_filter;
af0818ef 332 tp_rule->parent.get_filter_bytecode =
28ab034a 333 lttng_event_rule_kernel_tracepoint_get_internal_filter_bytecode;
af0818ef 334 tp_rule->parent.generate_exclusions =
28ab034a 335 lttng_event_rule_kernel_tracepoint_generate_exclusions;
af0818ef 336 tp_rule->parent.hash = lttng_event_rule_kernel_tracepoint_hash;
6a751b95 337 tp_rule->parent.mi_serialize = lttng_event_rule_kernel_tracepoint_mi_serialize;
af0818ef
JR
338
339 /* Not necessary for now. */
cd9adb8b 340 tp_rule->parent.generate_lttng_event = nullptr;
af0818ef
JR
341
342 /* Default pattern is '*'. */
343 status = lttng_event_rule_kernel_tracepoint_set_name_pattern(rule, "*");
344 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
345 lttng_event_rule_destroy(rule);
cd9adb8b 346 rule = nullptr;
af0818ef
JR
347 }
348
349end:
350 return rule;
351}
352
28ab034a
JG
353ssize_t
354lttng_event_rule_kernel_tracepoint_create_from_payload(struct lttng_payload_view *view,
355 struct lttng_event_rule **_event_rule)
af0818ef
JR
356{
357 ssize_t ret, offset = 0;
358 enum lttng_event_rule_status status;
359 const struct lttng_event_rule_kernel_tracepoint_comm *tracepoint_comm;
360 const char *pattern;
cd9adb8b 361 const char *filter_expression = nullptr;
af0818ef 362 struct lttng_buffer_view current_buffer_view;
cd9adb8b 363 struct lttng_event_rule *rule = nullptr;
af0818ef
JR
364
365 if (!_event_rule) {
366 ret = -1;
367 goto end;
368 }
369
28ab034a
JG
370 current_buffer_view =
371 lttng_buffer_view_from_view(&view->buffer, offset, sizeof(*tracepoint_comm));
af0818ef
JR
372 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
373 ERR("Failed to initialize from malformed event rule kernel tracepoint: buffer too short to contain header.");
374 ret = -1;
375 goto end;
376 }
377
378 tracepoint_comm = (typeof(tracepoint_comm)) current_buffer_view.data;
379
380 /* Skip to payload. */
381 offset += current_buffer_view.size;
382
383 /* Map the pattern. */
28ab034a
JG
384 current_buffer_view =
385 lttng_buffer_view_from_view(&view->buffer, offset, tracepoint_comm->pattern_len);
af0818ef
JR
386
387 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
388 ret = -1;
389 goto end;
390 }
391
392 pattern = current_buffer_view.data;
28ab034a
JG
393 if (!lttng_buffer_view_contains_string(
394 &current_buffer_view, pattern, tracepoint_comm->pattern_len)) {
af0818ef
JR
395 ret = -1;
396 goto end;
397 }
398
399 /* Skip after the pattern. */
400 offset += tracepoint_comm->pattern_len;
401
402 if (!tracepoint_comm->filter_expression_len) {
403 goto skip_filter_expression;
404 }
405
406 /* Map the filter_expression. */
28ab034a
JG
407 current_buffer_view = lttng_buffer_view_from_view(
408 &view->buffer, offset, tracepoint_comm->filter_expression_len);
af0818ef
JR
409 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
410 ret = -1;
411 goto end;
412 }
413
414 filter_expression = current_buffer_view.data;
415 if (!lttng_buffer_view_contains_string(&current_buffer_view,
28ab034a
JG
416 filter_expression,
417 tracepoint_comm->filter_expression_len)) {
af0818ef
JR
418 ret = -1;
419 goto end;
420 }
421
422 /* Skip after the pattern. */
423 offset += tracepoint_comm->filter_expression_len;
424
425skip_filter_expression:
426
427 rule = lttng_event_rule_kernel_tracepoint_create();
428 if (!rule) {
429 ERR("Failed to create event rule kernel tracepoint.");
430 ret = -1;
431 goto end;
432 }
433
434 status = lttng_event_rule_kernel_tracepoint_set_name_pattern(rule, pattern);
435 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
436 ERR("Failed to set event rule kernel tracepoint pattern.");
437 ret = -1;
438 goto end;
439 }
440
441 if (filter_expression) {
28ab034a 442 status = lttng_event_rule_kernel_tracepoint_set_filter(rule, filter_expression);
af0818ef
JR
443 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
444 ERR("Failed to set event rule kernel tracepoint pattern.");
445 ret = -1;
446 goto end;
447 }
448 }
449
450 *_event_rule = rule;
cd9adb8b 451 rule = nullptr;
af0818ef
JR
452 ret = offset;
453end:
454 lttng_event_rule_destroy(rule);
455 return ret;
456}
457
28ab034a
JG
458enum lttng_event_rule_status
459lttng_event_rule_kernel_tracepoint_set_name_pattern(struct lttng_event_rule *rule,
460 const char *pattern)
af0818ef 461{
cd9adb8b 462 char *pattern_copy = nullptr;
af0818ef
JR
463 struct lttng_event_rule_kernel_tracepoint *tracepoint;
464 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
465
28ab034a 466 if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !pattern || strlen(pattern) == 0) {
af0818ef
JR
467 status = LTTNG_EVENT_RULE_STATUS_INVALID;
468 goto end;
469 }
470
28ab034a 471 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
472 pattern_copy = strdup(pattern);
473 if (!pattern_copy) {
474 status = LTTNG_EVENT_RULE_STATUS_ERROR;
475 goto end;
476 }
477
478 /* Normalize the pattern. */
479 strutils_normalize_star_glob_pattern(pattern_copy);
480
481 free(tracepoint->pattern);
482
483 tracepoint->pattern = pattern_copy;
cd9adb8b 484 pattern_copy = nullptr;
af0818ef
JR
485end:
486 return status;
487}
488
28ab034a
JG
489enum lttng_event_rule_status
490lttng_event_rule_kernel_tracepoint_get_name_pattern(const struct lttng_event_rule *rule,
491 const char **pattern)
af0818ef
JR
492{
493 struct lttng_event_rule_kernel_tracepoint *tracepoint;
494 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
495
496 if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !pattern) {
497 status = LTTNG_EVENT_RULE_STATUS_INVALID;
498 goto end;
499 }
500
28ab034a 501 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
502 if (!tracepoint->pattern) {
503 status = LTTNG_EVENT_RULE_STATUS_UNSET;
504 goto end;
505 }
506
507 *pattern = tracepoint->pattern;
508end:
509 return status;
510}
511
28ab034a
JG
512enum lttng_event_rule_status
513lttng_event_rule_kernel_tracepoint_set_filter(struct lttng_event_rule *rule, const char *expression)
af0818ef 514{
cd9adb8b 515 char *expression_copy = nullptr;
af0818ef
JR
516 struct lttng_event_rule_kernel_tracepoint *tracepoint;
517 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
518
519 if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !expression ||
28ab034a 520 strlen(expression) == 0) {
af0818ef
JR
521 status = LTTNG_EVENT_RULE_STATUS_INVALID;
522 goto end;
523 }
524
28ab034a 525 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
526 expression_copy = strdup(expression);
527 if (!expression_copy) {
528 PERROR("Failed to copy filter expression");
529 status = LTTNG_EVENT_RULE_STATUS_ERROR;
530 goto end;
531 }
532
533 if (tracepoint->filter_expression) {
534 free(tracepoint->filter_expression);
535 }
536
537 tracepoint->filter_expression = expression_copy;
cd9adb8b 538 expression_copy = nullptr;
af0818ef
JR
539end:
540 return status;
541}
542
28ab034a
JG
543enum lttng_event_rule_status
544lttng_event_rule_kernel_tracepoint_get_filter(const struct lttng_event_rule *rule,
545 const char **expression)
af0818ef
JR
546{
547 struct lttng_event_rule_kernel_tracepoint *tracepoint;
548 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
549
550 if (!rule || !IS_KERNEL_TRACEPOINT_EVENT_RULE(rule) || !expression) {
551 status = LTTNG_EVENT_RULE_STATUS_INVALID;
552 goto end;
553 }
554
28ab034a 555 tracepoint = lttng::utils::container_of(rule, &lttng_event_rule_kernel_tracepoint::parent);
af0818ef
JR
556 if (!tracepoint->filter_expression) {
557 status = LTTNG_EVENT_RULE_STATUS_UNSET;
558 goto end;
559 }
560
561 *expression = tracepoint->filter_expression;
562end:
563 return status;
564}
This page took 0.063264 seconds and 4 git commands to generate.