Implement lttng_msgpack_write_user_str
[lttng-modules.git] / src / lib / msgpack / msgpack.c
1 /*
2 * msgpack.c
3 *
4 * Copyright (C) 2020 Francis Deslauriers <francis.deslauriers@efficios.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; only
9 * version 2.1 of the License.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #define _GNU_SOURCE
22 #define _LGPL_SOURCE
23
24 #define MSGPACK_FIXSTR_ID_MASK 0xA0
25 #define MSGPACK_FIXMAP_ID_MASK 0x80
26 #define MSGPACK_FIXARRAY_ID_MASK 0x90
27
28 #define MSGPACK_NIL_ID 0xC0
29 #define MSGPACK_FALSE_ID 0xC2
30 #define MSGPACK_TRUE_ID 0xC3
31 #define MSGPACK_MAP16_ID 0xDE
32 #define MSGPACK_ARRAY16_ID 0xDC
33
34 #define MSGPACK_UINT8_ID 0xCC
35 #define MSGPACK_UINT16_ID 0xCD
36 #define MSGPACK_UINT32_ID 0xCE
37 #define MSGPACK_UINT64_ID 0xCF
38
39 #define MSGPACK_INT8_ID 0xD0
40 #define MSGPACK_INT16_ID 0xD1
41 #define MSGPACK_INT32_ID 0xD2
42 #define MSGPACK_INT64_ID 0xD3
43
44 #define MSGPACK_FLOAT64_ID 0xCB
45 #define MSGPACK_STR16_ID 0xDA
46
47 #define MSGPACK_FIXINT_MAX ((1 << 7) - 1)
48 #define MSGPACK_FIXINT_MIN -(1 << 5)
49 #define MSGPACK_FIXMAP_MAX_COUNT 15
50 #define MSGPACK_FIXARRAY_MAX_COUNT 15
51 #define MSGPACK_FIXSTR_MAX_LENGTH 31
52
53 #ifdef __KERNEL__
54 #include <linux/bug.h>
55 #include <linux/string.h>
56 #include <linux/types.h>
57 #include <asm/byteorder.h>
58
59 #include <lttng/msgpack.h>
60 #include <lttng/probe-user.h>
61
62 #define INT8_MIN (-128)
63 #define INT16_MIN (-32767-1)
64 #define INT32_MIN (-2147483647-1)
65 #define INT8_MAX (127)
66 #define INT16_MAX (32767)
67 #define INT32_MAX (2147483647)
68 #define UINT8_MAX (255)
69 #define UINT16_MAX (65535)
70 #define UINT32_MAX (4294967295U)
71
72 #define byteswap_host_to_be16(_tmp) cpu_to_be16(_tmp)
73 #define byteswap_host_to_be32(_tmp) cpu_to_be32(_tmp)
74 #define byteswap_host_to_be64(_tmp) cpu_to_be64(_tmp)
75
76 #define lttng_msgpack_assert(cond) WARN_ON(!(cond))
77
78 #else /* __KERNEL__ */
79
80 #include <endian.h>
81 #include <stdio.h>
82 #include <string.h>
83
84 #include "msgpack.h"
85
86 #define byteswap_host_to_be16(_tmp) htobe16(_tmp)
87 #define byteswap_host_to_be32(_tmp) htobe32(_tmp)
88 #define byteswap_host_to_be64(_tmp) htobe64(_tmp)
89
90 #define lttng_msgpack_assert(cond) ({ \
91 if (!(cond)) \
92 fprintf(stderr, "Assertion failed. %s:%d\n", __FILE__, __LINE__); \
93 })
94 #endif /* __KERNEL__ */
95
96 static inline int lttng_msgpack_append_buffer(
97 struct lttng_msgpack_writer *writer,
98 const uint8_t *buf,
99 size_t length)
100 {
101 int ret = 0;
102
103 lttng_msgpack_assert(buf);
104
105 /* Ensure we are not trying to write after the end of the buffer. */
106 if (writer->write_pos + length > writer->end_write_pos) {
107 ret = -1;
108 goto end;
109 }
110
111 memcpy(writer->write_pos, buf, length);
112 writer->write_pos += length;
113 end:
114 return ret;
115 }
116
117 static inline int lttng_msgpack_append_user_buffer(
118 struct lttng_msgpack_writer *writer,
119 const uint8_t __user *ubuf,
120 size_t length)
121 {
122 int ret = 0;
123
124 lttng_msgpack_assert(ubuf);
125
126 /* Ensure we are not trying to write after the end of the buffer. */
127 if (writer->write_pos + length > writer->end_write_pos) {
128 ret = -1;
129 goto end;
130 }
131
132 if (lttng_copy_from_user_check_nofault(writer->write_pos, ubuf, length)) {
133 /*
134 * After a successful strlen user, a page fault on copy is handled by
135 * considering the string as empty, returning a success.
136 */
137 goto end;
138 }
139 writer->write_pos += length;
140 end:
141 return ret;
142 }
143
144 static inline int lttng_msgpack_append_u8(
145 struct lttng_msgpack_writer *writer, uint8_t value)
146 {
147 return lttng_msgpack_append_buffer(writer, &value, sizeof(value));
148 }
149
150 static inline int lttng_msgpack_append_u16(
151 struct lttng_msgpack_writer *writer, uint16_t value)
152 {
153 value = byteswap_host_to_be16(value);
154
155 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
156 }
157
158 static inline int lttng_msgpack_append_u32(
159 struct lttng_msgpack_writer *writer, uint32_t value)
160 {
161 value = byteswap_host_to_be32(value);
162
163 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
164 }
165
166 static inline int lttng_msgpack_append_u64(
167 struct lttng_msgpack_writer *writer, uint64_t value)
168 {
169 value = byteswap_host_to_be64(value);
170
171 return lttng_msgpack_append_buffer(writer, (uint8_t *) &value, sizeof(value));
172 }
173
174 static inline int lttng_msgpack_append_i8(
175 struct lttng_msgpack_writer *writer, int8_t value)
176 {
177 return lttng_msgpack_append_u8(writer, (uint8_t) value);
178 }
179
180 static inline int lttng_msgpack_append_i16(
181 struct lttng_msgpack_writer *writer, int16_t value)
182 {
183 return lttng_msgpack_append_u16(writer, (uint16_t) value);
184 }
185
186 static inline int lttng_msgpack_append_i32(
187 struct lttng_msgpack_writer *writer, int32_t value)
188 {
189 return lttng_msgpack_append_u32(writer, (uint32_t) value);
190 }
191
192 static inline int lttng_msgpack_append_i64(
193 struct lttng_msgpack_writer *writer, int64_t value)
194 {
195 return lttng_msgpack_append_u64(writer, (uint64_t) value);
196 }
197
198 static inline int lttng_msgpack_encode_fixmap(
199 struct lttng_msgpack_writer *writer, uint8_t count)
200 {
201 int ret = 0;
202
203 lttng_msgpack_assert(count <= MSGPACK_FIXMAP_MAX_COUNT);
204
205 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXMAP_ID_MASK | count);
206 if (ret)
207 goto end;
208
209 end:
210 return ret;
211 }
212
213 static inline int lttng_msgpack_encode_map16(
214 struct lttng_msgpack_writer *writer, uint16_t count)
215 {
216 int ret;
217
218 lttng_msgpack_assert(count > MSGPACK_FIXMAP_MAX_COUNT);
219
220 ret = lttng_msgpack_append_u8(writer, MSGPACK_MAP16_ID);
221 if (ret)
222 goto end;
223
224 ret = lttng_msgpack_append_u16(writer, count);
225 if (ret)
226 goto end;
227
228 end:
229 return ret;
230 }
231
232 static inline int lttng_msgpack_encode_fixarray(
233 struct lttng_msgpack_writer *writer, uint8_t count)
234 {
235 int ret = 0;
236
237 lttng_msgpack_assert(count <= MSGPACK_FIXARRAY_MAX_COUNT);
238
239 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXARRAY_ID_MASK | count);
240 if (ret)
241 goto end;
242
243 end:
244 return ret;
245 }
246
247 static inline int lttng_msgpack_encode_array16(
248 struct lttng_msgpack_writer *writer, uint16_t count)
249 {
250 int ret;
251
252 lttng_msgpack_assert(count > MSGPACK_FIXARRAY_MAX_COUNT);
253
254 ret = lttng_msgpack_append_u8(writer, MSGPACK_ARRAY16_ID);
255 if (ret)
256 goto end;
257
258 ret = lttng_msgpack_append_u16(writer, count);
259 if (ret)
260 goto end;
261
262 end:
263 return ret;
264 }
265
266 static inline int lttng_msgpack_encode_fixstr(
267 struct lttng_msgpack_writer *writer,
268 const char *str,
269 uint8_t len)
270 {
271 int ret;
272
273 lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
274
275 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
276 if (ret)
277 goto end;
278
279 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
280 if (ret)
281 goto end;
282
283 end:
284 return ret;
285 }
286
287 static inline int lttng_msgpack_encode_str16(
288 struct lttng_msgpack_writer *writer,
289 const char *str,
290 uint16_t len)
291 {
292 int ret;
293
294 lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
295
296 ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
297 if (ret)
298 goto end;
299
300 ret = lttng_msgpack_append_u16(writer, len);
301 if (ret)
302 goto end;
303
304 ret = lttng_msgpack_append_buffer(writer, (uint8_t *) str, len);
305 if (ret)
306 goto end;
307
308 end:
309 return ret;
310 }
311
312 static inline int lttng_msgpack_encode_user_fixstr(
313 struct lttng_msgpack_writer *writer,
314 const char __user *ustr,
315 uint8_t len)
316 {
317 int ret;
318
319 lttng_msgpack_assert(len <= MSGPACK_FIXSTR_MAX_LENGTH);
320
321 ret = lttng_msgpack_append_u8(writer, MSGPACK_FIXSTR_ID_MASK | len);
322 if (ret)
323 goto end;
324
325 ret = lttng_msgpack_append_user_buffer(writer, (uint8_t __user *) ustr, len);
326 if (ret)
327 goto end;
328
329 end:
330 return ret;
331 }
332
333 static inline int lttng_msgpack_encode_user_str16(
334 struct lttng_msgpack_writer *writer,
335 const char __user *ustr,
336 uint16_t len)
337 {
338 int ret;
339
340 lttng_msgpack_assert(len > MSGPACK_FIXSTR_MAX_LENGTH);
341
342 ret = lttng_msgpack_append_u8(writer, MSGPACK_STR16_ID);
343 if (ret)
344 goto end;
345
346 ret = lttng_msgpack_append_u16(writer, len);
347 if (ret)
348 goto end;
349
350 ret = lttng_msgpack_append_user_buffer(writer, (uint8_t __user *) ustr, len);
351 if (ret)
352 goto end;
353
354 end:
355 return ret;
356 }
357
358
359 int lttng_msgpack_begin_map(struct lttng_msgpack_writer *writer, size_t count)
360 {
361 int ret;
362
363 if (count >= (1 << 16)) {
364 ret = -1;
365 goto end;
366 }
367
368 if (count <= MSGPACK_FIXMAP_MAX_COUNT)
369 ret = lttng_msgpack_encode_fixmap(writer, count);
370 else
371 ret = lttng_msgpack_encode_map16(writer, count);
372
373 writer->map_nesting++;
374 end:
375 return ret;
376 }
377
378 int lttng_msgpack_end_map(struct lttng_msgpack_writer *writer)
379 {
380 lttng_msgpack_assert(writer->map_nesting > 0);
381 writer->map_nesting--;
382 return 0;
383 }
384
385 int lttng_msgpack_begin_array(
386 struct lttng_msgpack_writer *writer, size_t count)
387 {
388 int ret;
389
390 if (count >= (1 << 16)) {
391 ret = -1;
392 goto end;
393 }
394
395 if (count <= MSGPACK_FIXARRAY_MAX_COUNT)
396 ret = lttng_msgpack_encode_fixarray(writer, count);
397 else
398 ret = lttng_msgpack_encode_array16(writer, count);
399
400 writer->array_nesting++;
401 end:
402 return ret;
403 }
404
405 int lttng_msgpack_end_array(struct lttng_msgpack_writer *writer)
406 {
407 lttng_msgpack_assert(writer->array_nesting > 0);
408 writer->array_nesting--;
409 return 0;
410 }
411
412 int lttng_msgpack_write_str(struct lttng_msgpack_writer *writer,
413 const char *str)
414 {
415 int ret;
416 size_t length = strlen(str);
417
418 if (length >= (1 << 16)) {
419 ret = -1;
420 goto end;
421 }
422
423 if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
424 ret = lttng_msgpack_encode_fixstr(writer, str, length);
425 else
426 ret = lttng_msgpack_encode_str16(writer, str, length);
427
428 end:
429 return ret;
430 }
431
432 /*
433 * Provide the same behavior on lttng_strlen_user_inatomic page fault as the
434 * lttng ring buffer: truncate the last string character.
435 */
436 int lttng_msgpack_write_user_str(struct lttng_msgpack_writer *writer,
437 const char __user *ustr)
438 {
439 int ret;
440 size_t length = max_t(size_t, lttng_strlen_user_inatomic(ustr), 1);
441
442 if (length >= (1 << 16)) {
443 ret = -1;
444 goto end;
445 }
446
447 /*
448 * Handle empty string and strlen user page fault as empty string.
449 */
450 if (length == 1)
451 return lttng_msgpack_write_str(writer, "");
452
453 if (length <= MSGPACK_FIXSTR_MAX_LENGTH)
454 ret = lttng_msgpack_encode_user_fixstr(writer, ustr, length);
455 else
456 ret = lttng_msgpack_encode_user_str16(writer, ustr, length);
457
458 end:
459 return ret;
460 }
461
462 int lttng_msgpack_write_nil(struct lttng_msgpack_writer *writer)
463 {
464 return lttng_msgpack_append_u8(writer, MSGPACK_NIL_ID);
465 }
466
467 int lttng_msgpack_write_true(struct lttng_msgpack_writer *writer)
468 {
469 return lttng_msgpack_append_u8(writer, MSGPACK_TRUE_ID);
470 }
471
472 int lttng_msgpack_write_false(struct lttng_msgpack_writer *writer)
473 {
474 return lttng_msgpack_append_u8(writer, MSGPACK_FALSE_ID);
475 }
476
477 int lttng_msgpack_write_unsigned_integer(
478 struct lttng_msgpack_writer *writer, uint64_t value)
479 {
480 int ret = 0;
481
482 if (value <= MSGPACK_FIXINT_MAX) {
483 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
484 if (ret)
485 goto end;
486 } else if (value <= UINT8_MAX) {
487 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT8_ID);
488 if (ret)
489 goto end;
490
491 ret = lttng_msgpack_append_u8(writer, (uint8_t) value);
492 if (ret)
493 goto end;
494 } else if (value <= UINT16_MAX) {
495 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT16_ID);
496 if (ret)
497 goto end;
498
499 ret = lttng_msgpack_append_u16(writer, (uint16_t) value);
500 if (ret)
501 goto end;
502 } else if (value <= UINT32_MAX) {
503 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT32_ID);
504 if (ret)
505 goto end;
506
507 ret = lttng_msgpack_append_u32(writer, (uint32_t) value);
508 if (ret)
509 goto end;
510 } else {
511 ret = lttng_msgpack_append_u8(writer, MSGPACK_UINT64_ID);
512 if (ret)
513 goto end;
514
515 ret = lttng_msgpack_append_u64(writer, value);
516 if (ret)
517 goto end;
518 }
519
520 end:
521 return ret;
522 }
523
524 int lttng_msgpack_write_signed_integer(struct lttng_msgpack_writer *writer, int64_t value)
525 {
526 int ret;
527
528 if (value >= MSGPACK_FIXINT_MIN && value <= MSGPACK_FIXINT_MAX){
529 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
530 if (ret)
531 goto end;
532 } else if (value >= INT8_MIN && value <= INT8_MAX) {
533 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT8_ID);
534 if (ret)
535 goto end;
536
537 ret = lttng_msgpack_append_i8(writer, (int8_t) value);
538 if (ret)
539 goto end;
540 } else if (value >= INT16_MIN && value <= INT16_MAX) {
541 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT16_ID);
542 if (ret)
543 goto end;
544
545 ret = lttng_msgpack_append_i16(writer, (int16_t) value);
546 if (ret)
547 goto end;
548 } else if (value >= INT32_MIN && value <= INT32_MAX) {
549 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT32_ID);
550 if (ret)
551 goto end;
552
553 ret = lttng_msgpack_append_i32(writer, (int32_t) value);
554 if (ret)
555 goto end;
556 } else {
557 ret = lttng_msgpack_append_u8(writer, MSGPACK_INT64_ID);
558 if (ret)
559 goto end;
560
561 ret = lttng_msgpack_append_i64(writer, value);
562 if (ret)
563 goto end;
564 }
565
566 end:
567 return ret;
568 }
569
570 void lttng_msgpack_writer_init(struct lttng_msgpack_writer *writer,
571 uint8_t *buffer, size_t size)
572 {
573 lttng_msgpack_assert(buffer);
574 lttng_msgpack_assert(size >= 0);
575
576 writer->buffer = buffer;
577 writer->write_pos = buffer;
578 writer->end_write_pos = buffer + size;
579
580 writer->array_nesting = 0;
581 writer->map_nesting = 0;
582 }
583
584 void lttng_msgpack_writer_fini(struct lttng_msgpack_writer *writer)
585 {
586 memset(writer, 0, sizeof(*writer));
587 }
This page took 0.040389 seconds and 4 git commands to generate.