SoW-2019-0007-2: Dynamic Snapshot: Triggers send partial event payload with notifications
[lttng-tools.git] / src / common / event-rule / kprobe.c
CommitLineData
5024c2ac
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>
9#include <common/error.h>
10#include <common/macros.h>
11#include <common/runas.h>
12#include <ctype.h>
13#include <lttng/constant.h>
14#include <lttng/event-rule/event-rule-internal.h>
15#include <lttng/event-rule/kprobe-internal.h>
16#include <stdio.h>
17
18#define IS_KPROBE_EVENT_RULE(rule) \
19 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KPROBE)
20
21#if (LTTNG_SYMBOL_NAME_LEN == 256)
22#define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
23#endif
24
25static void lttng_event_rule_kprobe_destroy(struct lttng_event_rule *rule)
26{
27 struct lttng_event_rule_kprobe *kprobe;
28
29 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
30
31 free(kprobe->name);
32 free(kprobe->probe.symbol_name);
33 free(kprobe);
34}
35
36static bool lttng_event_rule_kprobe_validate(
37 const struct lttng_event_rule *rule)
38{
39 bool valid = false;
40 struct lttng_event_rule_kprobe *kprobe;
41
42 if (!rule) {
43 goto end;
44 }
45
46 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
47
48 /* Required field */
49 if (!kprobe->name) {
50 ERR("Invalid name event rule: a name must be set.");
51 goto end;
52 }
53 if (kprobe->probe.set == LTTNG_DOMAIN_NONE) {
54 ERR("Invalid kprobe event rule: a source must be set.");
55 goto end;
56 }
57
58 valid = true;
59end:
60 return valid;
61}
62
63static int lttng_event_rule_kprobe_serialize(
64 const struct lttng_event_rule *rule,
65 struct lttng_dynamic_buffer *buf,
66 int *fd_to_send)
67{
68 int ret;
69 size_t name_len, probe_symbol_name_len;
70 struct lttng_event_rule_kprobe *kprobe;
71 struct lttng_event_rule_kprobe_comm kprobe_comm;
72
73 if (!rule || !IS_KPROBE_EVENT_RULE(rule)) {
74 ret = -1;
75 goto end;
76 }
77
78 DBG("Serializing kprobe event rule");
79 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
80
81 name_len = strlen(kprobe->name) + 1;
82
83 if (kprobe->probe.symbol_name != NULL) {
84 probe_symbol_name_len = strlen(kprobe->probe.symbol_name) + 1;
85 } else {
86 probe_symbol_name_len = 0;
87 }
88
89 kprobe_comm.name_len = name_len;
90 kprobe_comm.probe_symbol_name_len = probe_symbol_name_len;
91 kprobe_comm.probe_address = kprobe->probe.address;
92 kprobe_comm.probe_offset = kprobe->probe.offset;
93
94 ret = lttng_dynamic_buffer_append(
95 buf, &kprobe_comm, sizeof(kprobe_comm));
96 if (ret) {
97 goto end;
98 }
99 ret = lttng_dynamic_buffer_append(buf, kprobe->name, name_len);
100 if (ret) {
101 goto end;
102 }
103 ret = lttng_dynamic_buffer_append(
104 buf, kprobe->probe.symbol_name, probe_symbol_name_len);
105 if (ret) {
106 goto end;
107 }
108
109 if (fd_to_send) {
110 /* Nothing to send */
111 *fd_to_send = -1;
112 }
113end:
114 return ret;
115}
116
117static bool lttng_event_rule_kprobe_is_equal(const struct lttng_event_rule *_a,
118 const struct lttng_event_rule *_b)
119{
120 bool is_equal = false;
121 struct lttng_event_rule_kprobe *a, *b;
122
123 a = container_of(_a, struct lttng_event_rule_kprobe, parent);
124 b = container_of(_b, struct lttng_event_rule_kprobe, parent);
125
126 /* Quick checks */
127 if (!!a->name != !!b->name) {
128 goto end;
129 }
130
131 if (!!a->probe.symbol_name != !!b->probe.symbol_name) {
132 goto end;
133 }
134
135 /* Long check */
136 /* kprobe is invalid if this is not true */
137 /* TODO: validate that a kprobe MUST have a name */
138 assert(a->name);
139 assert(b->name);
140 if (strcmp(a->name, b->name)) {
141 goto end;
142 }
143
144 if (a->probe.symbol_name) {
145 /* Both have symbol name due to previous checks */
146 if (strcmp(a->probe.symbol_name, b->probe.symbol_name)) {
147 goto end;
148 }
149 }
150
151 if (a->probe.offset != b->probe.offset) {
152 goto end;
153 }
154
155 if (a->probe.address != b->probe.address) {
156 goto end;
157 }
158
159 is_equal = true;
160end:
161 return is_equal;
162}
163
164static enum lttng_error_code lttng_event_rule_kprobe_populate(
165 struct lttng_event_rule *rule, uid_t uid, gid_t gid)
166{
167 /* Nothing to do */
168 return LTTNG_OK;
169}
170
171static const char *lttng_event_rule_kprobe_get_filter(
172 const struct lttng_event_rule *rule)
173{
174 /* Not supported */
175 return NULL;
176}
177
178static const struct lttng_bytecode *
179lttng_event_rule_kprobe_get_filter_bytecode(const struct lttng_event_rule *rule)
180{
181 /* Not supported */
182 return NULL;
183}
184
185static struct lttng_event_exclusion *
186lttng_event_rule_kprobe_generate_exclusions(struct lttng_event_rule *rule)
187{
188 /* Not supported */
189 return NULL;
190}
191
192struct lttng_event_rule *lttng_event_rule_kprobe_create()
193{
194 struct lttng_event_rule_kprobe *rule;
195
196 rule = zmalloc(sizeof(struct lttng_event_rule_kprobe));
197 if (!rule) {
198 return NULL;
199 }
200
201 lttng_event_rule_init(&rule->parent, LTTNG_EVENT_RULE_TYPE_KPROBE);
202 rule->parent.validate = lttng_event_rule_kprobe_validate;
203 rule->parent.serialize = lttng_event_rule_kprobe_serialize;
204 rule->parent.equal = lttng_event_rule_kprobe_is_equal;
205 rule->parent.destroy = lttng_event_rule_kprobe_destroy;
206 rule->parent.populate = lttng_event_rule_kprobe_populate;
207 rule->parent.get_filter = lttng_event_rule_kprobe_get_filter;
208 rule->parent.get_filter_bytecode =
209 lttng_event_rule_kprobe_get_filter_bytecode;
210 rule->parent.generate_exclusions =
211 lttng_event_rule_kprobe_generate_exclusions;
212 return &rule->parent;
213}
214
215LTTNG_HIDDEN
216ssize_t lttng_event_rule_kprobe_create_from_buffer(
217 const struct lttng_buffer_view *view,
218 struct lttng_event_rule **_event_rule)
219{
220 ssize_t ret, offset = 0;
221 enum lttng_event_rule_status status;
222 const struct lttng_event_rule_kprobe_comm *kprobe_comm;
223 const char *name;
224 const char *probe_symbol_name = NULL;
225 struct lttng_buffer_view current_view;
226 struct lttng_event_rule *rule = NULL;
227 struct lttng_event_rule_kprobe *kprobe = NULL;
228
229 if (!_event_rule) {
230 ret = -1;
231 goto end;
232 }
233
234 if (view->size < sizeof(*kprobe_comm)) {
235 ERR("Failed to initialize from malformed event rule kprobe: buffer too short to contain header");
236 ret = -1;
237 goto end;
238 }
239
240 current_view = lttng_buffer_view_from_view(
241 view, offset, sizeof(*kprobe_comm));
242 kprobe_comm = (typeof(kprobe_comm)) current_view.data;
243 if (!kprobe_comm) {
244 ret = -1;
245 goto end;
246 }
247
248 rule = lttng_event_rule_kprobe_create();
249 if (!rule) {
250 ERR("Failed to create event rule kprobe");
251 ret = -1;
252 goto end;
253 }
254
255 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
256
257 /* Skip to payload */
258 offset += current_view.size;
259 /* Map the name */
260 current_view = lttng_buffer_view_from_view(
261 view, offset, kprobe_comm->name_len);
262 name = current_view.data;
263 if (!name) {
264 ret = -1;
265 goto end;
266 }
267
268 if (kprobe_comm->name_len == 1 ||
269 name[kprobe_comm->name_len - 1] != '\0' ||
270 strlen(name) != kprobe_comm->name_len - 1) {
271 /*
272 * Check that the name is not NULL, is NULL-terminated, and
273 * does not contain a NULL before the last byte.
274 */
275 ret = -1;
276 goto end;
277 }
278
279 /* Skip after the name */
280 offset += kprobe_comm->name_len;
281 if (!kprobe_comm->probe_symbol_name_len) {
282 goto skip_probe_symbol_name;
283 }
284
285 /* Map the probe_symbol_name */
286 current_view = lttng_buffer_view_from_view(
287 view, offset, kprobe_comm->probe_symbol_name_len);
288 probe_symbol_name = current_view.data;
289 if (!probe_symbol_name) {
290 ret = -1;
291 goto end;
292 }
293
294 if (kprobe_comm->probe_symbol_name_len == 1 ||
295 probe_symbol_name[kprobe_comm->probe_symbol_name_len -
296 1] != '\0' ||
297 strlen(probe_symbol_name) !=
298 kprobe_comm->probe_symbol_name_len -
299 1) {
300 /*
301 * Check that the filter expression is not NULL, is
302 * NULL-terminated, and does not contain a NULL before the last
303 * byte.
304 */
305 ret = -1;
306 goto end;
307 }
308
309 /* Skip after the pattern */
310 offset += kprobe_comm->probe_symbol_name_len;
311
312skip_probe_symbol_name:
313
314 status = lttng_event_rule_kprobe_set_name(rule, name);
315 if (status != LTTNG_EVENT_RULE_STATUS_OK) {
316 ERR("Failed to set event rule kprobe name");
317 ret = -1;
318 goto end;
319 }
320 kprobe->probe.offset = kprobe_comm->probe_offset;
321 kprobe->probe.address = kprobe_comm->probe_address;
322 if (probe_symbol_name) {
323 kprobe->probe.symbol_name = strdup(probe_symbol_name);
324 if (!kprobe->probe.symbol_name) {
325 ERR("Failed to set event rule kprobe probe symbol name");
326 ret = -1;
327 goto end;
328 }
329 }
330
331 *_event_rule = rule;
332 rule = NULL;
333 ret = offset;
334end:
335 lttng_event_rule_destroy(rule);
336 return ret;
337}
338
339enum lttng_event_rule_status lttng_event_rule_kprobe_set_source(
340 struct lttng_event_rule *rule, const char *source)
341{
342 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
343 int match;
344 char s_hex[19];
345 char name[LTTNG_SYMBOL_NAME_LEN];
346 struct lttng_event_rule_kprobe *kprobe;
347
348 /* TODO: support multiple call for this, we must free the symbol name if
349 * that happens !!!
350 */
351
352 if (!source || !IS_KPROBE_EVENT_RULE(rule) || !rule) {
353 status = LTTNG_EVENT_RULE_STATUS_INVALID;
354 goto end;
355 }
356
357 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
358
359 /* Check for symbol+offset */
360 match = sscanf(source, "%18s[^'+']+%18s", name, s_hex);
361 if (match == 2) {
362 /* TODO double validate termination handling of this */
363 kprobe->probe.symbol_name =
364 strndup(name, LTTNG_SYMBOL_NAME_LEN);
365 if (!kprobe->probe.symbol_name) {
366 status = LTTNG_EVENT_RULE_STATUS_ERROR;
367 goto end;
368 }
369 if (*s_hex == '\0') {
370 status = LTTNG_EVENT_RULE_STATUS_INVALID;
371 goto end;
372 }
373 kprobe->probe.offset = strtoul(s_hex, NULL, 0);
374 kprobe->probe.address = 0;
375 kprobe->probe.set = true;
376 goto end;
377 }
378
379 /* Check for symbol */
380 if (isalpha(name[0]) || name[0] == '_') {
381 match = sscanf(source,
382 "%" LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API
383 "s",
384 name);
385 if (match == 1) {
386 /* TODO double validate termination handling of this */
387 kprobe->probe.symbol_name =
388 strndup(name, LTTNG_SYMBOL_NAME_LEN);
389 if (!kprobe->probe.symbol_name) {
390 status = LTTNG_EVENT_RULE_STATUS_ERROR;
391 goto end;
392 }
393 kprobe->probe.offset = 0;
394 kprobe->probe.address = 0;
395 kprobe->probe.set = true;
396 goto end;
397 }
398 }
399
400 /* Check for address */
401 match = sscanf(source, "%18s", s_hex);
402 if (match > 0) {
403 if (*s_hex == '\0') {
404 status = LTTNG_EVENT_RULE_STATUS_INVALID;
405 goto end;
406 }
407 kprobe->probe.address = strtoul(s_hex, NULL, 0);
408 kprobe->probe.offset = 0;
409 kprobe->probe.symbol_name = NULL;
410 kprobe->probe.set = true;
411 goto end;
412 }
413
414 /* No match */
415 status = LTTNG_EVENT_RULE_STATUS_INVALID;
416
417end:
418 return status;
419}
420
421enum lttng_event_rule_status lttng_event_rule_kprobe_set_name(
422 struct lttng_event_rule *rule, const char *name)
423{
424 char *name_copy = NULL;
425 struct lttng_event_rule_kprobe *kprobe;
426 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
427
428 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name ||
429 strlen(name) == 0) {
430 status = LTTNG_EVENT_RULE_STATUS_INVALID;
431 goto end;
432 }
433
434 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
435 name_copy = strdup(name);
436 if (!name_copy) {
437 status = LTTNG_EVENT_RULE_STATUS_ERROR;
438 goto end;
439 }
440
441 if (kprobe->name) {
442 free(kprobe->name);
443 }
444
445 kprobe->name = name_copy;
446 name_copy = NULL;
447end:
448 return status;
449}
450
451enum lttng_event_rule_status lttng_event_rule_kprobe_get_name(
452 const struct lttng_event_rule *rule, const char **name)
453{
454 struct lttng_event_rule_kprobe *kprobe;
455 enum lttng_event_rule_status status = LTTNG_EVENT_RULE_STATUS_OK;
456
457 if (!rule || !IS_KPROBE_EVENT_RULE(rule) || !name) {
458 status = LTTNG_EVENT_RULE_STATUS_INVALID;
459 goto end;
460 }
461
462 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
463 if (!kprobe->name) {
464 status = LTTNG_EVENT_RULE_STATUS_UNSET;
465 goto end;
466 }
467
468 *name = kprobe->name;
469end:
470 return status;
471}
472
473LTTNG_HIDDEN
474uint64_t lttng_event_rule_kprobe_get_address(
475 const struct lttng_event_rule *rule)
476{
477 struct lttng_event_rule_kprobe *kprobe;
478
479 assert(rule && IS_KPROBE_EVENT_RULE(rule));
480
481 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
482
483 return kprobe->probe.address;
484}
485
486LTTNG_HIDDEN
487uint64_t lttng_event_rule_kprobe_get_offset(const struct lttng_event_rule *rule)
488{
489 struct lttng_event_rule_kprobe *kprobe;
490
491 assert(rule && IS_KPROBE_EVENT_RULE(rule));
492
493 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
494 return kprobe->probe.offset;
495}
496
497LTTNG_HIDDEN
498const char *lttng_event_rule_kprobe_get_symbol_name(
499 const struct lttng_event_rule *rule)
500{
501 struct lttng_event_rule_kprobe *kprobe;
502
503 assert(rule && IS_KPROBE_EVENT_RULE(rule));
504
505 kprobe = container_of(rule, struct lttng_event_rule_kprobe, parent);
506 return kprobe->probe.symbol_name;
507}
This page took 0.043242 seconds and 5 git commands to generate.