sessiond: registry_session: mark functions as noexcept
[lttng-tools.git] / src / common / event-rule / kernel-kprobe.cpp
CommitLineData
077192fd
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/payload-view.hpp>
15#include <common/payload.hpp>
16#include <common/runas.hpp>
077192fd
JR
17#include <ctype.h>
18#include <lttng/constant.h>
c9e313bc 19#include <lttng/event-rule/event-rule-internal.hpp>
6a751b95 20#include <lttng/event-rule/event-rule.h>
c9e313bc
SM
21#include <lttng/event-rule/kernel-kprobe-internal.hpp>
22#include <lttng/kernel-probe-internal.hpp>
6a751b95 23#include <lttng/kernel-probe.h>
077192fd
JR
24#include <stdio.h>
25
26#define IS_KPROBE_EVENT_RULE(rule) \
85522de5 27 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE)
077192fd
JR
28
29#if (LTTNG_SYMBOL_NAME_LEN == 256)
30#define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
31#endif
32
85522de5 33static void lttng_event_rule_kernel_kprobe_destroy(struct lttng_event_rule *rule)
077192fd 34{
85522de5 35 struct lttng_event_rule_kernel_kprobe *kprobe;
077192fd 36
85522de5 37 kprobe = container_of(rule, struct lttng_event_rule_kernel_kprobe, parent);
077192fd
JR
38
39 lttng_kernel_probe_location_destroy(kprobe->location);
40 free(kprobe->name);
41 free(kprobe);
42}
43
85522de5 44static bool lttng_event_rule_kernel_kprobe_validate(
077192fd
JR
45 const struct lttng_event_rule *rule)
46{
47 bool valid = false;
85522de5 48 struct lttng_event_rule_kernel_kprobe *kprobe;
077192fd
JR
49
50 if (!rule) {
51 goto end;
52 }
53
85522de5 54 kprobe = container_of(rule, struct lttng_event_rule_kernel_kprobe, parent);
077192fd
JR
55
56 /* Required field. */
57 if (!kprobe->name) {
58 ERR("Invalid name event rule: a name must be set.");
59 goto end;
60 }
61
62 /* Required field. */
63 if(!kprobe->location) {
64 ERR("Invalid name event rule: a location must be set.");
65 goto end;
66 }
67
68 valid = true;
69end:
70 return valid;
71}
72
85522de5 73static int lttng_event_rule_kernel_kprobe_serialize(
077192fd
JR
74 const struct lttng_event_rule *rule,
75 struct lttng_payload *payload)
76{
77 int ret;
78 size_t name_len, header_offset, size_before_location;
85522de5
JR
79 struct lttng_event_rule_kernel_kprobe *kprobe;
80 struct lttng_event_rule_kernel_kprobe_comm kprobe_comm;
81 struct lttng_event_rule_kernel_kprobe_comm *header;
077192fd
JR
82
83 if (!rule || !IS_KPROBE_EVENT_RULE(rule)) {
84 ret = -1;
85 goto end;
86 }
87
88 header_offset = payload->buffer.size;
89
90 DBG("Serializing kprobe event rule.");
85522de5 91 kprobe = container_of(rule, struct lttng_event_rule_kernel_kprobe, parent);
077192fd
JR
92
93 name_len = strlen(kprobe->name) + 1;
94 kprobe_comm.name_len = name_len;
95
96 ret = lttng_dynamic_buffer_append(
97 &payload->buffer, &kprobe_comm, sizeof(kprobe_comm));
98 if (ret) {
99 goto end;
100 }
101
102 ret = lttng_dynamic_buffer_append(&payload->buffer, kprobe->name, name_len);
103 if (ret) {
104 goto end;
105 }
106
107 size_before_location = payload->buffer.size;
108
109 ret = lttng_kernel_probe_location_serialize(kprobe->location, payload);
110 if (ret < 0) {
111 goto end;
112 }
113
114 /* Update the header regarding the probe size. */
85522de5 115 header = (struct lttng_event_rule_kernel_kprobe_comm*) (
077192fd
JR
116 (char *) payload->buffer.data + header_offset);
117 header->location_len = payload->buffer.size - size_before_location;
118
119 ret = 0;
120
121end:
122 return ret;
123}
124
85522de5 125static bool lttng_event_rule_kernel_kprobe_is_equal(const struct lttng_event_rule *_a,
077192fd
JR
126 const struct lttng_event_rule *_b)
127{
128 bool is_equal = false;
85522de5 129 struct lttng_event_rule_kernel_kprobe *a, *b;
077192fd 130
85522de5
JR
131 a = container_of(_a, struct lttng_event_rule_kernel_kprobe, parent);
132 b = container_of(_b, struct lttng_event_rule_kernel_kprobe, parent);
077192fd
JR
133
134 /* Quick checks */
135 if (!!a->name != !!b->name) {
136 goto end;
137 }
138
139 /* Long check */
a0377dfe
FD
140 LTTNG_ASSERT(a->name);
141 LTTNG_ASSERT(b->name);
077192fd
JR
142 if (strcmp(a->name, b->name)) {
143 goto end;
144 }
145
146 is_equal = lttng_kernel_probe_location_is_equal(
147 a->location, b->location);
148end:
149 return is_equal;
150}
151
85522de5 152static enum lttng_error_code lttng_event_rule_kernel_kprobe_generate_filter_bytecode(
f46376a1
MJ
153 struct lttng_event_rule *rule __attribute__((unused)),
154 const struct lttng_credentials *creds __attribute__((unused)))
077192fd
JR
155{
156 /* Nothing to do. */
157 return LTTNG_OK;
158}
159
85522de5 160static const char *lttng_event_rule_kernel_kprobe_get_filter(
f46376a1 161 const struct lttng_event_rule *rule __attribute__((unused)))
077192fd
JR
162{
163 /* Not supported. */
164 return NULL;
165}
166
2b00d462 167static const struct lttng_bytecode *
f46376a1
MJ
168lttng_event_rule_kernel_kprobe_get_filter_bytecode(
169 const struct lttng_event_rule *rule __attribute__((unused)))
077192fd
JR
170{
171 /* Not supported. */
172 return NULL;
173}
174
993578ff 175static enum lttng_event_rule_generate_exclusions_status
f46376a1
MJ
176lttng_event_rule_kernel_kprobe_generate_exclusions(
177 const struct lttng_event_rule *rule __attribute__((unused)),
993578ff 178 struct lttng_event_exclusion **exclusions)
077192fd
JR
179{
180 /* Not supported. */
993578ff
JR
181 *exclusions = NULL;
182 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE;
077192fd
JR
183}
184
959e3c66 185static unsigned long
85522de5 186lttng_event_rule_kernel_kprobe_hash(
959e3c66
JR
187 const struct lttng_event_rule *rule)
188{
189 unsigned long hash;
85522de5 190 struct lttng_event_rule_kernel_kprobe *krule =
959e3c66
JR
191 container_of(rule, typeof(*krule), parent);
192
85522de5 193 hash = hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE,
959e3c66
JR
194 lttng_ht_seed);
195 hash ^= hash_key_str(krule->name, lttng_ht_seed);
196 hash ^= lttng_kernel_probe_location_hash(krule->location);
197
198 return hash;
199}
200
602a6d40
JR
201static
202int kernel_probe_set_location(
85522de5 203 struct lttng_event_rule_kernel_kprobe *kprobe,
602a6d40
JR
204 const struct lttng_kernel_probe_location *location)
205{
206 int ret;
207 struct lttng_kernel_probe_location *location_copy = NULL;
208
209 if (!kprobe || !location || kprobe->location) {
210 ret = -1;
211 goto end;
212 }
213
214 location_copy = lttng_kernel_probe_location_copy(location);
215 if (!location_copy) {
216 ret = -1;
217 goto end;
218 }
219
220 kprobe->location = location_copy;
221 location_copy = NULL;
222 ret = 0;
223end:
224 lttng_kernel_probe_location_destroy(location_copy);
225 return ret;
226}
227
6a751b95
JR
228static
229enum lttng_error_code lttng_event_rule_kernel_kprobe_mi_serialize(
230 const struct lttng_event_rule *rule, struct mi_writer *writer)
231{
232 int ret;
233 enum lttng_error_code ret_code;
234 enum lttng_event_rule_status status;
235 const char *event_name = NULL;
236 const struct lttng_kernel_probe_location *location = NULL;
237
a0377dfe
FD
238 LTTNG_ASSERT(rule);
239 LTTNG_ASSERT(writer);
240 LTTNG_ASSERT(IS_KPROBE_EVENT_RULE(rule));
6a751b95
JR
241
242 status = lttng_event_rule_kernel_kprobe_get_event_name(
243 rule, &event_name);
a0377dfe
FD
244 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
245 LTTNG_ASSERT(event_name);
6a751b95
JR
246
247 status = lttng_event_rule_kernel_kprobe_get_location(rule, &location);
a0377dfe
FD
248 LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK);
249 LTTNG_ASSERT(location);
6a751b95
JR
250
251 /* Open event rule kernel kprobe element. */
252 ret = mi_lttng_writer_open_element(
253 writer, mi_lttng_element_event_rule_kernel_kprobe);
254 if (ret) {
255 goto mi_error;
256 }
257
258 /* Name. */
259 ret = mi_lttng_writer_write_element_string(writer,
260 mi_lttng_element_event_rule_event_name, event_name);
261 if (ret) {
262 goto mi_error;
263 }
264
265 /* Probe location. */
266 ret_code = lttng_kernel_probe_location_mi_serialize(location, writer);
267 if (ret_code != LTTNG_OK) {
268 goto end;
269 }
270
271 /* Close event rule kernel kprobe element. */
272 ret = mi_lttng_writer_close_element(writer);
273 if (ret) {
274 goto mi_error;
275 }
276
277 ret_code = LTTNG_OK;
278 goto end;
279
280mi_error:
281 ret_code = LTTNG_ERR_MI_IO_FAIL;
282end:
283 return ret_code;
284}
285
85522de5 286struct lttng_event_rule *lttng_event_rule_kernel_kprobe_create(
602a6d40 287 const struct lttng_kernel_probe_location *location)
077192fd
JR
288{
289 struct lttng_event_rule *rule = NULL;
85522de5 290 struct lttng_event_rule_kernel_kprobe *krule;
077192fd 291
64803277 292 krule = zmalloc<lttng_event_rule_kernel_kprobe>();
077192fd
JR
293 if (!krule) {
294 goto end;
295 }
296
297 rule = &krule->parent;
85522de5
JR
298 lttng_event_rule_init(&krule->parent, LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE);
299 krule->parent.validate = lttng_event_rule_kernel_kprobe_validate;
300 krule->parent.serialize = lttng_event_rule_kernel_kprobe_serialize;
301 krule->parent.equal = lttng_event_rule_kernel_kprobe_is_equal;
302 krule->parent.destroy = lttng_event_rule_kernel_kprobe_destroy;
077192fd 303 krule->parent.generate_filter_bytecode =
85522de5
JR
304 lttng_event_rule_kernel_kprobe_generate_filter_bytecode;
305 krule->parent.get_filter = lttng_event_rule_kernel_kprobe_get_filter;
077192fd 306 krule->parent.get_filter_bytecode =
85522de5 307 lttng_event_rule_kernel_kprobe_get_filter_bytecode;
077192fd 308 krule->parent.generate_exclusions =
85522de5
JR
309 lttng_event_rule_kernel_kprobe_generate_exclusions;
310 krule->parent.hash = lttng_event_rule_kernel_kprobe_hash;
6a751b95 311 krule->parent.mi_serialize = lttng_event_rule_kernel_kprobe_mi_serialize;
602a6d40
JR
312
313 if (kernel_probe_set_location(krule, location)) {
314 lttng_event_rule_destroy(rule);
315 rule = NULL;
316 }
317
077192fd
JR
318end:
319 return rule;
320}
321
85522de5 322ssize_t lttng_event_rule_kernel_kprobe_create_from_payload(
077192fd
JR
323 struct lttng_payload_view *view,
324 struct lttng_event_rule **_event_rule)
325{
326 ssize_t ret, offset = 0;
327 enum lttng_event_rule_status status;
85522de5 328 const struct lttng_event_rule_kernel_kprobe_comm *kprobe_comm;
077192fd
JR
329 const char *name;
330 struct lttng_buffer_view current_buffer_view;
331 struct lttng_event_rule *rule = NULL;
602a6d40 332 struct lttng_kernel_probe_location *location = NULL;
077192fd
JR
333
334 if (!_event_rule) {
335 ret = -1;
336 goto end;
337 }
338
3e6e0df2
JG
339 current_buffer_view = lttng_buffer_view_from_view(
340 &view->buffer, offset, sizeof(*kprobe_comm));
341 if (!lttng_buffer_view_is_valid(&current_buffer_view)) {
077192fd
JR
342 ERR("Failed to initialize from malformed event rule kprobe: buffer too short to contain header.");
343 ret = -1;
344 goto end;
345 }
346
077192fd 347 kprobe_comm = (typeof(kprobe_comm)) current_buffer_view.data;
077192fd 348
077192fd
JR
349 /* Skip to payload */
350 offset += current_buffer_view.size;
351
352 {
353 /* Map the name. */
354 struct lttng_payload_view current_payload_view =
355 lttng_payload_view_from_view(view, offset,
356 kprobe_comm->name_len);
357
3e6e0df2 358 if (!lttng_payload_view_is_valid(&current_payload_view)) {
077192fd
JR
359 ret = -1;
360 goto end;
361 }
362
3e6e0df2 363 name = current_payload_view.buffer.data;
077192fd
JR
364 if (!lttng_buffer_view_contains_string(
365 &current_payload_view.buffer, name,
366 kprobe_comm->name_len)) {
367 ret = -1;
368 goto end;
369 }
370 }
371
372 /* Skip after the name. */
373 offset += kprobe_comm->name_len;
374
375 /* Map the kernel probe location. */
376 {
377 struct lttng_payload_view current_payload_view =
378 lttng_payload_view_from_view(view, offset,
379 kprobe_comm->location_len);
380
3e6e0df2
JG
381 if (!lttng_payload_view_is_valid(&current_payload_view)) {
382 ret = -1;
383 goto end;
384 }
385
077192fd
JR
386 ret = lttng_kernel_probe_location_create_from_payload(
387 &current_payload_view, &location);
388 if (ret < 0) {
389 ret = -1;
390 goto end;
391 }
392 }
393
394 if (ret != kprobe_comm->location_len) {
395 ret = -1;
396 goto end;
397 }
398
077192fd
JR
399 /* Skip after the location */
400 offset += kprobe_comm->location_len;
401
85522de5 402 rule = lttng_event_rule_kernel_kprobe_create(location);
602a6d40
JR
403 if (!rule) {
404 ERR("Failed to create event rule kprobe.");
405 ret = -1;
406 goto end;
407 }
408
85522de5 409 status = lttng_event_rule_kernel_kprobe_set_event_name(rule, name);
077192fd
JR
410 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
411 ERR("Failed to set event rule kprobe name.");
412 ret = -1;
413 goto end;
414 }
415
416 *_event_rule = rule;
417 rule = NULL;
418 ret = offset;
419end:
602a6d40 420 lttng_kernel_probe_location_destroy(location);
077192fd
JR
421 lttng_event_rule_destroy(rule);
422 return ret;
423}
424
85522de5 425enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_get_location(
077192fd
JR
426 const struct lttng_event_rule *rule,
427 const struct lttng_kernel_probe_location **location)
428{
429 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
85522de5 430 struct lttng_event_rule_kernel_kprobe *kprobe;
077192fd
JR
431
432 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !location) {
433 status = LTTNG_EVENT_RULE_STATUS_INVALID;
434 goto end;
435 }
436
85522de5 437 kprobe = container_of(rule, struct lttng_event_rule_kernel_kprobe, parent);
077192fd
JR
438 *location = kprobe->location;
439
440 if (!*location) {
441 status = LTTNG_EVENT_RULE_STATUS_UNSET;
442 goto end;
443 }
444
445end:
446 return status;
447}
448
85522de5 449enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_set_event_name(
077192fd
JR
450 struct lttng_event_rule *rule, const char *name)
451{
452 char *name_copy = NULL;
85522de5 453 struct lttng_event_rule_kernel_kprobe *kprobe;
077192fd
JR
454 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
455
456 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name ||
457 strlen(name) == 0) {
458 status = LTTNG_EVENT_RULE_STATUS_INVALID;
459 goto end;
460 }
461
85522de5 462 kprobe = container_of(rule, struct lttng_event_rule_kernel_kprobe, parent);
077192fd
JR
463 name_copy = strdup(name);
464 if (!name_copy) {
465 status = LTTNG_EVENT_RULE_STATUS_ERROR;
466 goto end;
467 }
468
469 free(kprobe->name);
470
471 kprobe->name = name_copy;
472 name_copy = NULL;
473end:
474 return status;
475}
476
85522de5 477enum lttng_event_rule_status lttng_event_rule_kernel_kprobe_get_event_name(
077192fd
JR
478 const struct lttng_event_rule *rule, const char **name)
479{
85522de5 480 struct lttng_event_rule_kernel_kprobe *kprobe;
077192fd
JR
481 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
482
483 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name) {
484 status = LTTNG_EVENT_RULE_STATUS_INVALID;
485 goto end;
486 }
487
85522de5 488 kprobe = container_of(rule, struct lttng_event_rule_kernel_kprobe, parent);
077192fd
JR
489 if (!kprobe->name) {
490 status = LTTNG_EVENT_RULE_STATUS_UNSET;
491 goto end;
492 }
493
494 *name = kprobe->name;
495end:
496 return status;
497}
This page took 0.063969 seconds and 4 git commands to generate.