mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-21 03:33:59 +08:00
perf ctf: Convert invalid chars in a string before set value
We observed some crazy apps on Android set their comm to unprintable string. For example: # cat /proc/10607/task/*/comm tencent.qqmusic ... Binder_2 日志输出线 <-- Chinese word 'log output thread' WifiManager ... 'perf data convert' fails to convert perf.data with such string to CTF format. For example: # cat << EOF > ./badguy.c #include <sys/prctl.h> int main(int argc, char *argv[]) { prctl(PR_SET_NAME, "\xe6\x97\xa5\xe5\xbf\x97\xe8\xbe\x93\xe5\x87\xba\xe7\xba\xbf"); while(1) sleep(1); return 0; } EOF # gcc ./badguy.c # perf record -e sched:* ./a.out # perf data convert --to-ctf ./bad.ctf CTF stream 4 flush failed [ perf data convert: Converted 'perf.data' into CTF data './bad.ctf' ] [ perf data convert: Converted and wrote 0.008 MB (78 samples) ] # babeltrace ./bad.ctf/ [error] Packet size (18446744073709551615 bits) is larger than remaining file size (262144 bits). [error] Stream index creation error. [error] Open file stream error. [warning] [Context] Cannot open_trace of format ctf at path ./bad.ctf. [warning] [Context] cannot open trace "./bad.ctf" from ./bad.ctf/ for reading. [error] Cannot open any trace for reading. [error] opening trace "./bad.ctf/" for reading. [error] none of the specified trace paths could be opened. This patch converts unprintable characters to hexadecimal word. After applying this patch the above test works correctly: # ~/perf data convert --to-ctf ./good.ctf [ perf data convert: Converted 'perf.data' into CTF data './good.ctf' ] [ perf data convert: Converted and wrote 0.008 MB (78 samples) ] # babeltrace ./good.ctf .. [23:14:35.491665268] (+0.000001100) sched:sched_wakeup: { cpu_id = 4 }, { perf_ip = 0xFFFFFFFF810AEF33, perf_tid = 0, perf_pid = 0, perf_id = 5123, perf_period = 1, common_type = 270, common_flags = 45, common_preempt_count = 4, common_pid = 0, comm = "\xe6\x97\xa5\xe5\xbf\x97\xe8\xbe\x93\xe5\x87\xba\xe7\xba\xbf", pid = 1057, prio = 120, success = 1, target_cpu = 4 } [23:14:35.491666230] (+0.000000962) sched:sched_wakeup: { cpu_id = 4 }, { perf_ip = 0xFFFFFFFF810AEF33, perf_tid = 0, perf_pid = 0, perf_id = 5122, perf_period = 1, common_type = 270, common_flags = 45, common_preempt_count = 4, common_pid = 0, comm = "\xe6\x97\xa5\xe5\xbf\x97\xe8\xbe\x93\xe5\x87\xba\xe7\xba\xbf", pid = 1057, prio = 120, success = 1, target_cpu = 4 } .. Committer note: To build perf with libabeltrace, use: $ mkdir -p /tmp/build/perf $ make LIBBABELTRACE=1 LIBBABELTRACE_DIR=/usr/local O=/tmp/build/perf -C tools/perf install-bin Or equivalent (no O=, fixup LIBBABELTRACE_DIR, etc). Signed-off-by: Wang Nan <wangnan0@huawei.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1464348951-179595-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
3dc6c1d54f
commit
5ea5888b2f
@ -204,6 +204,44 @@ static unsigned long long adjust_signedness(unsigned long long value_int, int si
|
||||
return (value_int & value_mask) | ~value_mask;
|
||||
}
|
||||
|
||||
static int string_set_value(struct bt_ctf_field *field, const char *string)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
size_t len = strlen(string), i, p;
|
||||
int err;
|
||||
|
||||
for (i = p = 0; i < len; i++, p++) {
|
||||
if (isprint(string[i])) {
|
||||
if (!buffer)
|
||||
continue;
|
||||
buffer[p] = string[i];
|
||||
} else {
|
||||
char numstr[5];
|
||||
|
||||
snprintf(numstr, sizeof(numstr), "\\x%02x",
|
||||
(unsigned int)(string[i]) & 0xff);
|
||||
|
||||
if (!buffer) {
|
||||
buffer = zalloc(i + (len - i) * 4 + 2);
|
||||
if (!buffer) {
|
||||
pr_err("failed to set unprintable string '%s'\n", string);
|
||||
return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
|
||||
}
|
||||
if (i > 0)
|
||||
strncpy(buffer, string, i);
|
||||
}
|
||||
strncat(buffer + p, numstr, 4);
|
||||
p += 3;
|
||||
}
|
||||
}
|
||||
|
||||
if (!buffer)
|
||||
return bt_ctf_field_string_set_value(field, string);
|
||||
err = bt_ctf_field_string_set_value(field, buffer);
|
||||
free(buffer);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int add_tracepoint_field_value(struct ctf_writer *cw,
|
||||
struct bt_ctf_event_class *event_class,
|
||||
struct bt_ctf_event *event,
|
||||
@ -270,8 +308,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
|
||||
}
|
||||
|
||||
if (flags & FIELD_IS_STRING)
|
||||
ret = bt_ctf_field_string_set_value(field,
|
||||
data + offset + i * len);
|
||||
ret = string_set_value(field, data + offset + i * len);
|
||||
else {
|
||||
unsigned long long value_int;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user