Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'trace-v6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace

Pull tracing fixes from Steven Rostedt:
"Replace trace_check_vprintf() with test_event_printk() and
ignore_event()

The function test_event_printk() checks on boot up if the trace event
printf() formats dereference any pointers, and if they do, it then
looks at the arguments to make sure that the pointers they dereference
will exist in the event on the ring buffer. If they do not, it issues
a WARN_ON() as it is a likely bug.

But this isn't the case for the strings that can be dereferenced with
"%s", as some trace events (notably RCU and some IPI events) save a
pointer to a static string in the ring buffer. As the string it points
to lives as long as the kernel is running, it is not a bug to
reference it, as it is guaranteed to be there when the event is read.
But it is also possible (and a common bug) to point to some allocated
string that could be freed before the trace event is read and the
dereference is to bad memory. This case requires a run time check.

The previous way to handle this was with trace_check_vprintf() that
would process the printf format piece by piece and send what it didn't
care about to vsnprintf() to handle arguments that were not strings.
This kept it from having to reimplement vsnprintf(). But it relied on
va_list implementation and for architectures that copied the va_list
and did not pass it by reference, it wasn't even possible to do this
check and it would be skipped. As 64bit x86 passed va_list by
reference, most events were tested and this kept out bugs where
strings would have been dereferenced after being freed.

Instead of relying on the implementation of va_list, extend the boot
up test_event_printk() function to validate all the "%s" strings that
can be validated at boot, and for the few events that point to strings
outside the ring buffer, flag both the event and the field that is
dereferenced as "needs_test". Then before the event is printed, a call
to ignore_event() is made, and if the event has the flag set, it
iterates all its fields and for every field that is to be tested, it
will read the pointer directly from the event in the ring buffer and
make sure that it is valid. If the pointer is not valid, it will print
a WARN_ON(), print out to the trace that the event has unsafe memory
and ignore the print format.

With this new update, the trace_check_vprintf() can be safely removed
and now all events can be verified regardless of architecture"

* tag 'trace-v6.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace:
tracing: Check "%s" dereference via the field and not the TP_printk format
tracing: Add "%s" check in test_event_printk()
tracing: Add missing helper functions in event pointer dereference check
tracing: Fix test_event_printk() to process entire print argument

