When the captured fields end up taking more than
PIPE_BUF - sizeof(struct lttng_ust_abi_event_notifier_notification) - 1
bytes of space for the msgpack message, the notification append capture
fails.
Currently, the result is that the msgpack buffer will contain a (likely
corrupted) truncated msgpack data.
Handle those overflow errors, and when they are encountered, reset the
msgpack writer position to skip the problematic captured field entirely.
Change-Id: I7ba1bf06aa72512fc73211a1d8ae6823d0e8d7ff
return lttng_msgpack_encode_f64(writer, value);
}
return lttng_msgpack_encode_f64(writer, value);
}
+int lttng_msgpack_save_writer_pos(struct lttng_msgpack_writer *writer, uint8_t **pos)
+{
+ *pos = writer->write_pos;
+ return 0;
+}
+
+int lttng_msgpack_restore_writer_pos(struct lttng_msgpack_writer *writer, uint8_t *pos)
+{
+ writer->write_pos = pos;
+ return 0;
+}
+
void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
uint8_t *buffer, size_t size)
{
void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
uint8_t *buffer, size_t size)
{
int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer)
__attribute__((visibility("hidden")));
int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer)
__attribute__((visibility("hidden")));
+int lttng_msgpack_save_writer_pos(struct lttng_msgpack_writer *writer, uint8_t **pos)
+ __attribute__((visibility("hidden")));
+
+int lttng_msgpack_restore_writer_pos(struct lttng_msgpack_writer *writer, uint8_t *pos)
+ __attribute__((visibility("hidden")));
+
#endif /* _LTTNG_UST_MSGPACK_H */
#endif /* _LTTNG_UST_MSGPACK_H */
-void capture_enum(struct lttng_msgpack_writer *writer,
+int capture_enum(struct lttng_msgpack_writer *writer,
struct lttng_interpreter_output *output)
{
struct lttng_interpreter_output *output)
{
- lttng_msgpack_begin_map(writer, 2);
- lttng_msgpack_write_str(writer, "type");
- lttng_msgpack_write_str(writer, "enum");
- lttng_msgpack_write_str(writer, "value");
+ ret = lttng_msgpack_begin_map(writer, 2);
+ if (ret) {
+ goto end;
+ }
+ ret = lttng_msgpack_write_str(writer, "type");
+ if (ret) {
+ goto end;
+ }
+ ret = lttng_msgpack_write_str(writer, "enum");
+ if (ret) {
+ goto end;
+ }
+ ret = lttng_msgpack_write_str(writer, "value");
+ if (ret) {
+ goto end;
+ }
switch (output->type) {
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
switch (output->type) {
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
- lttng_msgpack_write_signed_integer(writer, output->u.s);
+ ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
+ if (ret) {
+ goto end;
+ }
break;
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
break;
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
- lttng_msgpack_write_signed_integer(writer, output->u.u);
+ ret = lttng_msgpack_write_signed_integer(writer, output->u.u);
+ if (ret) {
+ goto end;
+ }
+ CRIT("Unknown enum output type\n");
+ ret = -1;
+ goto end;
- lttng_msgpack_end_map(writer);
+ ret = lttng_msgpack_end_map(writer);
+end:
+ return ret;
+ CRIT("Unknown sequence element size\n");
+ value = 0;
+ CRIT("Unknown sequence element size\n");
+ value = 0;
-void capture_sequence(struct lttng_msgpack_writer *writer,
+int capture_sequence(struct lttng_msgpack_writer *writer,
struct lttng_interpreter_output *output)
{
const struct lttng_ust_type_integer *integer_type;
const struct lttng_ust_type_common *nested_type;
uint8_t *ptr;
bool signedness;
struct lttng_interpreter_output *output)
{
const struct lttng_ust_type_integer *integer_type;
const struct lttng_ust_type_common *nested_type;
uint8_t *ptr;
bool signedness;
- int i;
-
- lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
+ ret = lttng_msgpack_begin_array(writer, output->u.sequence.nr_elem);
+ if (ret) {
+ goto end;
+ }
ptr = (uint8_t *) output->u.sequence.ptr;
nested_type = output->u.sequence.nested_type;
switch (nested_type->type) {
ptr = (uint8_t *) output->u.sequence.ptr;
nested_type = output->u.sequence.nested_type;
switch (nested_type->type) {
integer_type = lttng_ust_get_type_integer(lttng_ust_get_type_enum(nested_type)->container_type);
break;
default:
integer_type = lttng_ust_get_type_integer(lttng_ust_get_type_enum(nested_type)->container_type);
break;
default:
- /* Capture of array of non-integer are not supported. */
- abort();
+ CRIT("Capture of array of non-integer are not supported\n");
+ ret = -1;
+ goto end;
}
signedness = integer_type->signedness;
for (i = 0; i < output->u.sequence.nr_elem; i++) {
if (signedness) {
}
signedness = integer_type->signedness;
for (i = 0; i < output->u.sequence.nr_elem; i++) {
if (signedness) {
- lttng_msgpack_write_signed_integer(writer,
+ ret = lttng_msgpack_write_signed_integer(writer,
capture_sequence_element_signed(ptr, integer_type));
} else {
capture_sequence_element_signed(ptr, integer_type));
} else {
- lttng_msgpack_write_unsigned_integer(writer,
+ ret = lttng_msgpack_write_unsigned_integer(writer,
capture_sequence_element_unsigned(ptr, integer_type));
}
capture_sequence_element_unsigned(ptr, integer_type));
}
+ if (ret) {
+ goto end;
+ }
/*
* We assume that alignment is smaller or equal to the size.
/*
* We assume that alignment is smaller or equal to the size.
ptr += (integer_type->size / CHAR_BIT) ;
}
ptr += (integer_type->size / CHAR_BIT) ;
}
- lttng_msgpack_end_array(writer);
+ ret = lttng_msgpack_end_array(writer);
+end:
+ return ret;
-void notification_init(struct lttng_event_notifier_notification *notif,
+int notification_init(struct lttng_event_notifier_notification *notif,
const struct lttng_ust_event_notifier *event_notifier)
{
struct lttng_msgpack_writer *writer = ¬if->writer;
const struct lttng_ust_event_notifier *event_notifier)
{
struct lttng_msgpack_writer *writer = ¬if->writer;
notif->event_notifier_token = event_notifier->priv->parent.user_token;
notif->notification_fd = event_notifier->priv->group->notification_fd;
notif->event_notifier_token = event_notifier->priv->parent.user_token;
notif->notification_fd = event_notifier->priv->group->notification_fd;
lttng_msgpack_writer_init(writer, notif->capture_buf,
CAPTURE_BUFFER_SIZE);
lttng_msgpack_writer_init(writer, notif->capture_buf,
CAPTURE_BUFFER_SIZE);
- lttng_msgpack_begin_array(writer, event_notifier->priv->num_captures);
+ ret = lttng_msgpack_begin_array(writer, event_notifier->priv->num_captures);
+ if (ret) {
+ goto end;
+ }
notif->has_captures = true;
}
notif->has_captures = true;
}
-void notification_append_capture(
+int notification_append_capture(
struct lttng_event_notifier_notification *notif,
struct lttng_interpreter_output *output)
{
struct lttng_msgpack_writer *writer = ¬if->writer;
struct lttng_event_notifier_notification *notif,
struct lttng_interpreter_output *output)
{
struct lttng_msgpack_writer *writer = ¬if->writer;
switch (output->type) {
case LTTNG_INTERPRETER_TYPE_S64:
switch (output->type) {
case LTTNG_INTERPRETER_TYPE_S64:
- lttng_msgpack_write_signed_integer(writer, output->u.s);
+ ret = lttng_msgpack_write_signed_integer(writer, output->u.s);
break;
case LTTNG_INTERPRETER_TYPE_U64:
break;
case LTTNG_INTERPRETER_TYPE_U64:
- lttng_msgpack_write_unsigned_integer(writer, output->u.u);
+ ret = lttng_msgpack_write_unsigned_integer(writer, output->u.u);
break;
case LTTNG_INTERPRETER_TYPE_DOUBLE:
break;
case LTTNG_INTERPRETER_TYPE_DOUBLE:
- lttng_msgpack_write_double(writer, output->u.d);
+ ret = lttng_msgpack_write_double(writer, output->u.d);
break;
case LTTNG_INTERPRETER_TYPE_STRING:
break;
case LTTNG_INTERPRETER_TYPE_STRING:
- lttng_msgpack_write_str(writer, output->u.str.str);
+ ret = lttng_msgpack_write_str(writer, output->u.str.str);
break;
case LTTNG_INTERPRETER_TYPE_SEQUENCE:
break;
case LTTNG_INTERPRETER_TYPE_SEQUENCE:
- capture_sequence(writer, output);
+ ret = capture_sequence(writer, output);
break;
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
break;
case LTTNG_INTERPRETER_TYPE_SIGNED_ENUM:
case LTTNG_INTERPRETER_TYPE_UNSIGNED_ENUM:
- capture_enum(writer, output);
+ ret = capture_enum(writer, output);
+ CRIT("Unknown capture output type\n");
+ ret = -1;
-void notification_append_empty_capture(
+int notification_append_empty_capture(
struct lttng_event_notifier_notification *notif)
{
struct lttng_event_notifier_notification *notif)
{
- lttng_msgpack_write_nil(¬if->writer);
+ return lttng_msgpack_write_nil(¬if->writer);
}
static void record_error(const struct lttng_ust_event_notifier *event_notifier)
}
static void record_error(const struct lttng_ust_event_notifier *event_notifier)
*/
struct lttng_event_notifier_notification notif = {0};
*/
struct lttng_event_notifier_notification notif = {0};
- notification_init(¬if, event_notifier);
+ if (notification_init(¬if, event_notifier)) {
+ record_error(event_notifier);
+ goto end;
+ }
if (caa_unlikely(notif_ctx->eval_capture)) {
struct lttng_ust_bytecode_runtime *capture_bc_runtime;
if (caa_unlikely(notif_ctx->eval_capture)) {
struct lttng_ust_bytecode_runtime *capture_bc_runtime;
cds_list_for_each_entry_rcu(capture_bc_runtime,
&event_notifier->priv->capture_bytecode_runtime_head, node) {
struct lttng_interpreter_output output;
cds_list_for_each_entry_rcu(capture_bc_runtime,
&event_notifier->priv->capture_bytecode_runtime_head, node) {
struct lttng_interpreter_output output;
+ uint8_t *save_pos;
+ int ret;
+ lttng_msgpack_save_writer_pos(¬if.writer, &save_pos);
if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
stack_data, probe_ctx, &output) == LTTNG_UST_BYTECODE_INTERPRETER_OK)
if (capture_bc_runtime->interpreter_func(capture_bc_runtime,
stack_data, probe_ctx, &output) == LTTNG_UST_BYTECODE_INTERPRETER_OK)
- notification_append_capture(¬if, &output);
+ ret = notification_append_capture(¬if, &output);
- notification_append_empty_capture(¬if);
+ ret = notification_append_empty_capture(¬if);
+ if (ret) {
+ /*
+ * On append capture error, skip the field
+ * capture by restoring the msgpack writer
+ * position.
+ */
+ lttng_msgpack_restore_writer_pos(¬if.writer, save_pos);
+ }
* sessiond.
*/
notification_send(¬if, event_notifier);
* sessiond.
*/
notification_send(¬if, event_notifier);