#include <asm/byteorder.h>
#include <lttng/msgpack.h>
+#include <lttng/probe-user.h>
#define INT8_MIN (-128)
#define INT16_MIN (-32767-1)
return ret;
}
+static inline int lttng_msgpack_append_user_buffer(
+ struct lttng_msgpack_writer *writer,
+ const uint8_t __user *ubuf,
+ size_t length)
+{
+ int ret = 0;
+
+ lttng_msgpack_assert(ubuf);
+
+ /* Ensure we are not trying to write after the end of the buffer. */
+ if (writer->write_pos + length > writer->end_write_pos) {
+ ret = -1;
+ goto end;
+ }
+
+ if (lttng_copy_from_user_check_nofault(writer->write_pos, ubuf, length)) {
+ /*
+ * After a successful strlen user, a page fault on copy is handled by
+ * considering the string as empty, returning a success.
+ */
+ goto end;
+ }
+ writer->write_pos += length;
+end:
+ return ret;
+}
+
static inline int lttng_msgpack_append_u8(
struct lttng_msgpack_writer *writer, uint8_t value)
{
return ret;
}
+static inline int lttng_msgpack_encode_user_fixstr(
+ struct lttng_msgpack_writer *writer,
+ const char __user *ustr,
+ uint8_t len)
+{
+ int ret;
+
+ lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
+
+ ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
+ if (ret)
+ goto end;
+
+ ret = lttng_msgpack_append_user_buffer(writer, (uint8_t __user *) ustr, len);
+ if (ret)
+ goto end;
+
+end:
+ return ret;
+}
+
+static inline int lttng_msgpack_encode_user_str16(
+ struct lttng_msgpack_writer *writer,
+ const char __user *ustr,
+ uint16_t len)
+{
+ int ret;
+
+ lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
+
+ ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
+ if (ret)
+ goto end;
+
+ ret = lttng_msgpack_append_u16(writer, len);
+ if (ret)
+ goto end;
+
+ ret = lttng_msgpack_append_user_buffer(writer, (uint8_t __user *) ustr, len);
+ if (ret)
+ goto end;
+
+end:
+ return ret;
+}
+
+
int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count)
{
int ret;
return ret;
}
+/*
+ * Provide the same behavior on lttng_strlen_user_inatomic page fault as the
+ * lttng ring buffer: truncate the last string character.
+ */
+int lttng_msgpack_write_user_str(struct lttng_msgpack_writer *writer,
+ const char __user *ustr)
+{
+ int ret;
+ size_t length = max_t(size_t, lttng_strlen_user_inatomic(ustr), 1);
+
+ if (length >= (1 << 16)) {
+ ret = -1;
+ goto end;
+ }
+
+ /*
+ * Handle empty string and strlen user page fault as empty string.
+ */
+ if (length == 1)
+ return lttng_msgpack_write_str(writer, "");
+
+ if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
+ ret = lttng_msgpack_encode_user_fixstr(writer, ustr, length);
+ else
+ ret = lttng_msgpack_encode_user_str16(writer, ustr, length);
+
+end:
+ return ret;
+}
+
int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer)
{
return lttng_msgpack_append_u8(writer, MSGPACK_NIL_ID);