+243 -257
+5 -1
include/linux/trace_events.h
··· 273 273 const char *name; 274 274 const int size; 275 275 const int align; 276 - const int is_signed; 276 + const unsigned int is_signed:1; 277 + unsigned int needs_test:1; 277 278 const int filter_type; 278 279 const int len; 279 280 }; ··· 325 324 TRACE_EVENT_FL_EPROBE_BIT, 326 325 TRACE_EVENT_FL_FPROBE_BIT, 327 326 TRACE_EVENT_FL_CUSTOM_BIT, 327 + TRACE_EVENT_FL_TEST_STR_BIT, 328 328 }; 329 329 330 330 /* ··· 342 340 * CUSTOM - Event is a custom event (to be attached to an exsiting tracepoint) 343 341 * This is set when the custom event has not been attached 344 342 * to a tracepoint yet, then it is cleared when it is. 343 + * TEST_STR - The event has a "%s" that points to a string outside the event 345 344 */ 346 345 enum { 347 346 TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT), ··· 355 352 TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT), 356 353 TRACE_EVENT_FL_FPROBE = (1 << TRACE_EVENT_FL_FPROBE_BIT), 357 354 TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT), 355 + TRACE_EVENT_FL_TEST_STR = (1 << TRACE_EVENT_FL_TEST_STR_BIT), 358 356 }; 359 357 360 358 #define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE)
+53 -202
kernel/trace/trace.c
··· 3611 3611 } 3612 3612 3613 3613 /* Returns true if the string is safe to dereference from an event */ 3614 - static bool trace_safe_str(struct trace_iterator *iter, const char *str, 3615 - bool star, int len) 3614 + static bool trace_safe_str(struct trace_iterator *iter, const char *str) 3616 3615 { 3617 3616 unsigned long addr = (unsigned long)str; 3618 3617 struct trace_event *trace_event; 3619 3618 struct trace_event_call *event; 3620 - 3621 - /* Ignore strings with no length */ 3622 - if (star && !len) 3623 - return true; 3624 3619 3625 3620 /* OK if part of the event data */ 3626 3621 if ((addr >= (unsigned long)iter->ent) && ··· 3656 3661 return false; 3657 3662 } 3658 3663 3659 - static DEFINE_STATIC_KEY_FALSE(trace_no_verify); 3660 - 3661 - static int test_can_verify_check(const char *fmt, ...) 3662 - { 3663 - char buf[16]; 3664 - va_list ap; 3665 - int ret; 3666 - 3667 - /* 3668 - * The verifier is dependent on vsnprintf() modifies the va_list 3669 - * passed to it, where it is sent as a reference. Some architectures 3670 - * (like x86_32) passes it by value, which means that vsnprintf() 3671 - * does not modify the va_list passed to it, and the verifier 3672 - * would then need to be able to understand all the values that 3673 - * vsnprintf can use. If it is passed by value, then the verifier 3674 - * is disabled. 3675 - */ 3676 - va_start(ap, fmt); 3677 - vsnprintf(buf, 16, "%d", ap); 3678 - ret = va_arg(ap, int); 3679 - va_end(ap); 3680 - 3681 - return ret; 3682 - } 3683 - 3684 - static void test_can_verify(void) 3685 - { 3686 - if (!test_can_verify_check("%d %d", 0, 1)) { 3687 - pr_info("trace event string verifier disabled\n"); 3688 - static_branch_inc(&trace_no_verify); 3689 - } 3690 - } 3691 - 3692 3664 /** 3693 - * trace_check_vprintf - Check dereferenced strings while writing to the seq buffer 3665 + * ignore_event - Check dereferenced fields while writing to the seq buffer 3694 3666 * @iter: The iterator that holds the seq buffer and the event being printed 3695 - * @fmt: The format used to print the event 3696 - * @ap: The va_list holding the data to print from @fmt. 3697 3667 * 3698 - * This writes the data into the @iter->seq buffer using the data from 3699 - * @fmt and @ap. If the format has a %s, then the source of the string 3700 - * is examined to make sure it is safe to print, otherwise it will 3701 - * warn and print "[UNSAFE MEMORY]" in place of the dereferenced string 3702 - * pointer. 3668 + * At boot up, test_event_printk() will flag any event that dereferences 3669 + * a string with "%s" that does exist in the ring buffer. It may still 3670 + * be valid, as the string may point to a static string in the kernel 3671 + * rodata that never gets freed. But if the string pointer is pointing 3672 + * to something that was allocated, there's a chance that it can be freed 3673 + * by the time the user reads the trace. This would cause a bad memory 3674 + * access by the kernel and possibly crash the system. 3675 + * 3676 + * This function will check if the event has any fields flagged as needing 3677 + * to be checked at runtime and perform those checks. 3678 + * 3679 + * If it is found that a field is unsafe, it will write into the @iter->seq 3680 + * a message stating what was found to be unsafe. 3681 + * 3682 + * @return: true if the event is unsafe and should be ignored, 3683 + * false otherwise. 3703 3684 */ 3704 - void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, 3705 - va_list ap) 3685 + bool ignore_event(struct trace_iterator *iter) 3706 3686 { 3707 - long text_delta = 0; 3708 - long data_delta = 0; 3709 - const char *p = fmt; 3710 - const char *str; 3711 - bool good; 3712 - int i, j; 3687 + struct ftrace_event_field *field; 3688 + struct trace_event *trace_event; 3689 + struct trace_event_call *event; 3690 + struct list_head *head; 3691 + struct trace_seq *seq; 3692 + const void *ptr; 3713 3693 3714 - if (WARN_ON_ONCE(!fmt)) 3715 - return; 3694 + trace_event = ftrace_find_event(iter->ent->type); 3716 3695 3717 - if (static_branch_unlikely(&trace_no_verify)) 3718 - goto print; 3696 + seq = &iter->seq; 3719 3697 3720 - /* 3721 - * When the kernel is booted with the tp_printk command line 3722 - * parameter, trace events go directly through to printk(). 3723 - * It also is checked by this function, but it does not 3724 - * have an associated trace_array (tr) for it. 3725 - */ 3726 - if (iter->tr) { 3727 - text_delta = iter->tr->text_delta; 3728 - data_delta = iter->tr->data_delta; 3698 + if (!trace_event) { 3699 + trace_seq_printf(seq, "EVENT ID %d NOT FOUND?\n", iter->ent->type); 3700 + return true; 3729 3701 } 3730 3702 3731 - /* Don't bother checking when doing a ftrace_dump() */ 3732 - if (iter->fmt == static_fmt_buf) 3733 - goto print; 3703 + event = container_of(trace_event, struct trace_event_call, event); 3704 + if (!(event->flags & TRACE_EVENT_FL_TEST_STR)) 3705 + return false; 3734 3706 3735 - while (*p) { 3736 - bool star = false; 3737 - int len = 0; 3707 + head = trace_get_fields(event); 3708 + if (!head) { 3709 + trace_seq_printf(seq, "FIELDS FOR EVENT '%s' NOT FOUND?\n", 3710 + trace_event_name(event)); 3711 + return true; 3712 + } 3738 3713 3739 - j = 0; 3714 + /* Offsets are from the iter->ent that points to the raw event */ 3715 + ptr = iter->ent; 3740 3716 3741 - /* 3742 - * We only care about %s and variants 3743 - * as well as %p[sS] if delta is non-zero 3744 - */ 3745 - for (i = 0; p[i]; i++) { 3746 - if (i + 1 >= iter->fmt_size) { 3747 - /* 3748 - * If we can't expand the copy buffer, 3749 - * just print it. 3750 - */ 3751 - if (!trace_iter_expand_format(iter)) 3752 - goto print; 3753 - } 3717 + list_for_each_entry(field, head, link) { 3718 + const char *str; 3719 + bool good; 3754 3720 3755 - if (p[i] == '\\' && p[i+1]) { 3756 - i++; 3757 - continue; 3758 - } 3759 - if (p[i] == '%') { 3760 - /* Need to test cases like %08.*s */ 3761 - for (j = 1; p[i+j]; j++) { 3762 - if (isdigit(p[i+j]) || 3763 - p[i+j] == '.') 3764 - continue; 3765 - if (p[i+j] == '*') { 3766 - star = true; 3767 - continue; 3768 - } 3769 - break; 3770 - } 3771 - if (p[i+j] == 's') 3772 - break; 3773 - 3774 - if (text_delta && p[i+1] == 'p' && 3775 - ((p[i+2] == 's' || p[i+2] == 'S'))) 3776 - break; 3777 - 3778 - star = false; 3779 - } 3780 - j = 0; 3781 - } 3782 - /* If no %s found then just print normally */ 3783 - if (!p[i]) 3784 - break; 3785 - 3786 - /* Copy up to the %s, and print that */ 3787 - strncpy(iter->fmt, p, i); 3788 - iter->fmt[i] = '\0'; 3789 - trace_seq_vprintf(&iter->seq, iter->fmt, ap); 3790 - 3791 - /* Add delta to %pS pointers */ 3792 - if (p[i+1] == 'p') { 3793 - unsigned long addr; 3794 - char fmt[4]; 3795 - 3796 - fmt[0] = '%'; 3797 - fmt[1] = 'p'; 3798 - fmt[2] = p[i+2]; /* Either %ps or %pS */ 3799 - fmt[3] = '\0'; 3800 - 3801 - addr = va_arg(ap, unsigned long); 3802 - addr += text_delta; 3803 - trace_seq_printf(&iter->seq, fmt, (void *)addr); 3804 - 3805 - p += i + 3; 3721 + if (!field->needs_test) 3806 3722 continue; 3807 - } 3808 3723 3809 - /* 3810 - * If iter->seq is full, the above call no longer guarantees 3811 - * that ap is in sync with fmt processing, and further calls 3812 - * to va_arg() can return wrong positional arguments. 3813 - * 3814 - * Ensure that ap is no longer used in this case. 3815 - */ 3816 - if (iter->seq.full) { 3817 - p = ""; 3818 - break; 3819 - } 3724 + str = *(const char **)(ptr + field->offset); 3820 3725 3821 - if (star) 3822 - len = va_arg(ap, int); 3823 - 3824 - /* The ap now points to the string data of the %s */ 3825 - str = va_arg(ap, const char *); 3826 - 3827 - good = trace_safe_str(iter, str, star, len); 3828 - 3829 - /* Could be from the last boot */ 3830 - if (data_delta && !good) { 3831 - str += data_delta; 3832 - good = trace_safe_str(iter, str, star, len); 3833 - } 3726 + good = trace_safe_str(iter, str); 3834 3727 3835 3728 /* 3836 3729 * If you hit this warning, it is likely that the ··· 3729 3846 * instead. See samples/trace_events/trace-events-sample.h 3730 3847 * for reference. 3731 3848 */ 3732 - if (WARN_ONCE(!good, "fmt: '%s' current_buffer: '%s'", 3733 - fmt, seq_buf_str(&iter->seq.seq))) { 3734 - int ret; 3735 - 3736 - /* Try to safely read the string */ 3737 - if (star) { 3738 - if (len + 1 > iter->fmt_size) 3739 - len = iter->fmt_size - 1; 3740 - if (len < 0) 3741 - len = 0; 3742 - ret = copy_from_kernel_nofault(iter->fmt, str, len); 3743 - iter->fmt[len] = 0; 3744 - star = false; 3745 - } else { 3746 - ret = strncpy_from_kernel_nofault(iter->fmt, str, 3747 - iter->fmt_size); 3748 - } 3749 - if (ret < 0) 3750 - trace_seq_printf(&iter->seq, "(0x%px)", str); 3751 - else 3752 - trace_seq_printf(&iter->seq, "(0x%px:%s)", 3753 - str, iter->fmt); 3754 - str = "[UNSAFE-MEMORY]"; 3755 - strcpy(iter->fmt, "%s"); 3756 - } else { 3757 - strncpy(iter->fmt, p + i, j + 1); 3758 - iter->fmt[j+1] = '\0'; 3849 + if (WARN_ONCE(!good, "event '%s' has unsafe pointer field '%s'", 3850 + trace_event_name(event), field->name)) { 3851 + trace_seq_printf(seq, "EVENT %s: HAS UNSAFE POINTER FIELD '%s'\n", 3852 + trace_event_name(event), field->name); 3853 + return true; 3759 3854 } 3760 - if (star) 3761 - trace_seq_printf(&iter->seq, iter->fmt, len, str); 3762 - else 3763 - trace_seq_printf(&iter->seq, iter->fmt, str); 3764 - 3765 - p += i + j + 1; 3766 3855 } 3767 - print: 3768 - if (*p) 3769 - trace_seq_vprintf(&iter->seq, p, ap); 3856 + return false; 3770 3857 } 3771 3858 3772 3859 const char *trace_event_format(struct trace_iterator *iter, const char *fmt) ··· 10629 10776 apply_trace_boot_options(); 10630 10777 10631 10778 register_snapshot_cmd(); 10632 - 10633 - test_can_verify(); 10634 10779 10635 10780 return 0; 10636 10781
+3 -3
kernel/trace/trace.h
··· 667 667 668 668 bool trace_is_tracepoint_string(const char *str); 669 669 const char *trace_event_format(struct trace_iterator *iter, const char *fmt); 670 - void trace_check_vprintf(struct trace_iterator *iter, const char *fmt, 671 - va_list ap) __printf(2, 0); 672 670 char *trace_iter_expand_format(struct trace_iterator *iter); 671 + bool ignore_event(struct trace_iterator *iter); 673 672 674 673 int trace_empty(struct trace_iterator *iter); 675 674 ··· 1412 1413 int filter_type; 1413 1414 int offset; 1414 1415 int size; 1415 - int is_signed; 1416 + unsigned int is_signed:1; 1417 + unsigned int needs_test:1; 1416 1418 int len; 1417 1419 }; 1418 1420
+177 -50
kernel/trace/trace_events.c
··· 82 82 } 83 83 84 84 static struct ftrace_event_field * 85 - __find_event_field(struct list_head *head, char *name) 85 + __find_event_field(struct list_head *head, const char *name) 86 86 { 87 87 struct ftrace_event_field *field; 88 88 ··· 114 114 115 115 static int __trace_define_field(struct list_head *head, const char *type, 116 116 const char *name, int offset, int size, 117 - int is_signed, int filter_type, int len) 117 + int is_signed, int filter_type, int len, 118 + int need_test) 118 119 { 119 120 struct ftrace_event_field *field; 120 121 ··· 134 133 field->offset = offset; 135 134 field->size = size; 136 135 field->is_signed = is_signed; 136 + field->needs_test = need_test; 137 137 field->len = len; 138 138 139 139 list_add(&field->link, head); ··· 153 151 154 152 head = trace_get_fields(call); 155 153 return __trace_define_field(head, type, name, offset, size, 156 - is_signed, filter_type, 0); 154 + is_signed, filter_type, 0, 0); 157 155 } 158 156 EXPORT_SYMBOL_GPL(trace_define_field); 159 157 160 158 static int trace_define_field_ext(struct trace_event_call *call, const char *type, 161 159 const char *name, int offset, int size, int is_signed, 162 - int filter_type, int len) 160 + int filter_type, int len, int need_test) 163 161 { 164 162 struct list_head *head; 165 163 ··· 168 166 169 167 head = trace_get_fields(call); 170 168 return __trace_define_field(head, type, name, offset, size, 171 - is_signed, filter_type, len); 169 + is_signed, filter_type, len, need_test); 172 170 } 173 171 174 172 #define __generic_field(type, item, filter_type) \ 175 173 ret = __trace_define_field(&ftrace_generic_fields, #type, \ 176 174 #item, 0, 0, is_signed_type(type), \ 177 - filter_type, 0); \ 175 + filter_type, 0, 0); \ 178 176 if (ret) \ 179 177 return ret; 180 178 ··· 183 181 "common_" #item, \ 184 182 offsetof(typeof(ent), item), \ 185 183 sizeof(ent.item), \ 186 - is_signed_type(type), FILTER_OTHER, 0); \ 184 + is_signed_type(type), FILTER_OTHER, \ 185 + 0, 0); \ 187 186 if (ret) \ 188 187 return ret; 189 188 ··· 247 244 return tail->offset + tail->size; 248 245 } 249 246 250 - /* 251 - * Check if the referenced field is an array and return true, 252 - * as arrays are OK to dereference. 253 - */ 254 - static bool test_field(const char *fmt, struct trace_event_call *call) 247 + 248 + static struct trace_event_fields *find_event_field(const char *fmt, 249 + struct trace_event_call *call) 255 250 { 256 251 struct trace_event_fields *field = call->class->fields_array; 257 - const char *array_descriptor; 258 252 const char *p = fmt; 259 253 int len; 260 254 261 255 if (!(len = str_has_prefix(fmt, "REC->"))) 262 - return false; 256 + return NULL; 263 257 fmt += len; 264 258 for (p = fmt; *p; p++) { 265 259 if (!isalnum(*p) && *p != '_') ··· 265 265 len = p - fmt; 266 266 267 267 for (; field->type; field++) { 268 - if (strncmp(field->name, fmt, len) || 269 - field->name[len]) 268 + if (strncmp(field->name, fmt, len) || field->name[len]) 270 269 continue; 271 - array_descriptor = strchr(field->type, '['); 272 - /* This is an array and is OK to dereference. */ 273 - return array_descriptor != NULL; 270 + 271 + return field; 272 + } 273 + return NULL; 274 + } 275 + 276 + /* 277 + * Check if the referenced field is an array and return true, 278 + * as arrays are OK to dereference. 279 + */ 280 + static bool test_field(const char *fmt, struct trace_event_call *call) 281 + { 282 + struct trace_event_fields *field; 283 + 284 + field = find_event_field(fmt, call); 285 + if (!field) 286 + return false; 287 + 288 + /* This is an array and is OK to dereference. */ 289 + return strchr(field->type, '[') != NULL; 290 + } 291 + 292 + /* Look for a string within an argument */ 293 + static bool find_print_string(const char *arg, const char *str, const char *end) 294 + { 295 + const char *r; 296 + 297 + r = strstr(arg, str); 298 + return r && r < end; 299 + } 300 + 301 + /* Return true if the argument pointer is safe */ 302 + static bool process_pointer(const char *fmt, int len, struct trace_event_call *call) 303 + { 304 + const char *r, *e, *a; 305 + 306 + e = fmt + len; 307 + 308 + /* Find the REC-> in the argument */ 309 + r = strstr(fmt, "REC->"); 310 + if (r && r < e) { 311 + /* 312 + * Addresses of events on the buffer, or an array on the buffer is 313 + * OK to dereference. There's ways to fool this, but 314 + * this is to catch common mistakes, not malicious code. 315 + */ 316 + a = strchr(fmt, '&'); 317 + if ((a && (a < r)) || test_field(r, call)) 318 + return true; 319 + } else if (find_print_string(fmt, "__get_dynamic_array(", e)) { 320 + return true; 321 + } else if (find_print_string(fmt, "__get_rel_dynamic_array(", e)) { 322 + return true; 323 + } else if (find_print_string(fmt, "__get_dynamic_array_len(", e)) { 324 + return true; 325 + } else if (find_print_string(fmt, "__get_rel_dynamic_array_len(", e)) { 326 + return true; 327 + } else if (find_print_string(fmt, "__get_sockaddr(", e)) { 328 + return true; 329 + } else if (find_print_string(fmt, "__get_rel_sockaddr(", e)) { 330 + return true; 274 331 } 275 332 return false; 333 + } 334 + 335 + /* Return true if the string is safe */ 336 + static bool process_string(const char *fmt, int len, struct trace_event_call *call) 337 + { 338 + struct trace_event_fields *field; 339 + const char *r, *e, *s; 340 + 341 + e = fmt + len; 342 + 343 + /* 344 + * There are several helper functions that return strings. 345 + * If the argument contains a function, then assume its field is valid. 346 + * It is considered that the argument has a function if it has: 347 + * alphanumeric or '_' before a parenthesis. 348 + */ 349 + s = fmt; 350 + do { 351 + r = strstr(s, "("); 352 + if (!r || r >= e) 353 + break; 354 + for (int i = 1; r - i >= s; i++) { 355 + char ch = *(r - i); 356 + if (isspace(ch)) 357 + continue; 358 + if (isalnum(ch) || ch == '_') 359 + return true; 360 + /* Anything else, this isn't a function */ 361 + break; 362 + } 363 + /* A function could be wrapped in parethesis, try the next one */ 364 + s = r + 1; 365 + } while (s < e); 366 + 367 + /* 368 + * If there's any strings in the argument consider this arg OK as it 369 + * could be: REC->field ? "foo" : "bar" and we don't want to get into 370 + * verifying that logic here. 371 + */ 372 + if (find_print_string(fmt, "\"", e)) 373 + return true; 374 + 375 + /* Dereferenced strings are also valid like any other pointer */ 376 + if (process_pointer(fmt, len, call)) 377 + return true; 378 + 379 + /* Make sure the field is found */ 380 + field = find_event_field(fmt, call); 381 + if (!field) 382 + return false; 383 + 384 + /* Test this field's string before printing the event */ 385 + call->flags |= TRACE_EVENT_FL_TEST_STR; 386 + field->needs_test = 1; 387 + 388 + return true; 276 389 } 277 390 278 391 /* ··· 397 284 static void test_event_printk(struct trace_event_call *call) 398 285 { 399 286 u64 dereference_flags = 0; 287 + u64 string_flags = 0; 400 288 bool first = true; 401 - const char *fmt, *c, *r, *a; 289 + const char *fmt; 402 290 int parens = 0; 403 291 char in_quote = 0; 404 292 int start_arg = 0; 405 293 int arg = 0; 406 - int i; 294 + int i, e; 407 295 408 296 fmt = call->print_fmt; 409 297 ··· 488 374 star = true; 489 375 continue; 490 376 } 491 - if ((fmt[i + j] == 's') && star) 492 - arg++; 377 + if ((fmt[i + j] == 's')) { 378 + if (star) 379 + arg++; 380 + if (WARN_ONCE(arg == 63, 381 + "Too many args for event: %s", 382 + trace_event_name(call))) 383 + return; 384 + dereference_flags |= 1ULL << arg; 385 + string_flags |= 1ULL << arg; 386 + } 493 387 break; 494 388 } 495 389 break; ··· 525 403 case ',': 526 404 if (in_quote || parens) 527 405 continue; 406 + e = i; 528 407 i++; 529 408 while (isspace(fmt[i])) 530 409 i++; 531 - start_arg = i; 532 - if (!(dereference_flags & (1ULL << arg))) 533 - goto next_arg; 534 410 535 - /* Find the REC-> in the argument */ 536 - c = strchr(fmt + i, ','); 537 - r = strstr(fmt + i, "REC->"); 538 - if (r && (!c || r < c)) { 539 - /* 540 - * Addresses of events on the buffer, 541 - * or an array on the buffer is 542 - * OK to dereference. 543 - * There's ways to fool this, but 544 - * this is to catch common mistakes, 545 - * not malicious code. 546 - */ 547 - a = strchr(fmt + i, '&'); 548 - if ((a && (a < r)) || test_field(r, call)) 549 - dereference_flags &= ~(1ULL << arg); 550 - } else if ((r = strstr(fmt + i, "__get_dynamic_array(")) && 551 - (!c || r < c)) { 552 - dereference_flags &= ~(1ULL << arg); 553 - } else if ((r = strstr(fmt + i, "__get_sockaddr(")) && 554 - (!c || r < c)) { 555 - dereference_flags &= ~(1ULL << arg); 411 + /* 412 + * If start_arg is zero, then this is the start of the 413 + * first argument. The processing of the argument happens 414 + * when the end of the argument is found, as it needs to 415 + * handle paranthesis and such. 416 + */ 417 + if (!start_arg) { 418 + start_arg = i; 419 + /* Balance out the i++ in the for loop */ 420 + i--; 421 + continue; 556 422 } 557 423 558 - next_arg: 559 - i--; 424 + if (dereference_flags & (1ULL << arg)) { 425 + if (string_flags & (1ULL << arg)) { 426 + if (process_string(fmt + start_arg, e - start_arg, call)) 427 + dereference_flags &= ~(1ULL << arg); 428 + } else if (process_pointer(fmt + start_arg, e - start_arg, call)) 429 + dereference_flags &= ~(1ULL << arg); 430 + } 431 + 432 + start_arg = i; 560 433 arg++; 434 + /* Balance out the i++ in the for loop */ 435 + i--; 561 436 } 437 + } 438 + 439 + if (dereference_flags & (1ULL << arg)) { 440 + if (string_flags & (1ULL << arg)) { 441 + if (process_string(fmt + start_arg, i - start_arg, call)) 442 + dereference_flags &= ~(1ULL << arg); 443 + } else if (process_pointer(fmt + start_arg, i - start_arg, call)) 444 + dereference_flags &= ~(1ULL << arg); 562 445 } 563 446 564 447 /* ··· 2598 2471 ret = trace_define_field_ext(call, field->type, field->name, 2599 2472 offset, field->size, 2600 2473 field->is_signed, field->filter_type, 2601 - field->len); 2474 + field->len, field->needs_test); 2602 2475 if (WARN_ON_ONCE(ret)) { 2603 2476 pr_err("error code is %d\n", ret); 2604 2477 break;
+5 -1
kernel/trace/trace_output.c
··· 317 317 318 318 void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...) 319 319 { 320 + struct trace_seq *s = &iter->seq; 320 321 va_list ap; 321 322 323 + if (ignore_event(iter)) 324 + return; 325 + 322 326 va_start(ap, fmt); 323 - trace_check_vprintf(iter, trace_event_format(iter, fmt), ap); 327 + trace_seq_vprintf(s, trace_event_format(iter, fmt), ap); 324 328 va_end(ap); 325 329 } 326 330 EXPORT_SYMBOL(trace_event_printf);