Skip to content

Commit eb01f53

Browse files
committed
tracing: Handle %.*s in trace_check_vprintf()
If a trace event uses the %*.s notation, the trace_check_vprintf() will fail and will warn about a bad processing of strings, because it does not take into account the length field when processing the star (*) part. Have it handle this case as well. Link: https://lore.kernel.org/linux-nfs/238C0E2D-C2A4-4578-ADD2-C565B3B99842@oracle.com/ Reported-by: Chuck Lever III <chuck.lever@oracle.com> Fixes: 9a6944f ("tracing: Add a verifier to check string pointers for trace events") Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
1 parent 6efb943 commit eb01f53

1 file changed

Lines changed: 27 additions & 4 deletions

File tree

kernel/trace/trace.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3704,6 +3704,9 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
37043704
goto print;
37053705

37063706
while (*p) {
3707+
bool star = false;
3708+
int len = 0;
3709+
37073710
j = 0;
37083711

37093712
/* We only care about %s and variants */
@@ -3725,13 +3728,17 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
37253728
/* Need to test cases like %08.*s */
37263729
for (j = 1; p[i+j]; j++) {
37273730
if (isdigit(p[i+j]) ||
3728-
p[i+j] == '*' ||
37293731
p[i+j] == '.')
37303732
continue;
3733+
if (p[i+j] == '*') {
3734+
star = true;
3735+
continue;
3736+
}
37313737
break;
37323738
}
37333739
if (p[i+j] == 's')
37343740
break;
3741+
star = false;
37353742
}
37363743
j = 0;
37373744
}
@@ -3744,6 +3751,9 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
37443751
iter->fmt[i] = '\0';
37453752
trace_seq_vprintf(&iter->seq, iter->fmt, ap);
37463753

3754+
if (star)
3755+
len = va_arg(ap, int);
3756+
37473757
/* The ap now points to the string data of the %s */
37483758
str = va_arg(ap, const char *);
37493759

@@ -3762,8 +3772,18 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
37623772
int ret;
37633773

37643774
/* Try to safely read the string */
3765-
ret = strncpy_from_kernel_nofault(iter->fmt, str,
3766-
iter->fmt_size);
3775+
if (star) {
3776+
if (len + 1 > iter->fmt_size)
3777+
len = iter->fmt_size - 1;
3778+
if (len < 0)
3779+
len = 0;
3780+
ret = copy_from_kernel_nofault(iter->fmt, str, len);
3781+
iter->fmt[len] = 0;
3782+
star = false;
3783+
} else {
3784+
ret = strncpy_from_kernel_nofault(iter->fmt, str,
3785+
iter->fmt_size);
3786+
}
37673787
if (ret < 0)
37683788
trace_seq_printf(&iter->seq, "(0x%px)", str);
37693789
else
@@ -3775,7 +3795,10 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
37753795
strncpy(iter->fmt, p + i, j + 1);
37763796
iter->fmt[j+1] = '\0';
37773797
}
3778-
trace_seq_printf(&iter->seq, iter->fmt, str);
3798+
if (star)
3799+
trace_seq_printf(&iter->seq, iter->fmt, len, str);
3800+
else
3801+
trace_seq_printf(&iter->seq, iter->fmt, str);
37793802

37803803
p += i + j + 1;
37813804
}

0 commit comments

Comments
 (0)