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/payload.h>
12 #include <common/payload-view.h>
13 #include <common/runas.h>
14 #include <lttng/event-rule/event-rule-internal.h>
15 #include <lttng/event-rule/uprobe-internal.h>
16 #include <lttng/userspace-probe-internal.h>
18 #define IS_UPROBE_EVENT_RULE(rule) \
19 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_UPROBE)
21 static void lttng_event_rule_uprobe_destroy(struct lttng_event_rule
*rule
)
23 struct lttng_event_rule_uprobe
*uprobe
;
25 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
27 lttng_userspace_probe_location_destroy(uprobe
->location
);
32 static bool lttng_event_rule_uprobe_validate(
33 const struct lttng_event_rule
*rule
)
36 struct lttng_event_rule_uprobe
*uprobe
;
42 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
46 ERR("Invalid uprobe event rule: a pattern must be set.");
50 if (!uprobe
->location
) {
51 ERR("Invalid uprobe event rule: a location must be set.");
60 static int lttng_event_rule_uprobe_serialize(
61 const struct lttng_event_rule
*rule
,
62 struct lttng_payload
*payload
)
65 size_t name_len
, header_offset
, size_before_probe
;
66 struct lttng_event_rule_uprobe
*uprobe
;
67 struct lttng_event_rule_uprobe_comm uprobe_comm
= {};
68 struct lttng_event_rule_uprobe_comm
*header
;
70 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
)) {
75 header_offset
= payload
->buffer
.size
;
77 DBG("Serializing uprobe event rule.");
78 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
80 name_len
= strlen(uprobe
->name
) + 1;
82 uprobe_comm
.name_len
= name_len
;
84 ret
= lttng_dynamic_buffer_append(
85 &payload
->buffer
, &uprobe_comm
, sizeof(uprobe_comm
));
89 ret
= lttng_dynamic_buffer_append(
90 &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(
99 uprobe
->location
, payload
);
104 /* Update the header regarding the probe size. */
105 header
= (struct lttng_event_rule_uprobe_comm
106 *) ((char *) payload
->buffer
.data
+
108 header
->location_len
= payload
->buffer
.size
- size_before_probe
;
116 static bool lttng_event_rule_uprobe_is_equal(const struct lttng_event_rule
*_a
,
117 const struct lttng_event_rule
*_b
)
119 bool is_equal
= false;
120 struct lttng_event_rule_uprobe
*a
, *b
;
122 a
= container_of(_a
, struct lttng_event_rule_uprobe
, parent
);
123 b
= container_of(_b
, struct lttng_event_rule_uprobe
, parent
);
125 /* uprobe is invalid if this is not true. */
128 if (strcmp(a
->name
, b
->name
)) {
134 is_equal
= lttng_userspace_probe_location_is_equal(
135 a
->location
, b
->location
);
140 static enum lttng_error_code
lttng_event_rule_uprobe_generate_filter_bytecode(
141 struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
147 static const char *lttng_event_rule_uprobe_get_filter(
148 const struct lttng_event_rule
*rule
)
154 static const struct lttng_filter_bytecode
*
155 lttng_event_rule_uprobe_get_filter_bytecode(const struct lttng_event_rule
*rule
)
161 static struct lttng_event_exclusion
*
162 lttng_event_rule_uprobe_generate_exclusions(const struct lttng_event_rule
*rule
)
168 struct lttng_event_rule
*lttng_event_rule_uprobe_create()
170 struct lttng_event_rule
*rule
= NULL
;
171 struct lttng_event_rule_uprobe
*urule
;
173 urule
= zmalloc(sizeof(struct lttng_event_rule_uprobe
));
178 rule
= &urule
->parent
;
179 lttng_event_rule_init(&urule
->parent
, LTTNG_EVENT_RULE_TYPE_UPROBE
);
180 urule
->parent
.validate
= lttng_event_rule_uprobe_validate
;
181 urule
->parent
.serialize
= lttng_event_rule_uprobe_serialize
;
182 urule
->parent
.equal
= lttng_event_rule_uprobe_is_equal
;
183 urule
->parent
.destroy
= lttng_event_rule_uprobe_destroy
;
184 urule
->parent
.generate_filter_bytecode
=
185 lttng_event_rule_uprobe_generate_filter_bytecode
;
186 urule
->parent
.get_filter
= lttng_event_rule_uprobe_get_filter
;
187 urule
->parent
.get_filter_bytecode
=
188 lttng_event_rule_uprobe_get_filter_bytecode
;
189 urule
->parent
.generate_exclusions
=
190 lttng_event_rule_uprobe_generate_exclusions
;
196 ssize_t
lttng_event_rule_uprobe_create_from_payload(
197 struct lttng_payload_view
*view
,
198 struct lttng_event_rule
**_event_rule
)
200 ssize_t ret
, offset
= 0;
201 const struct lttng_event_rule_uprobe_comm
*uprobe_comm
;
203 struct lttng_buffer_view current_buffer_view
;
204 struct lttng_event_rule
*rule
= NULL
;
205 struct lttng_userspace_probe_location
*location
;
206 struct lttng_event_rule_uprobe
*uprobe
;
207 enum lttng_event_rule_status status
;
214 current_buffer_view
= lttng_buffer_view_from_view(
215 &view
->buffer
, offset
, sizeof(*uprobe_comm
));
216 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
217 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
222 uprobe_comm
= (typeof(uprobe_comm
)) current_buffer_view
.data
;
224 rule
= lttng_event_rule_uprobe_create();
226 ERR("Failed to create event rule uprobe");
231 /* Skip to payload. */
232 offset
+= current_buffer_view
.size
;
235 current_buffer_view
= lttng_buffer_view_from_view(
236 &view
->buffer
, offset
, uprobe_comm
->name_len
);
237 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
242 name
= current_buffer_view
.data
;
243 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, name
,
244 uprobe_comm
->name_len
)) {
249 /* Skip after the name. */
250 offset
+= uprobe_comm
->name_len
;
252 /* Map the location. */
254 struct lttng_payload_view current_payload_view
=
255 lttng_payload_view_from_view(view
, offset
,
256 uprobe_comm
->location_len
);
258 if (!lttng_payload_view_is_valid(¤t_payload_view
)) {
259 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain location");
264 ret
= lttng_userspace_probe_location_create_from_payload(
265 ¤t_payload_view
, &location
);
272 assert(ret
== uprobe_comm
->location_len
);
274 /* Skip after the location. */
275 offset
+= uprobe_comm
->location_len
;
277 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
278 uprobe
->location
= location
;
280 status
= lttng_event_rule_uprobe_set_name(rule
, name
);
281 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
286 if (!lttng_event_rule_uprobe_validate(rule
)) {
295 lttng_event_rule_destroy(rule
);
299 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_location(
300 struct lttng_event_rule
*rule
,
301 const struct lttng_userspace_probe_location
*location
)
303 struct lttng_userspace_probe_location
*location_copy
= NULL
;
304 struct lttng_event_rule_uprobe
*uprobe
;
305 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
307 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
308 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
312 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
313 location_copy
= lttng_userspace_probe_location_copy(location
);
314 if (!location_copy
) {
315 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
319 if (uprobe
->location
) {
320 lttng_userspace_probe_location_destroy(uprobe
->location
);
323 uprobe
->location
= location_copy
;
324 location_copy
= NULL
;
326 lttng_userspace_probe_location_destroy(location_copy
);
330 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_location(
331 const struct lttng_event_rule
*rule
,
332 const struct lttng_userspace_probe_location
**location
)
334 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
336 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
337 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
341 *location
= lttng_event_rule_uprobe_get_location_mutable(rule
);
343 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
352 struct lttng_userspace_probe_location
*
353 lttng_event_rule_uprobe_get_location_mutable(
354 const struct lttng_event_rule
*rule
)
356 struct lttng_event_rule_uprobe
*uprobe
;
359 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
361 return uprobe
->location
;
364 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_name(
365 struct lttng_event_rule
*rule
, const char *name
)
367 char *name_copy
= NULL
;
368 struct lttng_event_rule_uprobe
*uprobe
;
369 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
371 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
||
373 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
377 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
378 name_copy
= strdup(name
);
380 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
388 uprobe
->name
= name_copy
;
394 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_name(
395 const struct lttng_event_rule
*rule
, const char **name
)
397 struct lttng_event_rule_uprobe
*uprobe
;
398 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
400 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
401 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
405 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
407 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
411 *name
= uprobe
->name
;