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>
18 #include <lttng/constant.h>
19 #include <lttng/event-rule/event-rule-internal.h>
20 #include <lttng/event-rule/kernel-probe-internal.h>
21 #include <lttng/kernel-probe.h>
22 #include <lttng/kernel-probe-internal.h>
25 #define IS_KPROBE_EVENT_RULE(rule) \
26 (lttng_event_rule_get_type(rule) == LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE)
28 #if (LTTNG_SYMBOL_NAME_LEN == 256)
29 #define LTTNG_SYMBOL_NAME_LEN_SCANF_IS_A_BROKEN_API "255"
32 static void lttng_event_rule_kernel_probe_destroy(struct lttng_event_rule
*rule
)
34 struct lttng_event_rule_kernel_probe
*kprobe
;
36 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
38 lttng_kernel_probe_location_destroy(kprobe
->location
);
43 static bool lttng_event_rule_kernel_probe_validate(
44 const struct lttng_event_rule
*rule
)
47 struct lttng_event_rule_kernel_probe
*kprobe
;
53 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
57 ERR("Invalid name event rule: a name must be set.");
62 if(!kprobe
->location
) {
63 ERR("Invalid name event rule: a location must be set.");
72 static int lttng_event_rule_kernel_probe_serialize(
73 const struct lttng_event_rule
*rule
,
74 struct lttng_payload
*payload
)
77 size_t name_len
, header_offset
, size_before_location
;
78 struct lttng_event_rule_kernel_probe
*kprobe
;
79 struct lttng_event_rule_kernel_probe_comm kprobe_comm
;
80 struct lttng_event_rule_kernel_probe_comm
*header
;
82 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
)) {
87 header_offset
= payload
->buffer
.size
;
89 DBG("Serializing kprobe event rule.");
90 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
92 name_len
= strlen(kprobe
->name
) + 1;
93 kprobe_comm
.name_len
= name_len
;
95 ret
= lttng_dynamic_buffer_append(
96 &payload
->buffer
, &kprobe_comm
, sizeof(kprobe_comm
));
101 ret
= lttng_dynamic_buffer_append(&payload
->buffer
, kprobe
->name
, name_len
);
106 size_before_location
= payload
->buffer
.size
;
108 ret
= lttng_kernel_probe_location_serialize(kprobe
->location
, payload
);
113 /* Update the header regarding the probe size. */
114 header
= (struct lttng_event_rule_kernel_probe_comm
*) (
115 (char *) payload
->buffer
.data
+ header_offset
);
116 header
->location_len
= payload
->buffer
.size
- size_before_location
;
124 static bool lttng_event_rule_kernel_probe_is_equal(const struct lttng_event_rule
*_a
,
125 const struct lttng_event_rule
*_b
)
127 bool is_equal
= false;
128 struct lttng_event_rule_kernel_probe
*a
, *b
;
130 a
= container_of(_a
, struct lttng_event_rule_kernel_probe
, parent
);
131 b
= container_of(_b
, struct lttng_event_rule_kernel_probe
, parent
);
134 if (!!a
->name
!= !!b
->name
) {
141 if (strcmp(a
->name
, b
->name
)) {
145 is_equal
= lttng_kernel_probe_location_is_equal(
146 a
->location
, b
->location
);
151 static enum lttng_error_code
lttng_event_rule_kernel_probe_generate_filter_bytecode(
152 struct lttng_event_rule
*rule
,
153 const struct lttng_credentials
*creds
)
159 static const char *lttng_event_rule_kernel_probe_get_filter(
160 const struct lttng_event_rule
*rule
)
166 static const struct lttng_bytecode
*
167 lttng_event_rule_kernel_probe_get_filter_bytecode(const struct lttng_event_rule
*rule
)
173 static enum lttng_event_rule_generate_exclusions_status
174 lttng_event_rule_kernel_probe_generate_exclusions(const struct lttng_event_rule
*rule
,
175 struct lttng_event_exclusion
**exclusions
)
179 return LTTNG_EVENT_RULE_GENERATE_EXCLUSIONS_STATUS_NONE
;
183 lttng_event_rule_kernel_probe_hash(
184 const struct lttng_event_rule
*rule
)
187 struct lttng_event_rule_kernel_probe
*krule
=
188 container_of(rule
, typeof(*krule
), parent
);
190 hash
= hash_key_ulong((void *) LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE
,
192 hash
^= hash_key_str(krule
->name
, lttng_ht_seed
);
193 hash
^= lttng_kernel_probe_location_hash(krule
->location
);
198 struct lttng_event_rule
*lttng_event_rule_kernel_probe_create(void)
200 struct lttng_event_rule
*rule
= NULL
;
201 struct lttng_event_rule_kernel_probe
*krule
;
203 krule
= zmalloc(sizeof(struct lttng_event_rule_kernel_probe
));
208 rule
= &krule
->parent
;
209 lttng_event_rule_init(&krule
->parent
, LTTNG_EVENT_RULE_TYPE_KERNEL_PROBE
);
210 krule
->parent
.validate
= lttng_event_rule_kernel_probe_validate
;
211 krule
->parent
.serialize
= lttng_event_rule_kernel_probe_serialize
;
212 krule
->parent
.equal
= lttng_event_rule_kernel_probe_is_equal
;
213 krule
->parent
.destroy
= lttng_event_rule_kernel_probe_destroy
;
214 krule
->parent
.generate_filter_bytecode
=
215 lttng_event_rule_kernel_probe_generate_filter_bytecode
;
216 krule
->parent
.get_filter
= lttng_event_rule_kernel_probe_get_filter
;
217 krule
->parent
.get_filter_bytecode
=
218 lttng_event_rule_kernel_probe_get_filter_bytecode
;
219 krule
->parent
.generate_exclusions
=
220 lttng_event_rule_kernel_probe_generate_exclusions
;
221 krule
->parent
.hash
= lttng_event_rule_kernel_probe_hash
;
227 ssize_t
lttng_event_rule_kernel_probe_create_from_payload(
228 struct lttng_payload_view
*view
,
229 struct lttng_event_rule
**_event_rule
)
231 ssize_t ret
, offset
= 0;
232 enum lttng_event_rule_status status
;
233 const struct lttng_event_rule_kernel_probe_comm
*kprobe_comm
;
235 struct lttng_buffer_view current_buffer_view
;
236 struct lttng_event_rule
*rule
= NULL
;
237 struct lttng_event_rule_kernel_probe
*kprobe
= NULL
;
238 struct lttng_kernel_probe_location
*location
;
245 current_buffer_view
= lttng_buffer_view_from_view(
246 &view
->buffer
, offset
, sizeof(*kprobe_comm
));
247 if (!lttng_buffer_view_is_valid(¤t_buffer_view
)) {
248 ERR("Failed to initialize from malformed event rule kprobe: buffer too short to contain header.");
253 kprobe_comm
= (typeof(kprobe_comm
)) current_buffer_view
.data
;
255 rule
= lttng_event_rule_kernel_probe_create();
257 ERR("Failed to create event rule kprobe.");
262 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
264 /* Skip to payload */
265 offset
+= current_buffer_view
.size
;
269 struct lttng_payload_view current_payload_view
=
270 lttng_payload_view_from_view(view
, offset
,
271 kprobe_comm
->name_len
);
273 if (!lttng_payload_view_is_valid(¤t_payload_view
)) {
278 name
= current_payload_view
.buffer
.data
;
279 if (!lttng_buffer_view_contains_string(
280 ¤t_payload_view
.buffer
, name
,
281 kprobe_comm
->name_len
)) {
287 /* Skip after the name. */
288 offset
+= kprobe_comm
->name_len
;
290 /* Map the kernel probe location. */
292 struct lttng_payload_view current_payload_view
=
293 lttng_payload_view_from_view(view
, offset
,
294 kprobe_comm
->location_len
);
296 if (!lttng_payload_view_is_valid(¤t_payload_view
)) {
301 ret
= lttng_kernel_probe_location_create_from_payload(
302 ¤t_payload_view
, &location
);
309 if (ret
!= kprobe_comm
->location_len
) {
314 kprobe
->location
= location
;
316 /* Skip after the location */
317 offset
+= kprobe_comm
->location_len
;
319 status
= lttng_event_rule_kernel_probe_set_event_name(rule
, name
);
320 if (status
!= LTTNG_EVENT_RULE_STATUS_OK
) {
321 ERR("Failed to set event rule kprobe name.");
330 lttng_event_rule_destroy(rule
);
334 enum lttng_event_rule_status
lttng_event_rule_kernel_probe_set_location(
335 struct lttng_event_rule
*rule
,
336 const struct lttng_kernel_probe_location
*location
)
338 struct lttng_kernel_probe_location
*location_copy
= NULL
;
339 struct lttng_event_rule_kernel_probe
*kprobe
;
340 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
342 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
) || !location
) {
343 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
347 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
348 location_copy
= lttng_kernel_probe_location_copy(location
);
349 if (!location_copy
) {
350 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
354 if (kprobe
->location
) {
355 lttng_kernel_probe_location_destroy(kprobe
->location
);
358 kprobe
->location
= location_copy
;
359 location_copy
= NULL
;
361 lttng_kernel_probe_location_destroy(location_copy
);
365 enum lttng_event_rule_status
lttng_event_rule_kernel_probe_get_location(
366 const struct lttng_event_rule
*rule
,
367 const struct lttng_kernel_probe_location
**location
)
369 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
370 struct lttng_event_rule_kernel_probe
*kprobe
;
372 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
) || !location
) {
373 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
377 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
378 *location
= kprobe
->location
;
381 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
389 enum lttng_event_rule_status
lttng_event_rule_kernel_probe_set_event_name(
390 struct lttng_event_rule
*rule
, const char *name
)
392 char *name_copy
= NULL
;
393 struct lttng_event_rule_kernel_probe
*kprobe
;
394 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
396 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
) || !name
||
398 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
402 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
403 name_copy
= strdup(name
);
405 status
= LTTNG_EVENT_RULE_STATUS_ERROR
;
411 kprobe
->name
= name_copy
;
417 enum lttng_event_rule_status
lttng_event_rule_kernel_probe_get_event_name(
418 const struct lttng_event_rule
*rule
, const char **name
)
420 struct lttng_event_rule_kernel_probe
*kprobe
;
421 enum lttng_event_rule_status status
= LTTNG_EVENT_RULE_STATUS_OK
;
423 if (!rule
|| !IS_KPROBE_EVENT_RULE(rule
) || !name
) {
424 status
= LTTNG_EVENT_RULE_STATUS_INVALID
;
428 kprobe
= container_of(rule
, struct lttng_event_rule_kernel_probe
, parent
);
430 status
= LTTNG_EVENT_RULE_STATUS_UNSET
;
434 *name
= kprobe
->name
;