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/macros.h>
12 #include <common/payload.h>
13 #include <common/payload-view.h>
14 #include <common/runas.h>
15 #include <common/hashtable/hashtable.h>
16 #include <common/hashtable/utils.h>
17 #include <lttng/event-rule/event-rule-internal.h>
18 #include <lttng/event-rule/uprobe-internal.h>
19 #include <lttng/userspace-probe-internal.h>
21 #define IS_UPROBE_EVENT_RULE(rule) \
22 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE)
24 static void lttng_event_rule_userspace_probe_destroy(struct lttng_event_rule
*rule
)
26 struct lttng_event_rule_userspace_probe
*uprobe
;
28 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, parent
);
30 lttng_userspace_probe_location_destroy(uprobe
->location
);
35 static bool lttng_event_rule_userspace_probe_validate(
36 const struct lttng_event_rule
*rule
)
39 struct lttng_event_rule_userspace_probe
*uprobe
;
45 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, 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_userspace_probe_serialize(
64 const struct lttng_event_rule
*rule
,
65 struct lttng_payload
*payload
)
68 size_t name_len
, header_offset
, size_before_probe
;
69 struct lttng_event_rule_userspace_probe
*uprobe
;
70 struct lttng_event_rule_userspace_probe_comm uprobe_comm
= {};
71 struct lttng_event_rule_userspace_probe_comm
*header
;
73 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
)) {
78 header_offset
= payload
->buffer
.size
;
80 DBG("Serializing uprobe event rule.");
81 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, parent
);
83 name_len
= strlen(uprobe
->name
) + 1;
85 uprobe_comm
.name_len
= name_len
;
87 ret
= lttng_dynamic_buffer_append(
88 &payload
->buffer
, &uprobe_comm
, sizeof(uprobe_comm
));
92 ret
= lttng_dynamic_buffer_append(
93 &payload
->buffer
, uprobe
->name
, name_len
);
98 size_before_probe
= payload
->buffer
.size
;
100 /* This serialize return the size taken in the buffer. */
101 ret
= lttng_userspace_probe_location_serialize(
102 uprobe
->location
, payload
);
107 /* Update the header regarding the probe size. */
108 header
= (struct lttng_event_rule_userspace_probe_comm
109 *) ((char *) payload
->buffer
.data
+
111 header
->location_len
= payload
->buffer
.size
- size_before_probe
;
119 static bool lttng_event_rule_userspace_probe_is_equal(const struct lttng_event_rule
*_a
,
120 const struct lttng_event_rule
*_b
)
122 bool is_equal
= false;
123 struct lttng_event_rule_userspace_probe
*a
, *b
;
125 a
= container_of(_a
, struct lttng_event_rule_userspace_probe
, parent
);
126 b
= container_of(_b
, struct lttng_event_rule_userspace_probe
, parent
);
128 /* uprobe is invalid if this is not true. */
131 if (strcmp(a
->name
, b
->name
)) {
137 is_equal
= lttng_userspace_probe_location_is_equal(
138 a
->location
, b
->location
);
143 static enum lttng_error_code
lttng_event_rule_userspace_probe_generate_filter_bytecode(
144 struct lttng_event_rule
*rule
,
145 const struct lttng_credentials
*creds
)
151 static const char *lttng_event_rule_userspace_probe_get_filter(
152 const struct lttng_event_rule
*rule
)
158 static const struct lttng_bytecode
*
159 lttng_event_rule_userspace_probe_get_filter_bytecode(const struct lttng_event_rule
*rule
)
165 static enum lttng_event_rule_generate_exclusions_status
166 lttng_event_rule_userspace_probe_generate_exclusions(const struct lttng_event_rule
*rule
,
167 struct lttng_event_exclusion
**exclusions
)
171 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
175 lttng_event_rule_userspace_probe_hash(
176 const struct lttng_event_rule
*rule
)
179 struct lttng_event_rule_userspace_probe
*urule
=
180 container_of(rule
, typeof(*urule
), parent
);
182 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE
,
184 hash
^= hash_key_str(urule
->name
, lttng_ht_seed
);
185 hash
^= lttng_userspace_probe_location_hash(urule
->location
);
190 struct lttng_event_rule
*lttng_event_rule_userspace_probe_create(void)
192 struct lttng_event_rule
*rule
= NULL
;
193 struct lttng_event_rule_userspace_probe
*urule
;
195 urule
= zmalloc(sizeof(struct lttng_event_rule_userspace_probe
));
200 rule
= &urule
->parent
;
201 lttng_event_rule_init(&urule
->parent
, LTTNG_EVENT_RULE_TYPE_USERSPACE_PROBE
);
202 urule
->parent
.validate
= lttng_event_rule_userspace_probe_validate
;
203 urule
->parent
.serialize
= lttng_event_rule_userspace_probe_serialize
;
204 urule
->parent
.equal
= lttng_event_rule_userspace_probe_is_equal
;
205 urule
->parent
.destroy
= lttng_event_rule_userspace_probe_destroy
;
206 urule
->parent
.generate_filter_bytecode
=
207 lttng_event_rule_userspace_probe_generate_filter_bytecode
;
208 urule
->parent
.get_filter
= lttng_event_rule_userspace_probe_get_filter
;
209 urule
->parent
.get_filter_bytecode
=
210 lttng_event_rule_userspace_probe_get_filter_bytecode
;
211 urule
->parent
.generate_exclusions
=
212 lttng_event_rule_userspace_probe_generate_exclusions
;
213 urule
->parent
.hash
= lttng_event_rule_userspace_probe_hash
;
220 ssize_t
lttng_event_rule_userspace_probe_create_from_payload(
221 struct lttng_payload_view
*view
,
222 struct lttng_event_rule
**_event_rule
)
224 ssize_t ret
, offset
= 0;
225 const struct lttng_event_rule_userspace_probe_comm
*uprobe_comm
;
227 struct lttng_buffer_view current_buffer_view
;
228 struct lttng_event_rule
*rule
= NULL
;
229 struct lttng_userspace_probe_location
*location
;
230 struct lttng_event_rule_userspace_probe
*uprobe
;
231 enum lttng_event_rule_status status
;
238 current_buffer_view
= lttng_buffer_view_from_view(
239 &view
->buffer
, offset
, sizeof(*uprobe_comm
));
240 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
241 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
246 uprobe_comm
= (typeof(uprobe_comm
)) current_buffer_view
.data
;
247 rule
= lttng_event_rule_userspace_probe_create();
249 ERR("Failed to create event rule uprobe");
254 /* Skip to payload. */
255 offset
+= current_buffer_view
.size
;
258 current_buffer_view
= lttng_buffer_view_from_view(
259 &view
->buffer
, offset
, uprobe_comm
->name_len
);
260 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
265 name
= current_buffer_view
.data
;
266 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, name
,
267 uprobe_comm
->name_len
)) {
272 /* Skip after the name. */
273 offset
+= uprobe_comm
->name_len
;
275 /* Map the location. */
277 struct lttng_payload_view current_payload_view
=
278 lttng_payload_view_from_view(view
, offset
,
279 uprobe_comm
->location_len
);
281 if (!lttng_payload_view_is_valid(¤t_payload_view
)) {
282 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain location");
287 ret
= lttng_userspace_probe_location_create_from_payload(
288 ¤t_payload_view
, &location
);
295 assert(ret
== uprobe_comm
->location_len
);
297 /* Skip after the location. */
298 offset
+= uprobe_comm
->location_len
;
300 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, parent
);
301 uprobe
->location
= location
;
303 status
= lttng_event_rule_userspace_probe_set_name(rule
, name
);
304 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
309 if (!lttng_event_rule_userspace_probe_validate(rule
)) {
318 lttng_event_rule_destroy(rule
);
322 enum lttng_event_rule_status
lttng_event_rule_userspace_probe_set_location(
323 struct lttng_event_rule
*rule
,
324 const struct lttng_userspace_probe_location
*location
)
326 struct lttng_userspace_probe_location
*location_copy
= NULL
;
327 struct lttng_event_rule_userspace_probe
*uprobe
;
328 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
330 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
331 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
335 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, parent
);
336 location_copy
= lttng_userspace_probe_location_copy(location
);
337 if (!location_copy
) {
338 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
342 if (uprobe
->location
) {
343 lttng_userspace_probe_location_destroy(uprobe
->location
);
346 uprobe
->location
= location_copy
;
347 location_copy
= NULL
;
349 lttng_userspace_probe_location_destroy(location_copy
);
353 enum lttng_event_rule_status
lttng_event_rule_userspace_probe_get_location(
354 const struct lttng_event_rule
*rule
,
355 const struct lttng_userspace_probe_location
**location
)
357 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
359 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
360 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
364 *location
= lttng_event_rule_userspace_probe_get_location_mutable(rule
);
366 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
375 struct lttng_userspace_probe_location
*
376 lttng_event_rule_userspace_probe_get_location_mutable(
377 const struct lttng_event_rule
*rule
)
379 struct lttng_event_rule_userspace_probe
*uprobe
;
382 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, parent
);
384 return uprobe
->location
;
387 enum lttng_event_rule_status
lttng_event_rule_userspace_probe_set_name(
388 struct lttng_event_rule
*rule
, const char *name
)
390 char *name_copy
= NULL
;
391 struct lttng_event_rule_userspace_probe
*uprobe
;
392 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
394 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
||
396 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
400 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, parent
);
401 name_copy
= strdup(name
);
403 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
411 uprobe
->name
= name_copy
;
417 enum lttng_event_rule_status
lttng_event_rule_userspace_probe_get_name(
418 const struct lttng_event_rule
*rule
, const char **name
)
420 struct lttng_event_rule_userspace_probe
*uprobe
;
421 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
423 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
424 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
428 uprobe
= container_of(rule
, struct lttng_event_rule_userspace_probe
, parent
);
430 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
434 *name
= uprobe
->name
;