Fix: add_trigger.c: `goto error` with a wrong UID for `--owner-uid`
[lttng-tools.git] / src / common / kernel-probe.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2020 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8#include "lttng/lttng-error.h"
9#include <assert.h>
10#include <common/error.h>
11#include <common/macros.h>
12#include <common/payload.h>
13#include <common/payload-view.h>
14#include <common/hashtable/hashtable.h>
15#include <common/hashtable/utils.h>
16#include <fcntl.h>
17#include <lttng/constant.h>
18#include <lttng/kernel-probe.h>
19#include <lttng/kernel-probe-internal.h>
20#include <sys/stat.h>
21#include <sys/types.h>
22#include <sys/unistd.h>
23
24static
25int lttng_kernel_probe_location_address_serialize(
26 const struct lttng_kernel_probe_location *location,
27 struct lttng_payload *payload);
28
29static
30int lttng_kernel_probe_location_symbol_serialize(
31 const struct lttng_kernel_probe_location *location,
32 struct lttng_payload *payload);
33
34static
35bool lttng_kernel_probe_location_address_is_equal(
36 const struct lttng_kernel_probe_location *a,
37 const struct lttng_kernel_probe_location *b);
38
39static
40bool lttng_kernel_probe_location_symbol_is_equal(
41 const struct lttng_kernel_probe_location *a,
42 const struct lttng_kernel_probe_location *b);
43
44static
45unsigned long lttng_kernel_probe_location_address_hash(
46 const struct lttng_kernel_probe_location *location);
47
48static
49unsigned long lttng_kernel_probe_location_symbol_hash(
50 const struct lttng_kernel_probe_location *location);
51
52enum lttng_kernel_probe_location_type lttng_kernel_probe_location_get_type(
53 const struct lttng_kernel_probe_location *location)
54{
55 return location ? location->type :
56 LTTNG_KERNEL_PROBE_LOCATION_TYPE_UNKNOWN;
57}
58
59static
60void lttng_kernel_probe_location_address_destroy(
61 struct lttng_kernel_probe_location *location)
62{
63 assert(location);
64 free(location);
65}
66
67static
68void lttng_kernel_probe_location_symbol_destroy(
69 struct lttng_kernel_probe_location *location)
70{
71 struct lttng_kernel_probe_location_symbol *location_symbol = NULL;
72
73 assert(location);
74
75 location_symbol = container_of(location,
76 struct lttng_kernel_probe_location_symbol,
77 parent);
78
79 assert(location_symbol);
80
81 free(location_symbol->symbol_name);
82 free(location);
83}
84
85void lttng_kernel_probe_location_destroy(
86 struct lttng_kernel_probe_location *location)
87{
88 if (!location) {
89 return;
90 }
91
92 switch (location->type) {
93 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
94 lttng_kernel_probe_location_address_destroy(location);
95 break;
96 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
97 lttng_kernel_probe_location_symbol_destroy(location);
98 break;
99 default:
100 abort();
101 }
102}
103
104struct lttng_kernel_probe_location *
105lttng_kernel_probe_location_address_create(uint64_t address)
106{
107 struct lttng_kernel_probe_location *ret = NULL;
108 struct lttng_kernel_probe_location_address *location;
109
110 location = zmalloc(sizeof(*location));
111 if (!location) {
112 PERROR("Error allocating userspace probe location.");
113 goto end;
114 }
115
116 location->address = address;
117
118 ret = &location->parent;
119 ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS;
120 ret->equal = lttng_kernel_probe_location_address_is_equal;
121 ret->serialize = lttng_kernel_probe_location_address_serialize;
122 ret->hash = lttng_kernel_probe_location_address_hash;
123
124end:
125 return ret;
126}
127
128struct lttng_kernel_probe_location *
129lttng_kernel_probe_location_symbol_create(const char *symbol_name,
130 uint64_t offset)
131{
132 char *symbol_name_copy = NULL;
133 struct lttng_kernel_probe_location *ret = NULL;
134 struct lttng_kernel_probe_location_symbol *location;
135
136 if (!symbol_name || strlen(symbol_name) >= LTTNG_SYMBOL_NAME_LEN) {
137 goto error;
138 }
139
140 symbol_name_copy = strdup(symbol_name);
141 if (!symbol_name_copy) {
142 PERROR("Failed to copy symbol name '%s'", symbol_name);
143 goto error;
144 }
145
146 location = zmalloc(sizeof(*location));
147 if (!location) {
148 PERROR("Failed to allocate kernel symbol probe location");
149 goto error;
150 }
151
152 location->symbol_name = symbol_name_copy;
153 location->offset = offset;
154
155 ret = &location->parent;
156 ret->type = LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET;
157 ret->equal = lttng_kernel_probe_location_symbol_is_equal;
158 ret->serialize = lttng_kernel_probe_location_symbol_serialize;
159 ret->hash = lttng_kernel_probe_location_symbol_hash;
160 goto end;
161
162error:
163 free(symbol_name_copy);
164end:
165 return ret;
166}
167
168enum lttng_kernel_probe_location_status
169lttng_kernel_probe_location_address_get_address(
170 const struct lttng_kernel_probe_location *location,
171 uint64_t *offset)
172{
173 enum lttng_kernel_probe_location_status ret =
174 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK;
175 struct lttng_kernel_probe_location_address *address_location;
176
177 assert(offset);
178
179 if (!location || lttng_kernel_probe_location_get_type(location) !=
180 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS) {
181 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
182 ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID;
183 goto end;
184 }
185
186 address_location = container_of(location,
187 struct lttng_kernel_probe_location_address, parent);
188 *offset = address_location->address;
189end:
190 return ret;
191}
192
193const char *lttng_kernel_probe_location_symbol_get_name(
194 const struct lttng_kernel_probe_location *location)
195{
196 const char *ret = NULL;
197 struct lttng_kernel_probe_location_symbol *symbol_location;
198
199 if (!location || lttng_kernel_probe_location_get_type(location) !=
200 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET) {
201 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
202 goto end;
203 }
204
205 symbol_location = container_of(location,
206 struct lttng_kernel_probe_location_symbol, parent);
207 ret = symbol_location->symbol_name;
208end:
209 return ret;
210}
211
212enum lttng_kernel_probe_location_status
213lttng_kernel_probe_location_symbol_get_offset(
214 const struct lttng_kernel_probe_location *location,
215 uint64_t *offset)
216{
217 enum lttng_kernel_probe_location_status ret =
218 LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK;
219 struct lttng_kernel_probe_location_symbol *symbol_location;
220
221 assert(offset);
222
223 if (!location || lttng_kernel_probe_location_get_type(location) !=
224 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET) {
225 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
226 ret = LTTNG_KERNEL_PROBE_LOCATION_STATUS_INVALID;
227 goto end;
228 }
229
230 symbol_location = container_of(location,
231 struct lttng_kernel_probe_location_symbol, parent);
232 *offset = symbol_location->offset;
233end:
234 return ret;
235}
236
237static
238int lttng_kernel_probe_location_symbol_serialize(
239 const struct lttng_kernel_probe_location *location,
240 struct lttng_payload *payload)
241{
242 int ret;
243 size_t symbol_name_len;
244 size_t original_payload_size;
245 struct lttng_kernel_probe_location_symbol *location_symbol;
246 struct lttng_kernel_probe_location_symbol_comm location_symbol_comm;
247
248 if (!location || !payload) {
249 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
250 ret = -LTTNG_ERR_INVALID;
251 goto end;
252 }
253
254 assert(lttng_kernel_probe_location_get_type(location) ==
255 LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
256
257 original_payload_size = payload->buffer.size;
258 location_symbol = container_of(location,
259 struct lttng_kernel_probe_location_symbol, parent);
260
261 if (!location_symbol->symbol_name) {
262 ret = -LTTNG_ERR_INVALID;
263 goto end;
264 }
265
266 symbol_name_len = strlen(location_symbol->symbol_name);
267 if (symbol_name_len == 0) {
268 ret = -LTTNG_ERR_INVALID;
269 goto end;
270 }
271
272 location_symbol_comm.symbol_len = symbol_name_len + 1;
273 location_symbol_comm.offset = location_symbol->offset;
274
275 ret = lttng_dynamic_buffer_append(&payload->buffer,
276 &location_symbol_comm, sizeof(location_symbol_comm));
277 if (ret) {
278 ret = -LTTNG_ERR_INVALID;
279 goto end;
280 }
281
282 ret = lttng_dynamic_buffer_append(&payload->buffer,
283 location_symbol->symbol_name,
284 location_symbol_comm.symbol_len);
285 if (ret) {
286 ret = -LTTNG_ERR_INVALID;
287 goto end;
288 }
289
290 ret = (int) (payload->buffer.size - original_payload_size);
291end:
292 return ret;
293}
294
295static
296int lttng_kernel_probe_location_address_serialize(
297 const struct lttng_kernel_probe_location *location,
298 struct lttng_payload *payload)
299{
300 int ret;
301 size_t original_payload_size;
302 struct lttng_kernel_probe_location_address *location_address;
303 struct lttng_kernel_probe_location_address_comm location_address_comm;
304
305 assert(location);
306 assert(lttng_kernel_probe_location_get_type(location) ==
307 LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
308
309 original_payload_size = payload->buffer.size;
310 location_address = container_of(location,
311 struct lttng_kernel_probe_location_address,
312 parent);
313
314 location_address_comm.address = location_address->address;
315
316 ret = lttng_dynamic_buffer_append(&payload->buffer,
317 &location_address_comm,
318 sizeof(location_address_comm));
319 if (ret) {
320 ret = -LTTNG_ERR_INVALID;
321 goto end;
322 }
323
324 ret = (int) (payload->buffer.size - original_payload_size);
325end:
326 return ret;
327}
328
329LTTNG_HIDDEN
330int lttng_kernel_probe_location_serialize(
331 const struct lttng_kernel_probe_location *location,
332 struct lttng_payload *payload)
333{
334 int ret;
335 size_t original_payload_size;
336 struct lttng_kernel_probe_location_comm location_generic_comm = {};
337
338 if (!location || !payload) {
339 ERR("Invalid argument(s) passed to '%s'", __FUNCTION__);
340 ret = -LTTNG_ERR_INVALID;
341 goto end;
342 }
343
344 original_payload_size = payload->buffer.size;
345 location_generic_comm.type = (int8_t) location->type;
346 ret = lttng_dynamic_buffer_append(&payload->buffer,
347 &location_generic_comm,
348 sizeof(location_generic_comm));
349 if (ret) {
350 goto end;
351 }
352
353 ret = location->serialize(location, payload);
354 if (ret < 0) {
355 goto end;
356 }
357
358 ret = (int) (payload->buffer.size - original_payload_size);
359end:
360 return ret;
361}
362
363static
364int lttng_kernel_probe_location_symbol_create_from_payload(
365 struct lttng_payload_view *view,
366 struct lttng_kernel_probe_location **location)
367{
368 struct lttng_kernel_probe_location_symbol_comm *location_symbol_comm;
369 const char *symbol_name_src;
370 ssize_t ret = 0;
371 size_t expected_size;
372
373 assert(location);
374
375 if (view->buffer.size < sizeof(*location_symbol_comm)) {
376 ret = -LTTNG_ERR_INVALID;
377 goto end;
378 }
379
380 location_symbol_comm =
381 (typeof(location_symbol_comm)) view->buffer.data;
382
383 expected_size = sizeof(*location_symbol_comm) +
384 location_symbol_comm->symbol_len;
385
386 if (view->buffer.size < expected_size) {
387 ret = -LTTNG_ERR_INVALID;
388 goto end;
389 }
390
391 symbol_name_src = view->buffer.data + sizeof(*location_symbol_comm);
392
393 if (!lttng_buffer_view_contains_string(&view->buffer, symbol_name_src,
394 location_symbol_comm->symbol_len)) {
395 ret = -LTTNG_ERR_INVALID;
396 goto end;
397 }
398
399 *location = lttng_kernel_probe_location_symbol_create(
400 symbol_name_src, location_symbol_comm->offset);
401 if (!(*location)) {
402 ret = -LTTNG_ERR_INVALID;
403 goto end;
404 }
405
406 ret = (ssize_t) expected_size;
407end:
408 return ret;
409}
410
411static
412ssize_t lttng_kernel_probe_location_address_create_from_payload(
413 struct lttng_payload_view *view,
414 struct lttng_kernel_probe_location **location)
415{
416 struct lttng_kernel_probe_location_address_comm *location_address_comm;
417 ssize_t ret = 0;
418 size_t expected_size;
419
420 assert(location);
421
422 expected_size = sizeof(*location_address_comm);
423
424 if (view->buffer.size < expected_size) {
425 ret = -LTTNG_ERR_INVALID;
426 goto end;
427 }
428
429 location_address_comm =
430 (typeof(location_address_comm)) view->buffer.data;
431
432 *location = lttng_kernel_probe_location_address_create(location_address_comm->address);
433 if (!(*location)) {
434 ret = -LTTNG_ERR_INVALID;
435 goto end;
436 }
437
438 ret = (size_t) expected_size;
439end:
440 return ret;
441}
442
443LTTNG_HIDDEN
444ssize_t lttng_kernel_probe_location_create_from_payload(
445 struct lttng_payload_view *view,
446 struct lttng_kernel_probe_location **location)
447{
448 enum lttng_kernel_probe_location_type type;
449 ssize_t consumed = 0;
450 ssize_t ret;
451 const struct lttng_kernel_probe_location_comm *probe_location_comm;
452 const struct lttng_payload_view probe_location_comm_view =
453 lttng_payload_view_from_view(
454 view, 0, sizeof(*probe_location_comm));
455
456 assert(view);
457 assert(location);
458
459 if (!lttng_payload_view_is_valid(&probe_location_comm_view)) {
460 ret = -LTTNG_ERR_INVALID;
461 goto end;
462 }
463
464 probe_location_comm = (typeof(probe_location_comm)) probe_location_comm_view.buffer.data;
465 type = (enum lttng_kernel_probe_location_type) probe_location_comm->type;
466 consumed += sizeof(*probe_location_comm);
467
468 switch (type) {
469 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
470 {
471 struct lttng_payload_view location_view =
472 lttng_payload_view_from_view(
473 view, consumed, -1);
474
475 ret = lttng_kernel_probe_location_symbol_create_from_payload(
476 &location_view, location);
477 break;
478 }
479 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
480 {
481 struct lttng_payload_view location_view =
482 lttng_payload_view_from_view(view, consumed, -1);
483
484 ret = lttng_kernel_probe_location_address_create_from_payload(
485 &location_view, location);
486 break;
487 }
488 default:
489 ret = -LTTNG_ERR_INVALID;
490 break;
491 }
492
493 if (ret < 0) {
494 ret = -LTTNG_ERR_INVALID;
495 goto end;
496 }
497
498 ret += consumed;
499
500end:
501 return ret;
502}
503
504static
505unsigned long lttng_kernel_probe_location_address_hash(
506 const struct lttng_kernel_probe_location *location)
507{
508 unsigned long hash = hash_key_ulong(
509 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS,
510 lttng_ht_seed);
511 struct lttng_kernel_probe_location_address *address_location =
512 container_of(location, typeof(*address_location),
513 parent);
514
515 hash ^= hash_key_u64(&address_location->address, lttng_ht_seed);
516
517 return hash;
518}
519
520static
521bool lttng_kernel_probe_location_address_is_equal(
522 const struct lttng_kernel_probe_location *_a,
523 const struct lttng_kernel_probe_location *_b)
524{
525 bool is_equal = false;
526 struct lttng_kernel_probe_location_address *a, *b;
527
528 a = container_of(_a, struct lttng_kernel_probe_location_address,
529 parent);
530 b = container_of(_b, struct lttng_kernel_probe_location_address,
531 parent);
532
533 if (a->address != b->address) {
534 goto end;
535 }
536
537 is_equal = true;
538
539end:
540 return is_equal;
541}
542
543static
544unsigned long lttng_kernel_probe_location_symbol_hash(
545 const struct lttng_kernel_probe_location *location)
546{
547 unsigned long hash = hash_key_ulong(
548 (void *) LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET,
549 lttng_ht_seed);
550 struct lttng_kernel_probe_location_symbol *symbol_location =
551 container_of(location, typeof(*symbol_location),
552 parent);
553
554 hash ^= hash_key_str(symbol_location->symbol_name, lttng_ht_seed);
555 hash ^= hash_key_u64(&symbol_location->offset, lttng_ht_seed);
556
557 return hash;
558}
559
560static
561bool lttng_kernel_probe_location_symbol_is_equal(
562 const struct lttng_kernel_probe_location *_a,
563 const struct lttng_kernel_probe_location *_b)
564{
565 bool is_equal = false;
566 struct lttng_kernel_probe_location_symbol *a, *b;
567
568 a = container_of(_a, struct lttng_kernel_probe_location_symbol,
569 parent);
570 b = container_of(_b, struct lttng_kernel_probe_location_symbol,
571 parent);
572
573 assert(a->symbol_name);
574 assert(b->symbol_name);
575 if (strcmp(a->symbol_name, b->symbol_name)) {
576 goto end;
577 }
578
579 if (a->offset != b->offset) {
580 goto end;
581 }
582
583 is_equal = true;
584
585end:
586 return is_equal;
587}
588
589LTTNG_HIDDEN
590bool lttng_kernel_probe_location_is_equal(
591 const struct lttng_kernel_probe_location *a,
592 const struct lttng_kernel_probe_location *b)
593{
594 bool is_equal = false;
595
596 if (!a || !b) {
597 goto end;
598 }
599
600 if (a == b) {
601 is_equal = true;
602 goto end;
603 }
604
605 if (a->type != b->type) {
606 goto end;
607 }
608
609 is_equal = a->equal ? a->equal(a, b) : true;
610end:
611 return is_equal;
612}
613
614static struct lttng_kernel_probe_location *
615lttng_kernel_probe_location_symbol_copy(
616 const struct lttng_kernel_probe_location *location)
617{
618 struct lttng_kernel_probe_location *new_location = NULL;
619 struct lttng_kernel_probe_location_symbol *symbol_location;
620 enum lttng_kernel_probe_location_status status;
621 const char *symbol_name = NULL;
622 uint64_t offset;
623
624 assert(location);
625 assert(location->type == LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET);
626 symbol_location = container_of(
627 location, typeof(*symbol_location), parent);
628
629 /* Get probe location offset */
630 status = lttng_kernel_probe_location_symbol_get_offset(location, &offset);
631 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
632 ERR("Get kernel probe location offset failed.");
633 goto error;
634 }
635
636 symbol_name = lttng_kernel_probe_location_symbol_get_name(location);
637 if (!symbol_name) {
638 ERR("Kernel probe symbol name is NULL.");
639 goto error;
640 }
641
642 /* Create the probe_location */
643 new_location = lttng_kernel_probe_location_symbol_create(
644 symbol_name, offset);
645
646 goto end;
647
648error:
649 new_location = NULL;
650end:
651 return new_location;
652}
653static struct lttng_kernel_probe_location *
654lttng_kernel_probe_location_address_copy(
655 const struct lttng_kernel_probe_location *location)
656{
657 struct lttng_kernel_probe_location *new_location = NULL;
658 struct lttng_kernel_probe_location_address *address_location;
659 enum lttng_kernel_probe_location_status status;
660 uint64_t address;
661
662 assert(location);
663 assert(location->type == LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS);
664 address_location = container_of(
665 location, typeof(*address_location), parent);
666
667
668 /* Get probe location fields */
669 status = lttng_kernel_probe_location_address_get_address(location, &address);
670 if (status != LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK) {
671 ERR("Get kernel probe address failed.");
672 goto error;
673 }
674
675 /* Create the probe_location */
676 new_location = lttng_kernel_probe_location_address_create(address);
677
678 goto end;
679
680error:
681 new_location = NULL;
682end:
683 return new_location;
684}
685
686LTTNG_HIDDEN
687struct lttng_kernel_probe_location *lttng_kernel_probe_location_copy(
688 const struct lttng_kernel_probe_location *location)
689{
690 struct lttng_kernel_probe_location *new_location = NULL;
691 enum lttng_kernel_probe_location_type type;
692
693 if (!location) {
694 goto err;
695 }
696
697 type = lttng_kernel_probe_location_get_type(location);
698 switch (type) {
699 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS:
700 new_location =
701 lttng_kernel_probe_location_address_copy(location);
702 if (!new_location) {
703 goto err;
704 }
705 break;
706 case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET:
707 new_location =
708 lttng_kernel_probe_location_symbol_copy(location);
709 if (!new_location) {
710 goto err;
711 }
712 break;
713 default:
714 new_location = NULL;
715 goto err;
716 }
717err:
718 return new_location;
719}
720
721LTTNG_HIDDEN
722unsigned long lttng_kernel_probe_location_hash(
723 const struct lttng_kernel_probe_location *location)
724{
725 return location->hash(location);
726}
This page took 0.02974 seconds and 5 git commands to generate.