X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=src%2Flttng-event-notifier-notification.c;h=29d2d1567b80242182fd2a68cffff05da8cb5f59;hb=435454a76c63eb3f574562aeb8146fba8889b25e;hp=b8f01395c57bf4e7fd3954f555aa26a286acbf7a;hpb=736f2dd654af78b4bce81cf8ba9579370a162a38;p=lttng-modules.git diff --git a/src/lttng-event-notifier-notification.c b/src/lttng-event-notifier-notification.c index b8f01395..29d2d156 100644 --- a/src/lttng-event-notifier-notification.c +++ b/src/lttng-event-notifier-notification.c @@ -5,6 +5,7 @@ * Copyright (C) 2020 Francis Deslauriers */ +#include #include #include @@ -13,7 +14,6 @@ #include #include #include -#include /* * The capture buffer size needs to be below 1024 bytes to avoid the @@ -25,6 +25,8 @@ */ #define CAPTURE_BUFFER_SIZE 512 +#define MSG_WRITE_NIL_LEN 1 + struct lttng_event_notifier_notification { int notification_fd; uint64_t event_notifier_token; @@ -79,6 +81,8 @@ int capture_enum(struct lttng_msgpack_writer *writer, break; default: WARN_ON_ONCE(1); + ret = -1; + goto end; } ret = lttng_msgpack_end_map(writer); @@ -87,8 +91,9 @@ end: } static -int64_t capture_sequence_element_signed(uint8_t *ptr, - const struct lttng_kernel_type_integer *type) +int capture_sequence_element_signed(uint8_t *ptr, + const struct lttng_kernel_type_integer *type, + int64_t *_value) { int64_t value = 0; unsigned int size = type->size; @@ -102,7 +107,7 @@ int64_t capture_sequence_element_signed(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int8_t))) - tmp = 0; + return -1; } else { tmp = *ptr; } @@ -115,7 +120,7 @@ int64_t capture_sequence_element_signed(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int16_t))) - tmp = 0; + return -1; } else { tmp = *(int16_t *) ptr; } @@ -130,7 +135,7 @@ int64_t capture_sequence_element_signed(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int32_t))) - tmp = 0; + return -1; } else { tmp = *(int32_t *) ptr; } @@ -145,7 +150,7 @@ int64_t capture_sequence_element_signed(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(int64_t))) - tmp = 0; + return -1; } else { tmp = *(int64_t *) ptr; } @@ -156,14 +161,17 @@ int64_t capture_sequence_element_signed(uint8_t *ptr, } default: WARN_ON_ONCE(1); + return -1; } - return value; + *_value = value; + return 0; } static -uint64_t capture_sequence_element_unsigned(uint8_t *ptr, - const struct lttng_kernel_type_integer *type) +int capture_sequence_element_unsigned(uint8_t *ptr, + const struct lttng_kernel_type_integer *type, + uint64_t *_value) { uint64_t value = 0; unsigned int size = type->size; @@ -177,7 +185,7 @@ uint64_t capture_sequence_element_unsigned(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint8_t))) - tmp = 0; + return -1; } else { tmp = *ptr; } @@ -190,7 +198,7 @@ uint64_t capture_sequence_element_unsigned(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint16_t))) - tmp = 0; + return -1; } else { tmp = *(uint16_t *) ptr; } @@ -205,7 +213,7 @@ uint64_t capture_sequence_element_unsigned(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint32_t))) - tmp = 0; + return -1; } else { tmp = *(uint32_t *) ptr; } @@ -220,7 +228,7 @@ uint64_t capture_sequence_element_unsigned(uint8_t *ptr, if (user) { if (lttng_copy_from_user_check_nofault(&tmp, ptr, sizeof(uint64_t))) - tmp = 0; + return -1; } else { tmp = *(uint64_t *) ptr; } @@ -231,11 +239,14 @@ uint64_t capture_sequence_element_unsigned(uint8_t *ptr, } default: WARN_ON_ONCE(1); + return -1; } - return value; + *_value = value; + return 0; } +static int capture_sequence(struct lttng_msgpack_writer *writer, struct lttng_interpreter_output *output) { @@ -269,14 +280,24 @@ int capture_sequence(struct lttng_msgpack_writer *writer, signedness = integer_type->signedness; for (i = 0; i < output->u.sequence.nr_elem; i++) { if (signedness) { - ret = lttng_msgpack_write_signed_integer(writer, - capture_sequence_element_signed(ptr, integer_type)); + int64_t v; + + ret = capture_sequence_element_signed(ptr, integer_type, &v); + if (ret) { + goto end; + } + ret = lttng_msgpack_write_signed_integer(writer, v); if (ret) { goto end; } } else { - ret = lttng_msgpack_write_unsigned_integer(writer, - capture_sequence_element_unsigned(ptr, integer_type)); + uint64_t v; + + ret = capture_sequence_element_unsigned(ptr, integer_type, &v); + if (ret) { + goto end; + } + ret = lttng_msgpack_write_unsigned_integer(writer, v); if (ret) { goto end; } @@ -378,11 +399,11 @@ void record_error(struct lttng_kernel_event_notifier *event_notifier) int ret; /* - * lttng_smp_load_acquire paired with lttng_smp_store_release orders - * creation of the error counter and setting error_counter_len - * before the error_counter is used. + * smp_load_acquire paired with smp_store_release orders creation of + * the error counter and setting error_counter_len before the + * error_counter is used. */ - error_counter = lttng_smp_load_acquire(&event_notifier_group->error_counter); + error_counter = smp_load_acquire(&event_notifier_group->error_counter); /* This group may not have an error counter attached to it. */ if (!error_counter) return; @@ -442,20 +463,31 @@ void notification_send(struct lttng_event_notifier_notification *notif, irq_work_queue(&event_notifier_group->wakeup_pending); } +/* + * Validate that the buffer has enough room to hold empty capture fields. + */ +static +bool validate_buffer_len(struct lttng_event_notifier_notification *notif, size_t captures_left) +{ + if (notif->writer.end_write_pos - notif->writer.write_pos < MSG_WRITE_NIL_LEN * captures_left) + return false; + return true; +} + void lttng_event_notifier_notification_send(struct lttng_kernel_event_notifier *event_notifier, const char *stack_data, struct lttng_kernel_probe_ctx *probe_ctx, struct lttng_kernel_notification_ctx *notif_ctx) { struct lttng_event_notifier_notification notif = { 0 }; + size_t captures_left; - if (unlikely(!READ_ONCE(event_notifier->parent.enabled))) - return; + if (notification_init(¬if, event_notifier)) + goto error; - if (notification_init(¬if, event_notifier)) { - record_error(event_notifier); - goto end; - } + captures_left = event_notifier->priv->num_captures; + if (!validate_buffer_len(¬if, captures_left)) + goto error; if (unlikely(notif_ctx->eval_capture)) { struct lttng_kernel_bytecode_runtime *capture_bc_runtime; @@ -470,30 +502,40 @@ void lttng_event_notifier_notification_send(struct lttng_kernel_event_notifier * &event_notifier->priv->capture_bytecode_runtime_head, node) { struct lttng_interpreter_output output; uint8_t *save_pos; - int ret; + int ret = -1; lttng_msgpack_save_writer_pos(¬if.writer, &save_pos); + captures_left--; if (capture_bc_runtime->interpreter_func(capture_bc_runtime, stack_data, probe_ctx, &output) == LTTNG_KERNEL_BYTECODE_INTERPRETER_OK) ret = notification_append_capture(¬if, &output); - else - ret = notification_append_empty_capture(¬if); - if (ret) { + if (ret || !validate_buffer_len(¬if, captures_left)) { /* - * On append capture error, skip the field - * capture by restoring the msgpack writer - * position. + * On append capture error or if the generated + * buffer data would not leave enough room to + * write empty capture fields for the remaining + * fields, skip the field capture by restoring + * the msgpack writer position and writing an + * empty capture field. */ lttng_msgpack_restore_writer_pos(¬if.writer, save_pos); + ret = notification_append_empty_capture(¬if); + WARN_ON_ONCE(ret); } } } + if (notif.has_captures && lttng_msgpack_end_array(¬if.writer)) + goto error; + /* * Send the notification (including the capture buffer) to the * sessiond. */ notification_send(¬if, event_notifier); -end: + return; + +error: + record_error(event_notifier); return; }