2 * Copyright (C) 2019 Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
4 * SPDX-License-Identifier: LGPL-2.1-only
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>
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>
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
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_uprobe::parent
);
31 lttng_userspace_probe_location_destroy(uprobe
->location
);
36 static bool lttng_event_rule_kernel_uprobe_validate(const struct lttng_event_rule
*rule
)
39 struct lttng_event_rule_kernel_uprobe
*uprobe
;
45 uprobe
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_uprobe::parent
);
49 ERR("Invalid uprobe event rule: a pattern must be set.");
53 if (!uprobe
->location
) {
54 ERR("Invalid uprobe event rule: a location must be set.");
63 static int lttng_event_rule_kernel_uprobe_serialize(const struct lttng_event_rule
*rule
,
64 struct lttng_payload
*payload
)
67 size_t name_len
, header_offset
, size_before_probe
;
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
;
72 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
)) {
77 header_offset
= payload
->buffer
.size
;
79 DBG("Serializing uprobe event rule.");
80 uprobe
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_uprobe::parent
);
82 name_len
= strlen(uprobe
->name
) + 1;
84 uprobe_comm
.name_len
= name_len
;
86 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, &uprobe_comm
, sizeof(uprobe_comm
));
90 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, uprobe
->name
, name_len
);
95 size_before_probe
= payload
->buffer
.size
;
97 /* This serialize return the size taken in the buffer. */
98 ret
= lttng_userspace_probe_location_serialize(uprobe
->location
, payload
);
103 /* Update the header regarding the probe size. */
104 header
= (struct lttng_event_rule_kernel_uprobe_comm
*) ((char *) payload
->buffer
.data
+
106 header
->location_len
= payload
->buffer
.size
- size_before_probe
;
114 static bool lttng_event_rule_kernel_uprobe_is_equal(const struct lttng_event_rule
*_a
,
115 const struct lttng_event_rule
*_b
)
117 bool is_equal
= false;
118 struct lttng_event_rule_kernel_uprobe
*a
, *b
;
120 a
= lttng::utils::container_of(_a
, <tng_event_rule_kernel_uprobe::parent
);
121 b
= lttng::utils::container_of(_b
, <tng_event_rule_kernel_uprobe::parent
);
123 /* uprobe is invalid if this is not true. */
124 LTTNG_ASSERT(a
->name
);
125 LTTNG_ASSERT(b
->name
);
126 if (strcmp(a
->name
, b
->name
) != 0) {
130 LTTNG_ASSERT(a
->location
);
131 LTTNG_ASSERT(b
->location
);
132 is_equal
= lttng_userspace_probe_location_is_equal(a
->location
, b
->location
);
137 static enum lttng_error_code
lttng_event_rule_kernel_uprobe_generate_filter_bytecode(
138 struct lttng_event_rule
*rule
__attribute__((unused
)),
139 const struct lttng_credentials
*creds
__attribute__((unused
)))
145 static const char *lttng_event_rule_kernel_uprobe_get_filter(const struct lttng_event_rule
*rule
146 __attribute__((unused
)))
152 static const struct lttng_bytecode
*
153 lttng_event_rule_kernel_uprobe_get_filter_bytecode(const struct lttng_event_rule
*rule
154 __attribute__((unused
)))
160 static enum lttng_event_rule_generate_exclusions_status
161 lttng_event_rule_kernel_uprobe_generate_exclusions(const struct lttng_event_rule
*rule
162 __attribute__((unused
)),
163 struct lttng_event_exclusion
**exclusions
)
166 *exclusions
= nullptr;
167 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
170 static unsigned long lttng_event_rule_kernel_uprobe_hash(const struct lttng_event_rule
*rule
)
173 struct lttng_event_rule_kernel_uprobe
*urule
=
174 lttng::utils::container_of(rule
, <tng_event_rule_kernel_uprobe::parent
);
176 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE
, lttng_ht_seed
);
177 hash
^= hash_key_str(urule
->name
, lttng_ht_seed
);
178 hash
^= lttng_userspace_probe_location_hash(urule
->location
);
183 static int userspace_probe_set_location(struct lttng_event_rule_kernel_uprobe
*uprobe
,
184 const struct lttng_userspace_probe_location
*location
)
187 struct lttng_userspace_probe_location
*location_copy
= nullptr;
189 if (!uprobe
|| !location
|| uprobe
->location
) {
194 location_copy
= lttng_userspace_probe_location_copy(location
);
195 if (!location_copy
) {
200 uprobe
->location
= location_copy
;
201 location_copy
= nullptr;
204 lttng_userspace_probe_location_destroy(location_copy
);
208 static enum lttng_error_code
209 lttng_event_rule_kernel_uprobe_mi_serialize(const struct lttng_event_rule
*rule
,
210 struct mi_writer
*writer
)
213 enum lttng_error_code ret_code
;
214 enum lttng_event_rule_status status
;
215 const char *event_name
= nullptr;
216 const struct lttng_userspace_probe_location
*location
= nullptr;
219 LTTNG_ASSERT(writer
);
220 LTTNG_ASSERT(IS_UPROBE_EVENT_RULE(rule
));
222 status
= lttng_event_rule_kernel_uprobe_get_event_name(rule
, &event_name
);
223 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
224 LTTNG_ASSERT(event_name
);
226 status
= lttng_event_rule_kernel_uprobe_get_location(rule
, &location
);
227 LTTNG_ASSERT(status
== LTTNG_EVENT_RULE_STATUS_OK
);
228 LTTNG_ASSERT(location
);
230 /* Open event rule kernel uprobe element. */
231 ret
= mi_lttng_writer_open_element(writer
, mi_lttng_element_event_rule_kernel_uprobe
);
237 ret
= mi_lttng_writer_write_element_string(
238 writer
, mi_lttng_element_event_rule_event_name
, event_name
);
243 /* Probe location. */
244 ret_code
= lttng_userspace_probe_location_mi_serialize(location
, writer
);
245 if (ret_code
!= LTTNG_OK
) {
249 /* Close event rule kernel uprobe element. */
250 ret
= mi_lttng_writer_close_element(writer
);
259 ret_code
= LTTNG_ERR_MI_IO_FAIL
;
264 struct lttng_event_rule
*
265 lttng_event_rule_kernel_uprobe_create(const struct lttng_userspace_probe_location
*location
)
267 struct lttng_event_rule
*rule
= nullptr;
268 struct lttng_event_rule_kernel_uprobe
*urule
;
270 urule
= zmalloc
<lttng_event_rule_kernel_uprobe
>();
275 rule
= &urule
->parent
;
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
;
281 urule
->parent
.generate_filter_bytecode
=
282 lttng_event_rule_kernel_uprobe_generate_filter_bytecode
;
283 urule
->parent
.get_filter
= lttng_event_rule_kernel_uprobe_get_filter
;
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
;
286 urule
->parent
.hash
= lttng_event_rule_kernel_uprobe_hash
;
287 urule
->parent
.mi_serialize
= lttng_event_rule_kernel_uprobe_mi_serialize
;
289 if (userspace_probe_set_location(urule
, location
)) {
290 lttng_event_rule_destroy(rule
);
298 ssize_t
lttng_event_rule_kernel_uprobe_create_from_payload(struct lttng_payload_view
*view
,
299 struct lttng_event_rule
**_event_rule
)
301 ssize_t ret
, offset
= 0;
302 const struct lttng_event_rule_kernel_uprobe_comm
*uprobe_comm
;
304 struct lttng_buffer_view current_buffer_view
;
305 struct lttng_event_rule
*rule
= nullptr;
306 struct lttng_userspace_probe_location
*location
= nullptr;
307 enum lttng_event_rule_status status
;
314 current_buffer_view
=
315 lttng_buffer_view_from_view(&view
->buffer
, offset
, sizeof(*uprobe_comm
));
316 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
317 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
322 uprobe_comm
= (typeof(uprobe_comm
)) current_buffer_view
.data
;
324 /* Skip to payload. */
325 offset
+= current_buffer_view
.size
;
328 current_buffer_view
=
329 lttng_buffer_view_from_view(&view
->buffer
, offset
, uprobe_comm
->name_len
);
330 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
335 name
= current_buffer_view
.data
;
336 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, name
, uprobe_comm
->name_len
)) {
341 /* Skip after the name. */
342 offset
+= uprobe_comm
->name_len
;
344 /* Map the location. */
346 struct lttng_payload_view current_payload_view
=
347 lttng_payload_view_from_view(view
, offset
, uprobe_comm
->location_len
);
349 if (!lttng_payload_view_is_valid(¤t_payload_view
)) {
350 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain location");
355 ret
= lttng_userspace_probe_location_create_from_payload(¤t_payload_view
,
363 LTTNG_ASSERT(ret
== uprobe_comm
->location_len
);
365 /* Skip after the location. */
366 offset
+= uprobe_comm
->location_len
;
368 rule
= lttng_event_rule_kernel_uprobe_create(location
);
370 ERR("Failed to create event rule uprobe.");
375 status
= lttng_event_rule_kernel_uprobe_set_event_name(rule
, name
);
376 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
381 if (!lttng_event_rule_kernel_uprobe_validate(rule
)) {
390 lttng_userspace_probe_location_destroy(location
);
391 lttng_event_rule_destroy(rule
);
395 enum lttng_event_rule_status
396 lttng_event_rule_kernel_uprobe_get_location(const struct lttng_event_rule
*rule
,
397 const struct lttng_userspace_probe_location
**location
)
399 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
401 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
402 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
406 *location
= lttng_event_rule_kernel_uprobe_get_location_mutable(rule
);
408 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
416 struct lttng_userspace_probe_location
*
417 lttng_event_rule_kernel_uprobe_get_location_mutable(const struct lttng_event_rule
*rule
)
419 struct lttng_event_rule_kernel_uprobe
*uprobe
;
422 uprobe
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_uprobe::parent
);
424 return uprobe
->location
;
427 enum lttng_event_rule_status
428 lttng_event_rule_kernel_uprobe_set_event_name(struct lttng_event_rule
*rule
, const char *name
)
430 char *name_copy
= nullptr;
431 struct lttng_event_rule_kernel_uprobe
*uprobe
;
432 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
434 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
|| strlen(name
) == 0) {
435 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
439 uprobe
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_uprobe::parent
);
440 name_copy
= strdup(name
);
442 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
450 uprobe
->name
= name_copy
;
456 enum lttng_event_rule_status
457 lttng_event_rule_kernel_uprobe_get_event_name(const struct lttng_event_rule
*rule
,
460 struct lttng_event_rule_kernel_uprobe
*uprobe
;
461 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
463 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
464 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
468 uprobe
= lttng::utils::container_of(rule
, <tng_event_rule_kernel_uprobe::parent
);
470 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
474 *name
= uprobe
->name
;