X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Flttng-event-notifier-notification.c;h=7d345acc8be648f7ab3719fbaed7a63b09b908cd;hb=b3ab29505fe0ffb03ebb5098c0257e2c28bd08e4;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..7d345acc 100644 --- a/src/lttng-event-notifier-notification.c +++ b/src/lttng-event-notifier-notification.c @@ -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,9 +239,11 @@ uint64_t capture_sequence_element_unsigned(uint8_t *ptr, } default: WARN_ON_ONCE(1); + return -1; } - return value; + *_value = value; + return 0; } int capture_sequence(struct lttng_msgpack_writer *writer, @@ -269,14 +279,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; } @@ -442,20 +462,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 +501,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; }