Skip to content

Commit c7bdb07

Browse files
beaubelgraverostedt
authored andcommitted
tracing: Fix print_fields() for __dyn_loc/__rel_loc
Both print_fields() and print_array() do not handle if dynamic data ends at the last byte of the payload for both __dyn_loc and __rel_loc field types. For __rel_loc, the offset was off by 4 bytes, leading to incorrect strings and data being printed out. In print_array() the buffer pos was missed from being advanced, which results in the first payload byte being used as the offset base instead of the field offset. Advance __rel_loc offset by 4 to ensure correct offset and advance pos to the field offset to ensure correct data is displayed when printing arrays. Change >= to > when checking if data is in-bounds, since it's valid for dynamic data to include the last byte of the payload. Example outputs for event format: field:unsigned short common_type; offset:0; size:2; signed:0; field:unsigned char common_flags; offset:2; size:1; signed:0; field:unsigned char common_preempt_count; offset:3; size:1; signed:0; field:int common_pid; offset:4; size:4; signed:1; field:__rel_loc char text[]; offset:8; size:4; signed:1; Output before: tp_rel_loc: text=<OVERFLOW> Output after: tp_rel_loc: text=Test Link: https://lkml.kernel.org/r/20230419214140.4158-3-beaub@linux.microsoft.com Fixes: 80a7699 ("tracing: Add "fields" option to show raw trace event fields") Reported-by: Doug Cook <dcook@linux.microsoft.com> Signed-off-by: Beau Belgrave <beaub@linux.microsoft.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent 9872c07 commit c7bdb07

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

kernel/trace/trace_output.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -819,13 +819,15 @@ static void print_array(struct trace_iterator *iter, void *pos,
819819
len = *(int *)pos >> 16;
820820

821821
if (field)
822-
offset += field->offset;
822+
offset += field->offset + sizeof(int);
823823

824-
if (offset + len >= iter->ent_size) {
824+
if (offset + len > iter->ent_size) {
825825
trace_seq_puts(&iter->seq, "<OVERFLOW>");
826826
return;
827827
}
828828

829+
pos = (void *)iter->ent + offset;
830+
829831
for (i = 0; i < len; i++, pos++) {
830832
if (i)
831833
trace_seq_putc(&iter->seq, ',');
@@ -861,9 +863,9 @@ static void print_fields(struct trace_iterator *iter, struct trace_event_call *c
861863
len = *(int *)pos >> 16;
862864

863865
if (field->filter_type == FILTER_RDYN_STRING)
864-
offset += field->offset;
866+
offset += field->offset + sizeof(int);
865867

866-
if (offset + len >= iter->ent_size) {
868+
if (offset + len > iter->ent_size) {
867869
trace_seq_puts(&iter->seq, "<OVERFLOW>");
868870
break;
869871
}

0 commit comments

Comments
 (0)