2 * Copyright (C) 2019 - Jonathan Rajotte-Julien <jonathan.rajotte-julien@efficios.com>
4 * This library is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License, version 2.1 only,
6 * as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library; if not, write to the Free Software Foundation,
15 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <lttng/event-rule/event-rule-internal.h>
19 #include <lttng/event-rule/uprobe-internal.h>
20 #include <lttng/userspace-probe-internal.h>
21 #include <common/macros.h>
22 #include <common/error.h>
23 #include <common/runas.h>
26 #define IS_UPROBE_EVENT_RULE(rule) ( \
27 lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_UPROBE \
31 void lttng_event_rule_uprobe_destroy(struct lttng_event_rule
*rule
)
33 struct lttng_event_rule_uprobe
*uprobe
;
35 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
,
38 lttng_userspace_probe_location_destroy(uprobe
->location
);
44 bool lttng_event_rule_uprobe_validate(
45 const struct lttng_event_rule
*rule
)
48 struct lttng_event_rule_uprobe
*uprobe
;
54 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
,
59 ERR("Invalid uprobe event rule: a pattern must be set.");
63 if (!uprobe
->location
) {
64 ERR("Invalid uprobe event rule: a location must be set.");
68 /* TODO should we validate the probe location? */
76 int lttng_event_rule_uprobe_serialize(
77 const struct lttng_event_rule
*rule
,
78 struct lttng_dynamic_buffer
*buf
,
82 size_t name_len
, header_offset
, size_before_probe
;
83 struct lttng_event_rule_uprobe
*uprobe
;
84 struct lttng_event_rule_uprobe_comm uprobe_comm
= { 0 };
85 struct lttng_event_rule_uprobe_comm
*header
;
87 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
)) {
92 header_offset
= buf
->size
;
94 DBG("Serializing uprobe event rule");
95 uprobe
= container_of(
96 rule
, struct lttng_event_rule_uprobe
, parent
);
98 name_len
= strlen(uprobe
->name
) + 1;
100 uprobe_comm
.name_len
= name_len
;
102 ret
= lttng_dynamic_buffer_append(
103 buf
, &uprobe_comm
, sizeof(uprobe_comm
));
107 ret
= lttng_dynamic_buffer_append(buf
, uprobe
->name
,
113 size_before_probe
= buf
->size
;
115 /* This serialize return the size taken in the buffer */
116 /* TODO: should all serialize standardise on this? */
117 ret
= lttng_userspace_probe_location_serialize(
118 uprobe
->location
, buf
, fd_to_send
);
123 /* Update the header regarding the probe size */
124 header
= (struct lttng_event_rule_uprobe_comm
*) ((char *) buf
->data
+ header_offset
);
125 header
->location_len
= buf
->size
- size_before_probe
;
134 bool lttng_event_rule_uprobe_is_equal(const struct lttng_event_rule
*_a
,
135 const struct lttng_event_rule
*_b
)
137 bool is_equal
= false;
138 struct lttng_event_rule_uprobe
*a
, *b
;
140 a
= container_of(_a
, struct lttng_event_rule_uprobe
, parent
);
141 b
= container_of(_b
, struct lttng_event_rule_uprobe
, parent
);
143 /* uprobe is invalid if this is not true */
146 if (strcmp(a
->name
, b
->name
)) {
152 is_equal
= lttng_userspace_probe_location_is_equal(a
->location
, b
->location
);
158 enum lttng_error_code
lttng_event_rule_uprobe_populate(struct lttng_event_rule
*rule
, uid_t uid
, gid_t gid
)
164 static const char *lttng_event_rule_uprobe_get_filter(
165 const struct lttng_event_rule
*rule
)
171 static const struct lttng_filter_bytecode
*
172 lttng_event_rule_uprobe_get_filter_bytecode(const struct lttng_event_rule
*rule
)
179 struct lttng_event_exclusion
*lttng_event_rule_uprobe_generate_exclusions(struct lttng_event_rule
*rule
)
185 struct lttng_event_rule
*lttng_event_rule_uprobe_create()
187 struct lttng_event_rule_uprobe
*rule
;
189 rule
= zmalloc(sizeof(struct lttng_event_rule_uprobe
));
194 lttng_event_rule_init(&rule
->parent
, LTTNG_EVENT_RULE_TYPE_UPROBE
);
195 rule
->parent
.validate
= lttng_event_rule_uprobe_validate
;
196 rule
->parent
.serialize
= lttng_event_rule_uprobe_serialize
;
197 rule
->parent
.equal
= lttng_event_rule_uprobe_is_equal
;
198 rule
->parent
.destroy
= lttng_event_rule_uprobe_destroy
;
199 rule
->parent
.populate
= lttng_event_rule_uprobe_populate
;
200 rule
->parent
.get_filter
= lttng_event_rule_uprobe_get_filter
;
201 rule
->parent
.get_filter_bytecode
= lttng_event_rule_uprobe_get_filter_bytecode
;
202 rule
->parent
.generate_exclusions
= lttng_event_rule_uprobe_generate_exclusions
;
203 return &rule
->parent
;
207 ssize_t
lttng_event_rule_uprobe_create_from_buffer(
208 const struct lttng_buffer_view
*view
,
209 struct lttng_event_rule
**_event_rule
)
211 ssize_t ret
, offset
= 0;
212 const struct lttng_event_rule_uprobe_comm
*uprobe_comm
;
214 struct lttng_buffer_view current_view
;
215 struct lttng_event_rule
*rule
= NULL
;
216 struct lttng_userspace_probe_location
*location
;
217 struct lttng_event_rule_uprobe
*uprobe
;
224 if (view
->size
< sizeof(*uprobe_comm
)) {
225 ERR("Failed to initialize from malformed event rule uprobe: buffer too short to contain header");
230 current_view
= lttng_buffer_view_from_view(view
, offset
, sizeof(*uprobe_comm
));
231 uprobe_comm
= (typeof(uprobe_comm
)) current_view
.data
;
238 rule
= lttng_event_rule_uprobe_create();
240 ERR("Failed to create event rule uprobe");
245 /* Skip to payload */
246 offset
+= current_view
.size
;
249 current_view
= lttng_buffer_view_from_view(view
, offset
, uprobe_comm
->name_len
);
250 name
= current_view
.data
;
256 if (uprobe_comm
->name_len
== 1 ||
257 name
[uprobe_comm
->name_len
- 1] != '\0' ||
258 strlen(name
) != uprobe_comm
->name_len
- 1) {
260 * Check that the name is not NULL, is NULL-terminated, and
261 * does not contain a NULL before the last byte.
267 /* Skip after the name */
268 offset
+= uprobe_comm
->name_len
;
270 /* Map the location */
271 current_view
= lttng_buffer_view_from_view(view
, offset
, uprobe_comm
->location_len
);
272 ret
= lttng_userspace_probe_location_create_from_buffer(¤t_view
, &location
);
278 assert(ret
== uprobe_comm
->location_len
);
280 /* Skip after the location */
281 offset
+= uprobe_comm
->location_len
;
283 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
, parent
);
284 uprobe
->location
= location
;
286 (void) lttng_event_rule_uprobe_set_name(rule
, name
);
288 if (!lttng_event_rule_uprobe_validate(rule
)) {
297 lttng_event_rule_destroy(rule
);
301 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_location(
302 struct lttng_event_rule
*rule
,
303 const struct lttng_userspace_probe_location
*location
)
305 struct lttng_userspace_probe_location
*location_copy
= NULL
;
306 struct lttng_event_rule_uprobe
*uprobe
;
307 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
309 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
310 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
314 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
,
316 location_copy
= lttng_userspace_probe_location_copy(location
);
317 if (!location_copy
) {
318 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
322 if (uprobe
->location
) {
323 lttng_userspace_probe_location_destroy(uprobe
->location
);
326 uprobe
->location
= location_copy
;
327 location_copy
= NULL
;
329 lttng_userspace_probe_location_destroy(location_copy
);
333 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_location(
334 const struct lttng_event_rule
*rule
,
335 const struct lttng_userspace_probe_location
**location
)
337 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
339 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !location
) {
340 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
344 *location
= lttng_event_rule_uprobe_get_location_no_const(rule
);
346 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
356 struct lttng_userspace_probe_location
*
357 lttng_event_rule_uprobe_get_location_no_const(
358 const struct lttng_event_rule
*rule
)
360 struct lttng_event_rule_uprobe
*uprobe
;
362 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
,
365 return uprobe
->location
;
368 enum lttng_event_rule_status
lttng_event_rule_uprobe_set_name(
369 struct lttng_event_rule
*rule
, const char *name
)
371 char *name_copy
= NULL
;
372 struct lttng_event_rule_uprobe
*uprobe
;
373 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
375 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
||
377 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
381 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
,
383 name_copy
= strdup(name
);
385 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
393 uprobe
->name
= name_copy
;
399 enum lttng_event_rule_status
lttng_event_rule_uprobe_get_name(
400 const struct lttng_event_rule
*rule
, const char **name
)
402 struct lttng_event_rule_uprobe
*uprobe
;
403 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
405 if (!rule
|| !IS_UPROBE_EVENT_RULE(rule
) || !name
) {
406 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
410 uprobe
= container_of(rule
, struct lttng_event_rule_uprobe
,
413 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
417 *name
= uprobe
->name
;