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/runas.h>
12 #include <lttng/event-rule/event-rule-internal.h>
13 #include <lttng/event-rule/uprobe-internal.h>
14 #include <lttng/userspace-probe-internal.h>
16 #define IS_UPROBE_EVENT_RULE(rule) \
17 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_UPROBE)
19 static void lttng_event_rule_uprobe_destroy(struct lttng_event_rule
*rule
)
21 struct lttng_event_rule_uprobe
*uprobe
;
23 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
25 lttng_userspace_probe_location_destroy(uprobe
->location
);
30 static bool lttng_event_rule_uprobe_validate(
31 const struct lttng_event_rule
*rule
)
34 struct lttng_event_rule_uprobe
*uprobe
;
40 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
44 ERR("Invalid uprobe event rule: a pattern must be set.");
48 if (!uprobe
->location
) {
49 ERR("Invalid uprobe event rule: a location must be set.");
53 /* TODO should we validate the probe location? */
60 static int lttng_event_rule_uprobe_serialize(
61 const struct lttng_event_rule
*rule
,
62 struct lttng_dynamic_buffer
*buf
,
66 size_t name_len
, header_offset
, size_before_probe
;
67 struct lttng_event_rule_uprobe
*uprobe
;
68 struct lttng_event_rule_uprobe_comm uprobe_comm
= {0};
69 struct lttng_event_rule_uprobe_comm
*header
;
71 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
)) {
76 header_offset
= buf
->size
;
78 DBG("Serializing uprobe event rule");
79 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
81 name_len
= strlen(uprobe
->name
) + 1;
83 uprobe_comm
.name_len
= name_len
;
85 ret
= lttng_dynamic_buffer_append(
86 buf
, &uprobe_comm
, sizeof(uprobe_comm
));
90 ret
= lttng_dynamic_buffer_append(buf
, uprobe
->name
, name_len
);
95 size_before_probe
= buf
->size
;
97 /* This serialize return the size taken in the buffer */
98 /* TODO: should all serialize standardise on this? */
99 ret
= lttng_userspace_probe_location_serialize(
100 uprobe
->location
, buf
, fd_to_send
);
105 /* Update the header regarding the probe size */
106 header
= (struct lttng_event_rule_uprobe_comm
*) ((char *) buf
->data
+
108 header
->location_len
= buf
->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_populate(
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_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(struct lttng_event_rule
*rule
)
168 struct lttng_event_rule
*lttng_event_rule_uprobe_create()
170 struct lttng_event_rule_uprobe
*rule
;
172 rule
= zmalloc(sizeof(struct lttng_event_rule_uprobe
));
177 lttng_event_rule_init(&rule
->parent
, LTTNG_EVENT_RULE_TYPE_UPROBE
);
178 rule
->parent
.validate
= lttng_event_rule_uprobe_validate
;
179 rule
->parent
.serialize
= lttng_event_rule_uprobe_serialize
;
180 rule
->parent
.equal
= lttng_event_rule_uprobe_is_equal
;
181 rule
->parent
.destroy
= lttng_event_rule_uprobe_destroy
;
182 rule
->parent
.populate
= lttng_event_rule_uprobe_populate
;
183 rule
->parent
.get_filter
= lttng_event_rule_uprobe_get_filter
;
184 rule
->parent
.get_filter_bytecode
=
185 lttng_event_rule_uprobe_get_filter_bytecode
;
186 rule
->parent
.generate_exclusions
=
187 lttng_event_rule_uprobe_generate_exclusions
;
188 return &rule
->parent
;
192 ssize_t
lttng_event_rule_uprobe_create_from_buffer(
193 const struct lttng_buffer_view
*view
,
194 struct lttng_event_rule
**_event_rule
)
196 ssize_t ret
, offset
= 0;
197 const struct lttng_event_rule_uprobe_comm
*uprobe_comm
;
199 struct lttng_buffer_view current_view
;
200 struct lttng_event_rule
*rule
= NULL
;
201 struct lttng_userspace_probe_location
*location
;
202 struct lttng_event_rule_uprobe
*uprobe
;
209 if (view
->size
< sizeof(*uprobe_comm
)) {
210 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
215 current_view
= lttng_buffer_view_from_view(
216 view
, offset
, sizeof(*uprobe_comm
));
217 uprobe_comm
= (typeof(uprobe_comm
)) current_view
.data
;
224 rule
= lttng_event_rule_uprobe_create();
226 ERR("Failed to create event rule uprobe");
231 /* Skip to payload */
232 offset
+= current_view
.size
;
235 current_view
= lttng_buffer_view_from_view(
236 view
, offset
, uprobe_comm
->name_len
);
237 name
= current_view
.data
;
243 if (uprobe_comm
->name_len
== 1 ||
244 name
[uprobe_comm
->name_len
- 1] != '\0' ||
245 strlen(name
) != uprobe_comm
->name_len
- 1) {
247 * Check that the name is not NULL, is NULL-terminated, and
248 * does not contain a NULL before the last byte.
254 /* Skip after the name */
255 offset
+= uprobe_comm
->name_len
;
257 /* Map the location */
258 current_view
= lttng_buffer_view_from_view(
259 view
, offset
, uprobe_comm
->location_len
);
260 ret
= lttng_userspace_probe_location_create_from_buffer(
261 ¤t_view
, &location
);
267 assert(ret
== uprobe_comm
->location_len
);
269 /* Skip after the location */
270 offset
+= uprobe_comm
->location_len
;
272 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
273 uprobe
->location
= location
;
275 (void) lttng_event_rule_uprobe_set_name(rule
, name
);
277 if (!lttng_event_rule_uprobe_validate(rule
)) {
286 lttng_event_rule_destroy(rule
);
290 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_location(
291 struct lttng_event_rule
*rule
,
292 const struct lttng_userspace_probe_location
*location
)
294 struct lttng_userspace_probe_location
*location_copy
= NULL
;
295 struct lttng_event_rule_uprobe
*uprobe
;
296 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
298 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
299 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
303 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
304 location_copy
= lttng_userspace_probe_location_copy(location
);
305 if (!location_copy
) {
306 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
310 if (uprobe
->location
) {
311 lttng_userspace_probe_location_destroy(uprobe
->location
);
314 uprobe
->location
= location_copy
;
315 location_copy
= NULL
;
317 lttng_userspace_probe_location_destroy(location_copy
);
321 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_location(
322 const struct lttng_event_rule
*rule
,
323 const struct lttng_userspace_probe_location
**location
)
325 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
327 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
328 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
332 *location
= lttng_event_rule_uprobe_get_location_no_const(rule
);
334 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
343 struct lttng_userspace_probe_location
*
344 lttng_event_rule_uprobe_get_location_no_const(
345 const struct lttng_event_rule
*rule
)
347 struct lttng_event_rule_uprobe
*uprobe
;
349 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
351 return uprobe
->location
;
354 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_name(
355 struct lttng_event_rule
*rule
, const char *name
)
357 char *name_copy
= NULL
;
358 struct lttng_event_rule_uprobe
*uprobe
;
359 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
361 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
||
363 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
367 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
368 name_copy
= strdup(name
);
370 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
378 uprobe
->name
= name_copy
;
384 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_name(
385 const struct lttng_event_rule
*rule
, const char **name
)
387 struct lttng_event_rule_uprobe
*uprobe
;
388 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
390 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
391 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
395 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
397 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
401 *name
= uprobe
->name
;