Fix: event notification capture error handling
[lttng-modules.git] / src / lttng-event-notifier-notification.c
1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * lttng-event-notifier-notification.c
4 *
5 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
6 */
7
8 #include <linux/bug.h>
9
10 #include <lttng/lttng-bytecode.h>
11 #include <lttng/events.h>
12 #include <lttng/msgpack.h>
13 #include <lttng/event-notifier-notification.h>
14 #include <lttng/events-internal.h>
15 #include <lttng/probe-user.h>
16 #include <wrapper/barrier.h>
17
18 /*
19 * The capture buffer size needs to be below 1024 bytes to avoid the
20 * frame to be larger than the 1024 limit enforced by the kernel. If we
21 * ever need to increase it, we will need to use a memory allocation
22 * scheme which allows allocating temporary memory chunks from the
23 * instrumentation sites. This could be done by adapting lttng
24 * tp-mempool to become nmi-safe and lock-free.
25 */
26 #define CAPTURE_BUFFER_SIZE 512
27
28 struct lttng_event_notifier_notification {
29 int notification_fd;
30 uint64_t event_notifier_token;
31 uint8_t capture_buf[CAPTURE_BUFFER_SIZE];
32 struct lttng_msgpack_writer writer;
33 bool has_captures;
34 };
35
36 static
37 int capture_enum(struct lttng_msgpack_writer *writer,
38 struct lttng_interpreter_output *output)
39 {
40 int ret;
41
42 /*
43 * Enums are captured as a map containing 2 key-value pairs. Such as:
44 * - type: enum
45 * value: 177
46 */
47 ret = lttng_msgpack_begin_map(writer, 2);
48 if (ret) {
49 goto end;
50 }
51
52 ret = lttng_msgpack_write_str(writer, "type");
53 if (ret) {
54 goto end;
55 }
56
57 ret = lttng_msgpack_write_str(writer, "enum");
58 if (ret) {
59 goto end;
60 }
61
62 ret = lttng_msgpack_write_str(writer, "value");
63 if (ret) {
64 goto end;
65 }
66
67 switch (output->type) {
68 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
69 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
70 if (ret) {
71 goto end;
72 }
73 break;
74 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
75 ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
76 if (ret) {
77 goto end;
78 }
79 break;
80 default:
81 WARN_ON_ONCE(1);
82 }
83
84 ret = lttng_msgpack_end_map(writer);
85 end:
86 return ret;
87 }
88
89 static
90 int64_t capture_sequence_element_signed(uint8_t *ptr,
91 const struct lttng_kernel_type_integer *type)
92 {
93 int64_t value = 0;
94 unsigned int size = type->size;
95 bool user = type->user;
96 bool byte_order_reversed = type->reverse_byte_order;
97
98 switch (size) {
99 case 8:
100 {
101 int8_t tmp;
102
103 if (user) {
104 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int8_t)))
105 tmp = 0;
106 } else {
107 tmp = *ptr;
108 }
109 value = tmp;
110 break;
111 }
112 case 16:
113 {
114 int16_t tmp;
115
116 if (user) {
117 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int16_t)))
118 tmp = 0;
119 } else {
120 tmp = *(int16_t *) ptr;
121 }
122 if (byte_order_reversed)
123 __swab16s(&tmp);
124 value = tmp;
125 break;
126 }
127 case 32:
128 {
129 int32_t tmp;
130
131 if (user) {
132 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int32_t)))
133 tmp = 0;
134 } else {
135 tmp = *(int32_t *) ptr;
136 }
137 if (byte_order_reversed)
138 __swab32s(&tmp);
139 value = tmp;
140 break;
141 }
142 case 64:
143 {
144 int64_t tmp;
145
146 if (user) {
147 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int64_t)))
148 tmp = 0;
149 } else {
150 tmp = *(int64_t *) ptr;
151 }
152 if (byte_order_reversed)
153 __swab64s(&tmp);
154 value = tmp;
155 break;
156 }
157 default:
158 WARN_ON_ONCE(1);
159 }
160
161 return value;
162 }
163
164 static
165 uint64_t capture_sequence_element_unsigned(uint8_t *ptr,
166 const struct lttng_kernel_type_integer *type)
167 {
168 uint64_t value = 0;
169 unsigned int size = type->size;
170 bool user = type->user;
171 bool byte_order_reversed = type->reverse_byte_order;
172
173 switch (size) {
174 case 8:
175 {
176 uint8_t tmp;
177
178 if (user) {
179 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint8_t)))
180 tmp = 0;
181 } else {
182 tmp = *ptr;
183 }
184 value = tmp;
185 break;
186 }
187 case 16:
188 {
189 uint16_t tmp;
190
191 if (user) {
192 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint16_t)))
193 tmp = 0;
194 } else {
195 tmp = *(uint16_t *) ptr;
196 }
197 if (byte_order_reversed)
198 __swab16s(&tmp);
199 value = tmp;
200 break;
201 }
202 case 32:
203 {
204 uint32_t tmp;
205
206 if (user) {
207 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint32_t)))
208 tmp = 0;
209 } else {
210 tmp = *(uint32_t *) ptr;
211 }
212 if (byte_order_reversed)
213 __swab32s(&tmp);
214 value = tmp;
215 break;
216 }
217 case 64:
218 {
219 uint64_t tmp;
220
221 if (user) {
222 if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint64_t)))
223 tmp = 0;
224 } else {
225 tmp = *(uint64_t *) ptr;
226 }
227 if (byte_order_reversed)
228 __swab64s(&tmp);
229 value = tmp;
230 break;
231 }
232 default:
233 WARN_ON_ONCE(1);
234 }
235
236 return value;
237 }
238
239 int capture_sequence(struct lttng_msgpack_writer *writer,
240 struct lttng_interpreter_output *output)
241 {
242 const struct lttng_kernel_type_integer *integer_type = NULL;
243 const struct lttng_kernel_type_common *nested_type;
244 uint8_t *ptr;
245 bool signedness;
246 int ret, i;
247
248 ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
249 if (ret) {
250 goto end;
251 }
252
253 ptr = (uint8_t *) output->u.sequence.ptr;
254 nested_type = output->u.sequence.nested_type;
255 switch (nested_type->type) {
256 case lttng_kernel_type_integer:
257 integer_type = lttng_kernel_get_type_integer(nested_type);
258 break;
259 case lttng_kernel_type_enum:
260 /* Treat enumeration as an integer. */
261 integer_type = lttng_kernel_get_type_integer(lttng_kernel_get_type_enum(nested_type)->container_type);
262 break;
263 default:
264 /* Capture of array of non-integer are not supported. */
265 WARN_ON_ONCE(1);
266 ret = -1;
267 goto end;
268 }
269 signedness = integer_type->signedness;
270 for (i = 0; i < output->u.sequence.nr_elem; i++) {
271 if (signedness) {
272 ret = lttng_msgpack_write_signed_integer(writer,
273 capture_sequence_element_signed(ptr, integer_type));
274 if (ret) {
275 goto end;
276 }
277 } else {
278 ret = lttng_msgpack_write_unsigned_integer(writer,
279 capture_sequence_element_unsigned(ptr, integer_type));
280 if (ret) {
281 goto end;
282 }
283 }
284
285 /*
286 * We assume that alignment is smaller or equal to the size.
287 * This currently holds true but if it changes in the future,
288 * we will want to change the pointer arithmetics below to
289 * take into account that the next element might be further
290 * away.
291 */
292 WARN_ON_ONCE(integer_type->alignment > integer_type->size);
293
294 /* Size is in number of bits. */
295 ptr += (integer_type->size / CHAR_BIT) ;
296 }
297
298 ret = lttng_msgpack_end_array(writer);
299 end:
300 return ret;
301 }
302
303 static
304 int notification_append_capture(
305 struct lttng_event_notifier_notification *notif,
306 struct lttng_interpreter_output *output)
307 {
308 struct lttng_msgpack_writer *writer = &notif->writer;
309 int ret = 0;
310
311 switch (output->type) {
312 case LTTNG_INTERPRETER_TYPE_S64:
313 ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
314 break;
315 case LTTNG_INTERPRETER_TYPE_U64:
316 ret = lttng_msgpack_write_unsigned_integer(writer, output->u.u);
317 break;
318 case LTTNG_INTERPRETER_TYPE_STRING:
319 if (output->u.str.user) {
320 ret = lttng_msgpack_write_user_str(writer, output->u.str.user_str);
321 } else {
322 ret = lttng_msgpack_write_str(writer, output->u.str.str);
323 }
324 break;
325 case LTTNG_INTERPRETER_TYPE_SEQUENCE:
326 ret = capture_sequence(writer, output);
327 break;
328 case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
329 case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
330 ret = capture_enum(writer, output);
331 break;
332 default:
333 ret = -1;
334 WARN_ON_ONCE(1);
335 }
336 return ret;
337 }
338
339 static
340 int notification_append_empty_capture(
341 struct lttng_event_notifier_notification *notif)
342 {
343 return lttng_msgpack_write_nil(&notif->writer);
344 }
345
346 static
347 int notification_init(struct lttng_event_notifier_notification *notif,
348 struct lttng_kernel_event_notifier *event_notifier)
349 {
350 struct lttng_msgpack_writer *writer = &notif->writer;
351 int ret = 0;
352
353 notif->has_captures = false;
354
355 if (event_notifier->priv->num_captures > 0) {
356 lttng_msgpack_writer_init(writer, notif->capture_buf,
357 CAPTURE_BUFFER_SIZE);
358
359 ret = lttng_msgpack_begin_array(writer, event_notifier->priv->num_captures);
360 if (ret) {
361 goto end;
362 }
363
364 notif->has_captures = true;
365 }
366
367 end:
368 return ret;
369 }
370
371 static
372 void record_error(struct lttng_kernel_event_notifier *event_notifier)
373 {
374
375 struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group;
376 struct lttng_counter *error_counter;
377 size_t dimension_index[1];
378 int ret;
379
380 /*
381 * lttng_smp_load_acquire paired with lttng_smp_store_release orders
382 * creation of the error counter and setting error_counter_len
383 * before the error_counter is used.
384 */
385 error_counter = lttng_smp_load_acquire(&event_notifier_group->error_counter);
386 /* This group may not have an error counter attached to it. */
387 if (!error_counter)
388 return;
389
390 dimension_index[0] = event_notifier->priv->error_counter_index;
391
392 ret = error_counter->ops->counter_add(error_counter->counter,
393 dimension_index, 1);
394 if (ret)
395 WARN_ON_ONCE(1);
396 }
397
398 static
399 void notification_send(struct lttng_event_notifier_notification *notif,
400 struct lttng_kernel_event_notifier *event_notifier)
401 {
402 struct lttng_event_notifier_group *event_notifier_group = event_notifier->priv->group;
403 struct lttng_kernel_ring_buffer_ctx ctx;
404 struct lttng_kernel_abi_event_notifier_notification kernel_notif;
405 size_t capture_buffer_content_len, reserve_size;
406 int ret;
407
408 reserve_size = sizeof(kernel_notif);
409 kernel_notif.token = event_notifier->priv->parent.user_token;
410
411 if (notif->has_captures) {
412 capture_buffer_content_len = notif->writer.write_pos - notif->writer.buffer;
413 } else {
414 capture_buffer_content_len = 0;
415 }
416
417 WARN_ON_ONCE(capture_buffer_content_len > CAPTURE_BUFFER_SIZE);
418
419 reserve_size += capture_buffer_content_len;
420 kernel_notif.capture_buf_size = capture_buffer_content_len;
421
422 lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, reserve_size,
423 lttng_alignof(kernel_notif), NULL);
424 ret = event_notifier_group->ops->event_reserve(&ctx);
425 if (ret < 0) {
426 record_error(event_notifier);
427 return;
428 }
429
430 /* Write the notif structure. */
431 event_notifier_group->ops->event_write(&ctx, &kernel_notif,
432 sizeof(kernel_notif), lttng_alignof(kernel_notif));
433
434 /*
435 * Write the capture buffer. No need to realigned as the below is a raw
436 * char* buffer.
437 */
438 event_notifier_group->ops->event_write(&ctx, &notif->capture_buf,
439 capture_buffer_content_len, 1);
440
441 event_notifier_group->ops->event_commit(&ctx);
442 irq_work_queue(&event_notifier_group->wakeup_pending);
443 }
444
445 void lttng_event_notifier_notification_send(struct lttng_kernel_event_notifier *event_notifier,
446 const char *stack_data,
447 struct lttng_kernel_probe_ctx *probe_ctx,
448 struct lttng_kernel_notification_ctx *notif_ctx)
449 {
450 struct lttng_event_notifier_notification notif = { 0 };
451
452 if (unlikely(!READ_ONCE(event_notifier->parent.enabled)))
453 return;
454
455 if (notification_init(&notif, event_notifier)) {
456 record_error(event_notifier);
457 goto end;
458 }
459
460 if (unlikely(notif_ctx->eval_capture)) {
461 struct lttng_kernel_bytecode_runtime *capture_bc_runtime;
462
463 /*
464 * Iterate over all the capture bytecodes. If the interpreter
465 * functions returns successfully, append the value of the
466 * `output` parameter to the capture buffer. If the interpreter
467 * fails, append an empty capture to the buffer.
468 */
469 list_for_each_entry_rcu(capture_bc_runtime,
470 &event_notifier->priv->capture_bytecode_runtime_head, node) {
471 struct lttng_interpreter_output output;
472 uint8_t *save_pos;
473 int ret;
474
475 lttng_msgpack_save_writer_pos(&notif.writer, &save_pos);
476 if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
477 stack_data, probe_ctx, &output) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK)
478 ret = notification_append_capture(&notif, &output);
479 else
480 ret = notification_append_empty_capture(&notif);
481 if (ret) {
482 /*
483 * On append capture error, skip the field
484 * capture by restoring the msgpack writer
485 * position.
486 */
487 lttng_msgpack_restore_writer_pos(&notif.writer, save_pos);
488 }
489 }
490 }
491
492 /*
493 * Send the notification (including the capture buffer) to the
494 * sessiond.
495 */
496 notification_send(&notif, event_notifier);
497 end:
498 return;
499 }
This page took 0.03996 seconds and 5 git commands to generate.