2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/error.h>
10 #include <common/macros.h>
11 #include <common/runas.h>
13 #include <lttng/constant.h>
14 #include <lttng/event-rule/event-rule-internal.h>
15 #include <lttng/event-rule/kprobe-internal.h>
18 #define IS_KPROBE_EVENT_RULE(rule) \
19 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KPROBE)
21 #if (LTTNG_SYMBOL_NAME_LEN == 256)
22 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
25 static void lttng_event_rule_kprobe_destroy(struct lttng_event_rule
*rule
)
27 struct lttng_event_rule_kprobe
*kprobe
;
29 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
32 free(kprobe
->probe
.symbol_name
);
36 static bool lttng_event_rule_kprobe_validate(
37 const struct lttng_event_rule
*rule
)
40 struct lttng_event_rule_kprobe
*kprobe
;
46 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
50 ERR("Invalid name event rule: a name must be set.");
53 if (kprobe
->probe
.set
== LTTNG_DOMAIN_NONE
) {
54 ERR("Invalid kprobe event rule: a source must be set.");
63 static int lttng_event_rule_kprobe_serialize(
64 const struct lttng_event_rule
*rule
,
65 struct lttng_dynamic_buffer
*buf
,
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
;
73 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
)) {
78 DBG("Serializing kprobe event rule");
79 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
81 name_len
= strlen(kprobe
->name
) + 1;
83 if (kprobe
->probe
.symbol_name
!= NULL
) {
84 probe_symbol_name_len
= strlen(kprobe
->probe
.symbol_name
) + 1;
86 probe_symbol_name_len
= 0;
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
;
94 ret
= lttng_dynamic_buffer_append(
95 buf
, &kprobe_comm
, sizeof(kprobe_comm
));
99 ret
= lttng_dynamic_buffer_append(buf
, kprobe
->name
, name_len
);
103 ret
= lttng_dynamic_buffer_append(
104 buf
, kprobe
->probe
.symbol_name
, probe_symbol_name_len
);
110 /* Nothing to send */
117 static bool lttng_event_rule_kprobe_is_equal(const struct lttng_event_rule
*_a
,
118 const struct lttng_event_rule
*_b
)
120 bool is_equal
= false;
121 struct lttng_event_rule_kprobe
*a
, *b
;
123 a
= container_of(_a
, struct lttng_event_rule_kprobe
, parent
);
124 b
= container_of(_b
, struct lttng_event_rule_kprobe
, parent
);
127 if (!!a
->name
!= !!b
->name
) {
131 if (!!a
->probe
.symbol_name
!= !!b
->probe
.symbol_name
) {
136 /* kprobe is invalid if this is not true */
137 /* TODO: validate that a kprobe MUST have a name */
140 if (strcmp(a
->name
, b
->name
)) {
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
)) {
151 if (a
->probe
.offset
!= b
->probe
.offset
) {
155 if (a
->probe
.address
!= b
->probe
.address
) {
164 static enum lttng_error_code
lttng_event_rule_kprobe_populate(
165 struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
171 static const char *lttng_event_rule_kprobe_get_filter(
172 const struct lttng_event_rule
*rule
)
178 static const struct lttng_bytecode
*
179 lttng_event_rule_kprobe_get_filter_bytecode(const struct lttng_event_rule
*rule
)
185 static struct lttng_event_exclusion
*
186 lttng_event_rule_kprobe_generate_exclusions(struct lttng_event_rule
*rule
)
192 struct lttng_event_rule
*lttng_event_rule_kprobe_create()
194 struct lttng_event_rule_kprobe
*rule
;
196 rule
= zmalloc(sizeof(struct lttng_event_rule_kprobe
));
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
;
216 ssize_t
lttng_event_rule_kprobe_create_from_buffer(
217 const struct lttng_buffer_view
*view
,
218 struct lttng_event_rule
**_event_rule
)
220 ssize_t ret
, offset
= 0;
221 enum lttng_event_rule_status status
;
222 const struct lttng_event_rule_kprobe_comm
*kprobe_comm
;
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
;
234 if (view
->size
< sizeof(*kprobe_comm
)) {
235 ERR("Failed to initialize from malformed event rule kprobe: buffer too short to contain header");
240 current_view
= lttng_buffer_view_from_view(
241 view
, offset
, sizeof(*kprobe_comm
));
242 kprobe_comm
= (typeof(kprobe_comm
)) current_view
.data
;
248 rule
= lttng_event_rule_kprobe_create();
250 ERR("Failed to create event rule kprobe");
255 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
257 /* Skip to payload */
258 offset
+= current_view
.size
;
260 current_view
= lttng_buffer_view_from_view(
261 view
, offset
, kprobe_comm
->name_len
);
262 name
= current_view
.data
;
268 if (kprobe_comm
->name_len
== 1 ||
269 name
[kprobe_comm
->name_len
- 1] != '\0' ||
270 strlen(name
) != kprobe_comm
->name_len
- 1) {
272 * Check that the name is not NULL, is NULL-terminated, and
273 * does not contain a NULL before the last byte.
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
;
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
) {
294 if (kprobe_comm
->probe_symbol_name_len
== 1 ||
295 probe_symbol_name
[kprobe_comm
->probe_symbol_name_len
-
297 strlen(probe_symbol_name
) !=
298 kprobe_comm
->probe_symbol_name_len
-
301 * Check that the filter expression is not NULL, is
302 * NULL-terminated, and does not contain a NULL before the last
309 /* Skip after the pattern */
310 offset
+= kprobe_comm
->probe_symbol_name_len
;
312 skip_probe_symbol_name
:
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");
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");
335 lttng_event_rule_destroy(rule
);
339 enum lttng_event_rule_status
lttng_event_rule_kprobe_set_source(
340 struct lttng_event_rule
*rule
, const char *source
)
342 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
345 char name
[LTTNG_SYMBOL_NAME_LEN
];
346 struct lttng_event_rule_kprobe
*kprobe
;
348 /* TODO: support multiple call for this, we must free the symbol name if
352 if (!source
|| !IS_KPROBE_EVENT_RULE(rule
) || !rule
) {
353 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
357 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
359 /* Check for symbol+offset */
360 match
= sscanf(source
, "%18s[^'+']+%18s", name
, s_hex
);
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
;
369 if (*s_hex
== '\0') {
370 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
373 kprobe
->probe
.offset
= strtoul(s_hex
, NULL
, 0);
374 kprobe
->probe
.address
= 0;
375 kprobe
->probe
.set
= true;
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
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
;
393 kprobe
->probe
.offset
= 0;
394 kprobe
->probe
.address
= 0;
395 kprobe
->probe
.set
= true;
400 /* Check for address */
401 match
= sscanf(source
, "%18s", s_hex
);
403 if (*s_hex
== '\0') {
404 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
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;
415 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
421 enum lttng_event_rule_status
lttng_event_rule_kprobe_set_name(
422 struct lttng_event_rule
*rule
, const char *name
)
424 char *name_copy
= NULL
;
425 struct lttng_event_rule_kprobe
*kprobe
;
426 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
428 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
) || !name
||
430 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
434 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
435 name_copy
= strdup(name
);
437 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
445 kprobe
->name
= name_copy
;
451 enum lttng_event_rule_status
lttng_event_rule_kprobe_get_name(
452 const struct lttng_event_rule
*rule
, const char **name
)
454 struct lttng_event_rule_kprobe
*kprobe
;
455 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
457 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
) || !name
) {
458 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
462 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
464 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
468 *name
= kprobe
->name
;
474 uint64_t lttng_event_rule_kprobe_get_address(
475 const struct lttng_event_rule
*rule
)
477 struct lttng_event_rule_kprobe
*kprobe
;
479 assert(rule
&& IS_KPROBE_EVENT_RULE(rule
));
481 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
483 return kprobe
->probe
.address
;
487 uint64_t lttng_event_rule_kprobe_get_offset(const struct lttng_event_rule
*rule
)
489 struct lttng_event_rule_kprobe
*kprobe
;
491 assert(rule
&& IS_KPROBE_EVENT_RULE(rule
));
493 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
494 return kprobe
->probe
.offset
;
498 const char *lttng_event_rule_kprobe_get_symbol_name(
499 const struct lttng_event_rule
*rule
)
501 struct lttng_event_rule_kprobe
*kprobe
;
503 assert(rule
&& IS_KPROBE_EVENT_RULE(rule
));
505 kprobe
= container_of(rule
, struct lttng_event_rule_kprobe
, parent
);
506 return kprobe
->probe
.symbol_name
;