summaryrefslogtreecommitdiffstats
path: root/lib/vsprintf.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-01 16:15:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-01 16:15:23 -0500
commit27529c891b132f4fc65711334e885f466138ea2a (patch)
treeff21f3a06613638d83fe0280f7761ae73addd9ca /lib/vsprintf.c
parent8e44e6600caa7b96a5b71ae36c8829db753c2d70 (diff)
parent841a915d20c7b22fc4f36f12368daf94d9f8cb10 (diff)
Merge tag 'trace-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace
Pull tracing updates from Steven Rostedt: "There's not much changes for the tracing system this release. Mostly small clean ups and fixes. The biggest change is to how bprintf works. bprintf is used by trace_printk() to just save the format and args of a printf call, and the formatting is done when the trace buffer is read. This is done to keep the formatting out of the fast path (this was recommended by you). The issue is when arguments are de-referenced. If a pointer is saved, and the format has something like "%*pbl", when the buffer is read, it will de-reference the argument then. The problem is if the data no longer exists. This can cause the kernel to oops. The fix for this was to make these de-reference pointes do the formatting at the time it is called (the fast path), as this guarantees that the data exists (and doesn't change later)" * tag 'trace-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace: vsprintf: Do not have bprintf dereference pointers ftrace: Mark function tracer test functions noinline/noclone trace_uprobe: Display correct offset in uprobe_events tracing: Make sure the parsed string always terminates with '\0' tracing: Clear parser->idx if only spaces are read tracing: Detect the string nul character when parsing user input string
Diffstat (limited to 'lib/vsprintf.c')
-rw-r--r--lib/vsprintf.c82
1 files changed, 69 insertions, 13 deletions
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 2b18135446dc..8f56cdd52149 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -2517,29 +2517,34 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
2517{ 2517{
2518 struct printf_spec spec = {0}; 2518 struct printf_spec spec = {0};
2519 char *str, *end; 2519 char *str, *end;
2520 int width;
2520 2521
2521 str = (char *)bin_buf; 2522 str = (char *)bin_buf;
2522 end = (char *)(bin_buf + size); 2523 end = (char *)(bin_buf + size);
2523 2524
2524#define save_arg(type) \ 2525#define save_arg(type) \
2525do { \ 2526({ \
2527 unsigned long long value; \
2526 if (sizeof(type) == 8) { \ 2528 if (sizeof(type) == 8) { \
2527 unsigned long long value; \ 2529 unsigned long long val8; \
2528 str = PTR_ALIGN(str, sizeof(u32)); \ 2530 str = PTR_ALIGN(str, sizeof(u32)); \
2529 value = va_arg(args, unsigned long long); \ 2531 val8 = va_arg(args, unsigned long long); \
2530 if (str + sizeof(type) <= end) { \ 2532 if (str + sizeof(type) <= end) { \
2531 *(u32 *)str = *(u32 *)&value; \ 2533 *(u32 *)str = *(u32 *)&val8; \
2532 *(u32 *)(str + 4) = *((u32 *)&value + 1); \ 2534 *(u32 *)(str + 4) = *((u32 *)&val8 + 1); \
2533 } \ 2535 } \
2536 value = val8; \
2534 } else { \ 2537 } else { \
2535 unsigned long value; \ 2538 unsigned int val4; \
2536 str = PTR_ALIGN(str, sizeof(type)); \ 2539 str = PTR_ALIGN(str, sizeof(type)); \
2537 value = va_arg(args, int); \ 2540 val4 = va_arg(args, int); \
2538 if (str + sizeof(type) <= end) \ 2541 if (str + sizeof(type) <= end) \
2539 *(typeof(type) *)str = (type)value; \ 2542 *(typeof(type) *)str = (type)(long)val4; \
2543 value = (unsigned long long)val4; \
2540 } \ 2544 } \
2541 str += sizeof(type); \ 2545 str += sizeof(type); \
2542} while (0) 2546 value; \
2547})
2543 2548
2544 while (*fmt) { 2549 while (*fmt) {
2545 int read = format_decode(fmt, &spec); 2550 int read = format_decode(fmt, &spec);
@@ -2555,7 +2560,10 @@ do { \
2555 2560
2556 case FORMAT_TYPE_WIDTH: 2561 case FORMAT_TYPE_WIDTH:
2557 case FORMAT_TYPE_PRECISION: 2562 case FORMAT_TYPE_PRECISION:
2558 save_arg(int); 2563 width = (int)save_arg(int);
2564 /* Pointers may require the width */
2565 if (*fmt == 'p')
2566 set_field_width(&spec, width);
2559 break; 2567 break;
2560 2568
2561 case FORMAT_TYPE_CHAR: 2569 case FORMAT_TYPE_CHAR:
@@ -2577,7 +2585,27 @@ do { \
2577 } 2585 }
2578 2586
2579 case FORMAT_TYPE_PTR: 2587 case FORMAT_TYPE_PTR:
2580 save_arg(void *); 2588 /* Dereferenced pointers must be done now */
2589 switch (*fmt) {
2590 /* Dereference of functions is still OK */
2591 case 'S':
2592 case 's':
2593 case 'F':
2594 case 'f':
2595 save_arg(void *);
2596 break;
2597 default:
2598 if (!isalnum(*fmt)) {
2599 save_arg(void *);
2600 break;
2601 }
2602 str = pointer(fmt, str, end, va_arg(args, void *),
2603 spec);
2604 if (str + 1 < end)
2605 *str++ = '\0';
2606 else
2607 end[-1] = '\0'; /* Must be nul terminated */
2608 }
2581 /* skip all alphanumeric pointer suffixes */ 2609 /* skip all alphanumeric pointer suffixes */
2582 while (isalnum(*fmt)) 2610 while (isalnum(*fmt))
2583 fmt++; 2611 fmt++;
@@ -2729,11 +2757,39 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
2729 break; 2757 break;
2730 } 2758 }
2731 2759
2732 case FORMAT_TYPE_PTR: 2760 case FORMAT_TYPE_PTR: {
2733 str = pointer(fmt, str, end, get_arg(void *), spec); 2761 bool process = false;
2762 int copy, len;
2763 /* Non function dereferences were already done */
2764 switch (*fmt) {
2765 case 'S':
2766 case 's':
2767 case 'F':
2768 case 'f':
2769 process = true;
2770 break;
2771 default:
2772 if (!isalnum(*fmt)) {
2773 process = true;
2774 break;
2775 }
2776 /* Pointer dereference was already processed */
2777 if (str < end) {
2778 len = copy = strlen(args);
2779 if (copy > end - str)
2780 copy = end - str;
2781 memcpy(str, args, copy);
2782 str += len;
2783 args += len;
2784 }
2785 }
2786 if (process)
2787 str = pointer(fmt, str, end, get_arg(void *), spec);
2788
2734 while (isalnum(*fmt)) 2789 while (isalnum(*fmt))
2735 fmt++; 2790 fmt++;
2736 break; 2791 break;
2792 }
2737 2793
2738 case FORMAT_TYPE_PERCENT_CHAR: 2794 case FORMAT_TYPE_PERCENT_CHAR:
2739 if (str < end) 2795 if (str < end)