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