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 if (view
->buffer
.size
< sizeof(*uprobe_comm
)) {
215 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header.");
220 current_buffer_view
= lttng_buffer_view_from_view(
221 &view
->buffer
, offset
, sizeof(*uprobe_comm
));
222 uprobe_comm
= (typeof(uprobe_comm
)) current_buffer_view
.data
;
229 rule
= lttng_event_rule_uprobe_create();
231 ERR("Failed to create event rule uprobe.");
236 /* Skip to payload. */
237 offset
+= current_buffer_view
.size
;
240 current_buffer_view
= lttng_buffer_view_from_view(
241 &view
->buffer
, offset
, uprobe_comm
->name_len
);
242 name
= current_buffer_view
.data
;
248 if (!lttng_buffer_view_contains_string(¤t_buffer_view
, name
,
249 uprobe_comm
->name_len
)) {
254 /* Skip after the name. */
255 offset
+= uprobe_comm
->name_len
;
257 /* Map the location. */
258 struct lttng_payload_view current_payload_view
=
259 lttng_payload_view_from_view(view
, offset
,
260 uprobe_comm
->location_len
);
261 ret
= lttng_userspace_probe_location_create_from_payload(
262 ¤t_payload_view
, &location
);
268 assert(ret
== uprobe_comm
->location_len
);
270 /* Skip after the location. */
271 offset
+= uprobe_comm
->location_len
;
273 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
274 uprobe
->location
= location
;
276 status
= lttng_event_rule_uprobe_set_name(rule
, name
);
277 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
282 if (!lttng_event_rule_uprobe_validate(rule
)) {
291 lttng_event_rule_destroy(rule
);
295 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_location(
296 struct lttng_event_rule
*rule
,
297 const struct lttng_userspace_probe_location
*location
)
299 struct lttng_userspace_probe_location
*location_copy
= NULL
;
300 struct lttng_event_rule_uprobe
*uprobe
;
301 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
303 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
304 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
308 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
309 location_copy
= lttng_userspace_probe_location_copy(location
);
310 if (!location_copy
) {
311 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
315 if (uprobe
->location
) {
316 lttng_userspace_probe_location_destroy(uprobe
->location
);
319 uprobe
->location
= location_copy
;
320 location_copy
= NULL
;
322 lttng_userspace_probe_location_destroy(location_copy
);
326 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_location(
327 const struct lttng_event_rule
*rule
,
328 const struct lttng_userspace_probe_location
**location
)
330 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
332 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
333 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
337 *location
= lttng_event_rule_uprobe_get_location_mutable(rule
);
339 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
348 struct lttng_userspace_probe_location
*
349 lttng_event_rule_uprobe_get_location_mutable(
350 const struct lttng_event_rule
*rule
)
352 struct lttng_event_rule_uprobe
*uprobe
;
355 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
357 return uprobe
->location
;
360 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_name(
361 struct lttng_event_rule
*rule
, const char *name
)
363 char *name_copy
= NULL
;
364 struct lttng_event_rule_uprobe
*uprobe
;
365 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
367 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
||
369 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
373 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
374 name_copy
= strdup(name
);
376 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
384 uprobe
->name
= name_copy
;
390 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_name(
391 const struct lttng_event_rule
*rule
, const char **name
)
393 struct lttng_event_rule_uprobe
*uprobe
;
394 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
396 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
397 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
401 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
403 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
407 *name
= uprobe
->name
;