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