X-Git-Url: http://git.lttng.org./?a=blobdiff_plain;f=src%2Flib%2Fmsgpack%2Fmsgpack.c;h=e7ff1e393cf33ac67625dbed2193edd475569cd1;hb=de34a55bebcd90795129b7c709815bdddd67ac87;hp=f3eca64a654cd5cfcfcc9cfabdaf5fca387e5f46;hpb=9b6ae9f609ebdc4708ef97e307ad2c39d9d94e5b;p=lttng-modules.git diff --git a/src/lib/msgpack/msgpack.c b/src/lib/msgpack/msgpack.c index f3eca64a..e7ff1e39 100644 --- a/src/lib/msgpack/msgpack.c +++ b/src/lib/msgpack/msgpack.c @@ -20,7 +20,6 @@ #define _GNU_SOURCE #define _LGPL_SOURCE -#include #define MSGPACK_FIXSTR_ID_MASK 0xA0 #define MSGPACK_FIXMAP_ID_MASK 0x80 @@ -55,8 +54,10 @@ #include #include #include +#include #include +#include #define INT8_MIN (-128) #define INT16_MIN (-32767-1) @@ -113,6 +114,33 @@ end: 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) { @@ -143,20 +171,6 @@ static inline int lttng_msgpack_append_u64( return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value)); } -static inline int lttng_msgpack_append_f64( - struct lttng_msgpack_writer *writer, double value) -{ - - union { - double d; - uint64_t u; - } u; - - u.d = value; - - return lttng_msgpack_append_u64(writer, u.u); -} - static inline int lttng_msgpack_append_i8( struct lttng_msgpack_writer *writer, int8_t value) { @@ -181,23 +195,6 @@ static inline int lttng_msgpack_append_i64( return lttng_msgpack_append_u64(writer, (uint64_t) value); } -static inline int lttng_msgpack_encode_f64( - struct lttng_msgpack_writer *writer, double value) -{ - int ret; - - ret = lttng_msgpack_append_u8(writer, MSGPACK_FLOAT64_ID); - if (ret) - goto end; - - ret = lttng_msgpack_append_f64(writer, value); - if (ret) - goto end; - -end: - return ret; -} - static inline int lttng_msgpack_encode_fixmap( struct lttng_msgpack_writer *writer, uint8_t count) { @@ -312,6 +309,53 @@ end: 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; @@ -385,6 +429,36 @@ end: 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); @@ -493,11 +567,6 @@ end: return ret; } -int lttng_msgpack_write_double(struct lttng_msgpack_writer *writer, double value) -{ - return lttng_msgpack_encode_f64(writer, value); -} - void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer, uint8_t *buffer, size_t size) {