2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
9 #include <common/credentials.h>
10 #include <common/error.h>
11 #include <common/hashtable/hashtable.h>
12 #include <common/hashtable/utils.h>
13 #include <common/macros.h>
14 #include <common/mi-lttng.h>
15 #include <common/payload-view.h>
16 #include <common/payload.h>
17 #include <common/runas.h>
18 #include <lttng/event-rule/event-rule-internal.h>
19 #include <lttng/event-rule/kernel-uprobe-internal.h>
20 #include <lttng/userspace-probe-internal.h>
22 #define IS_UPROBE_EVENT_RULE(rule) \
23 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE)
25 static void lttng_event_rule_kernel_uprobe_destroy(struct lttng_event_rule
*rule
)
27 struct lttng_event_rule_kernel_uprobe
*uprobe
;
29 uprobe
= container_of(rule
, struct lttng_event_rule_kernel_uprobe
, parent
);
31 lttng_userspace_probe_location_destroy(uprobe
->location
);
36 static bool lttng_event_rule_kernel_uprobe_validate(
37 const struct lttng_event_rule
*rule
)
40 struct lttng_event_rule_kernel_uprobe
*uprobe
;
46 uprobe
= container_of(rule
, struct lttng_event_rule_kernel_uprobe
, parent
);
50 ERR("Invalid uprobe event rule: a pattern must be set.");
54 if (!uprobe
->location
) {
55 ERR("Invalid uprobe event rule: a location must be set.");
64 static int lttng_event_rule_kernel_uprobe_serialize(
65 const struct lttng_event_rule
*rule
,
66 struct lttng_payload
*payload
)
69 size_t name_len
, header_offset
, size_before_probe
;
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
;
74 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
)) {
79 header_offset
= payload
->buffer
.size
;
81 DBG("Serializing uprobe event rule.");
82 uprobe
= container_of(rule
, struct lttng_event_rule_kernel_uprobe
, parent
);
84 name_len
= strlen(uprobe
->name
) + 1;
86 uprobe_comm
.name_len
= name_len
;
88 ret
= lttng_dynamic_buffer_append(
89 &payload
->buffer
, &uprobe_comm
, sizeof(uprobe_comm
));
93 ret
= lttng_dynamic_buffer_append(
94 &payload
->buffer
, uprobe
->name
, name_len
);
99 size_before_probe
= payload
->buffer
.size
;
101 /* This serialize return the size taken in the buffer. */
102 ret
= lttng_userspace_probe_location_serialize(
103 uprobe
->location
, payload
);
108 /* Update the header regarding the probe size. */
109 header
= (struct lttng_event_rule_kernel_uprobe_comm
110 *) ((char *) payload
->buffer
.data
+
112 header
->location_len
= payload
->buffer
.size
- size_before_probe
;
120 static bool lttng_event_rule_kernel_uprobe_is_equal(const struct lttng_event_rule
*_a
,
121 const struct lttng_event_rule
*_b
)
123 bool is_equal
= false;
124 struct lttng_event_rule_kernel_uprobe
*a
, *b
;
126 a
= container_of(_a
, struct lttng_event_rule_kernel_uprobe
, parent
);
127 b
= container_of(_b
, struct lttng_event_rule_kernel_uprobe
, parent
);
129 /* uprobe is invalid if this is not true. */
132 if (strcmp(a
->name
, b
->name
)) {
138 is_equal
= lttng_userspace_probe_location_is_equal(
139 a
->location
, b
->location
);
144 static enum lttng_error_code
lttng_event_rule_kernel_uprobe_generate_filter_bytecode(
145 struct lttng_event_rule
*rule
,
146 const struct lttng_credentials
*creds
)
152 static const char *lttng_event_rule_kernel_uprobe_get_filter(
153 const struct lttng_event_rule
*rule
)
159 static const struct lttng_bytecode
*
160 lttng_event_rule_kernel_uprobe_get_filter_bytecode(const struct lttng_event_rule
*rule
)
166 static enum lttng_event_rule_generate_exclusions_status
167 lttng_event_rule_kernel_uprobe_generate_exclusions(const struct lttng_event_rule
*rule
,
168 struct lttng_event_exclusion
**exclusions
)
172 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
176 lttng_event_rule_kernel_uprobe_hash(
177 const struct lttng_event_rule
*rule
)
180 struct lttng_event_rule_kernel_uprobe
*urule
=
181 container_of(rule
, typeof(*urule
), parent
);
183 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE
,
185 hash
^= hash_key_str(urule
->name
, lttng_ht_seed
);
186 hash
^= lttng_userspace_probe_location_hash(urule
->location
);
192 int userspace_probe_set_location(
193 struct lttng_event_rule_kernel_uprobe
*uprobe
,
194 const struct lttng_userspace_probe_location
*location
)
197 struct lttng_userspace_probe_location
*location_copy
= NULL
;
199 if (!uprobe
|| !location
|| uprobe
->location
) {
204 location_copy
= lttng_userspace_probe_location_copy(location
);
205 if (!location_copy
) {
210 uprobe
->location
= location_copy
;
211 location_copy
= NULL
;
214 lttng_userspace_probe_location_destroy(location_copy
);
218 static enum lttng_error_code
lttng_event_rule_kernel_uprobe_mi_serialize(
219 const struct lttng_event_rule
*rule
, struct mi_writer
*writer
)
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
;
229 assert(IS_UPROBE_EVENT_RULE(rule
));
231 status
= lttng_event_rule_kernel_uprobe_get_event_name(
233 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
236 status
= lttng_event_rule_kernel_uprobe_get_location(rule
, &location
);
237 assert(status
== LTTNG_EVENT_RULE_STATUS_OK
);
240 /* Open event rule kernel uprobe element. */
241 ret
= mi_lttng_writer_open_element(
242 writer
, mi_lttng_element_event_rule_kernel_uprobe
);
248 ret
= mi_lttng_writer_write_element_string(writer
,
249 mi_lttng_element_event_rule_event_name
, event_name
);
254 /* Probe location. */
255 ret_code
= lttng_userspace_probe_location_mi_serialize(location
, writer
);
256 if (ret_code
!= LTTNG_OK
) {
260 /* Close event rule kernel uprobe element. */
261 ret
= mi_lttng_writer_close_element(writer
);
270 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
275 struct lttng_event_rule
*lttng_event_rule_kernel_uprobe_create(
276 const struct lttng_userspace_probe_location
*location
)
278 struct lttng_event_rule
*rule
= NULL
;
279 struct lttng_event_rule_kernel_uprobe
*urule
;
281 urule
= zmalloc(sizeof(struct lttng_event_rule_kernel_uprobe
));
286 rule
= &urule
->parent
;
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
;
292 urule
->parent
.generate_filter_bytecode
=
293 lttng_event_rule_kernel_uprobe_generate_filter_bytecode
;
294 urule
->parent
.get_filter
= lttng_event_rule_kernel_uprobe_get_filter
;
295 urule
->parent
.get_filter_bytecode
=
296 lttng_event_rule_kernel_uprobe_get_filter_bytecode
;
297 urule
->parent
.generate_exclusions
=
298 lttng_event_rule_kernel_uprobe_generate_exclusions
;
299 urule
->parent
.hash
= lttng_event_rule_kernel_uprobe_hash
;
300 urule
->parent
.mi_serialize
= lttng_event_rule_kernel_uprobe_mi_serialize
;
302 if (userspace_probe_set_location(urule
, location
)) {
303 lttng_event_rule_destroy(rule
);
312 ssize_t
lttng_event_rule_kernel_uprobe_create_from_payload(
313 struct lttng_payload_view
*view
,
314 struct lttng_event_rule
**_event_rule
)
316 ssize_t ret
, offset
= 0;
317 const struct lttng_event_rule_kernel_uprobe_comm
*uprobe_comm
;
319 struct lttng_buffer_view current_buffer_view
;
320 struct lttng_event_rule
*rule
= NULL
;
321 struct lttng_userspace_probe_location
*location
= NULL
;
322 enum lttng_event_rule_status status
;
329 current_buffer_view
= lttng_buffer_view_from_view(
330 &view
->buffer
, offset
, sizeof(*uprobe_comm
));
331 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
332 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
337 uprobe_comm
= (typeof(uprobe_comm
)) current_buffer_view
.data
;
339 /* Skip to payload. */
340 offset
+= current_buffer_view
.size
;
343 current_buffer_view
= lttng_buffer_view_from_view(
344 &view
->buffer
, offset
, uprobe_comm
->name_len
);
345 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
350 name
= current_buffer_view
.data
;
351 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, name
,
352 uprobe_comm
->name_len
)) {
357 /* Skip after the name. */
358 offset
+= uprobe_comm
->name_len
;
360 /* Map the location. */
362 struct lttng_payload_view current_payload_view
=
363 lttng_payload_view_from_view(view
, offset
,
364 uprobe_comm
->location_len
);
366 if (!lttng_payload_view_is_valid(¤t_payload_view
)) {
367 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain location");
372 ret
= lttng_userspace_probe_location_create_from_payload(
373 ¤t_payload_view
, &location
);
380 assert(ret
== uprobe_comm
->location_len
);
382 /* Skip after the location. */
383 offset
+= uprobe_comm
->location_len
;
385 rule
= lttng_event_rule_kernel_uprobe_create(location
);
387 ERR("Failed to create event rule uprobe.");
392 status
= lttng_event_rule_kernel_uprobe_set_event_name(rule
, name
);
393 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
398 if (!lttng_event_rule_kernel_uprobe_validate(rule
)) {
407 lttng_userspace_probe_location_destroy(location
);
408 lttng_event_rule_destroy(rule
);
413 enum lttng_event_rule_status
lttng_event_rule_kernel_uprobe_get_location(
414 const struct lttng_event_rule
*rule
,
415 const struct lttng_userspace_probe_location
**location
)
417 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
419 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
420 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
424 *location
= lttng_event_rule_kernel_uprobe_get_location_mutable(rule
);
426 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
435 struct lttng_userspace_probe_location
*
436 lttng_event_rule_kernel_uprobe_get_location_mutable(
437 const struct lttng_event_rule
*rule
)
439 struct lttng_event_rule_kernel_uprobe
*uprobe
;
442 uprobe
= container_of(rule
, struct lttng_event_rule_kernel_uprobe
, parent
);
444 return uprobe
->location
;
447 enum lttng_event_rule_status
lttng_event_rule_kernel_uprobe_set_event_name(
448 struct lttng_event_rule
*rule
, const char *name
)
450 char *name_copy
= NULL
;
451 struct lttng_event_rule_kernel_uprobe
*uprobe
;
452 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
454 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
||
456 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
460 uprobe
= container_of(rule
, struct lttng_event_rule_kernel_uprobe
, parent
);
461 name_copy
= strdup(name
);
463 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
471 uprobe
->name
= name_copy
;
477 enum lttng_event_rule_status
lttng_event_rule_kernel_uprobe_get_event_name(
478 const struct lttng_event_rule
*rule
, const char **name
)
480 struct lttng_event_rule_kernel_uprobe
*uprobe
;
481 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
483 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
484 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
488 uprobe
= container_of(rule
, struct lttng_event_rule_kernel_uprobe
, parent
);
490 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
494 *name
= uprobe
->name
;