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