Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932250AbbFRIQ6 (ORCPT ); Thu, 18 Jun 2015 04:16:58 -0400 Received: from terminus.zytor.com ([198.137.202.10]:57225 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752751AbbFRIQc (ORCPT ); Thu, 18 Jun 2015 04:16:32 -0400 Date: Thu, 18 Jun 2015 01:16:03 -0700 From: tip-bot for Wang Nan Message-ID: Cc: a.p.zijlstra@chello.nl, tglx@linutronix.de, acme@redhat.com, wangnan0@huawei.com, masami.hiramatsu.pt@hitachi.com, mingo@redhat.com, mingo@kernel.org, linux-kernel@vger.kernel.org, hpa@zytor.com, jolsa@kernel.org, lizefan@huawei.com, namhyung@kernel.org Reply-To: namhyung@kernel.org, lizefan@huawei.com, hpa@zytor.com, jolsa@kernel.org, linux-kernel@vger.kernel.org, mingo@kernel.org, masami.hiramatsu.pt@hitachi.com, mingo@redhat.com, wangnan0@huawei.com, acme@redhat.com, tglx@linutronix.de, a.p.zijlstra@chello.nl In-Reply-To: <1434534999-85347-1-git-send-email-wangnan0@huawei.com> References: <1434534999-85347-1-git-send-email-wangnan0@huawei.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/core] perf tools: Fix a problem when opening old perf.data with different byte order Git-Commit-ID: b30b617292462ca7ee68834b117a7833f4a52e16 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4831 Lines: 125 Commit-ID: b30b617292462ca7ee68834b117a7833f4a52e16 Gitweb: http://git.kernel.org/tip/b30b617292462ca7ee68834b117a7833f4a52e16 Author: Wang Nan AuthorDate: Wed, 17 Jun 2015 09:56:39 +0000 Committer: Arnaldo Carvalho de Melo CommitDate: Wed, 17 Jun 2015 16:28:08 -0300 perf tools: Fix a problem when opening old perf.data with different byte order Following error occurs when trying to use 'perf report' on x86_64 to cross analysis a perf.data generated by an old perf on a big-endian machine: # perf report *** Error in `/home/w00229757/perf': free(): invalid next size (fast): 0x00000000032c99f0 *** ======= Backtrace: ========= /lib64/libc.so.6(+0x6eeef)[0x7ff6ff7e2eef] /lib64/libc.so.6(+0x78cae)[0x7ff6ff7eccae] /lib64/libc.so.6(+0x79987)[0x7ff6ff7ed987] /path/to/perf[0x4ac734] /path/to/perf[0x4ac829] /path/to/perf(perf_header__process_sections+0x129)[0x4ad2c9] /path/to/perf(perf_session__read_header+0x2e1)[0x4ad9e1] /path/to/perf(perf_session__new+0x168)[0x4bd458] /path/to/perf(cmd_report+0xfa0)[0x43eb70] /path/to/perf[0x47adc3] /path/to/perf(main+0x5f6)[0x42fd06] /lib64/libc.so.6(__libc_start_main+0xf5)[0x7ff6ff795bd5] /path/to/perf[0x42fe35] ======= Memory map: ======== [SNIP] The bug is in perf_event__attr_swap(). It swaps all fields in 'struct perf_event_attr' without checking whether the swapped field exist or not. In addition, in read_event_desc() allocs memory for attr according to size read from perf.data. Therefore, if the perf.data is collected by an old perf (without aux_watermark, for example), when perf_event__attr_swap() swaping attr->aux_watermark it destroy malloc's metadata. This patch introduces boundary checking in perf_event__attr_swap(). It adds macros bswap_field_64 and bswap_field_32 into perf_event__attr_swap() to make it only swap exist fields. Signed-off-by: Wang Nan Acked-by: Jiri Olsa Cc: Ingo Molnar Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Zefan Li Cc: pi3orama@163.com Link: http://lkml.kernel.org/r/1434534999-85347-1-git-send-email-wangnan0@huawei.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/session.c | 50 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index f31e024..e1cd17c 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -517,20 +517,42 @@ void perf_event__attr_swap(struct perf_event_attr *attr) { attr->type = bswap_32(attr->type); attr->size = bswap_32(attr->size); - attr->config = bswap_64(attr->config); - attr->sample_period = bswap_64(attr->sample_period); - attr->sample_type = bswap_64(attr->sample_type); - attr->read_format = bswap_64(attr->read_format); - attr->wakeup_events = bswap_32(attr->wakeup_events); - attr->bp_type = bswap_32(attr->bp_type); - attr->bp_addr = bswap_64(attr->bp_addr); - attr->bp_len = bswap_64(attr->bp_len); - attr->branch_sample_type = bswap_64(attr->branch_sample_type); - attr->sample_regs_user = bswap_64(attr->sample_regs_user); - attr->sample_stack_user = bswap_32(attr->sample_stack_user); - attr->aux_watermark = bswap_32(attr->aux_watermark); - - swap_bitfield((u8 *) (&attr->read_format + 1), sizeof(u64)); + +#define bswap_safe(f, n) \ + (attr->size > (offsetof(struct perf_event_attr, f) + \ + sizeof(attr->f) * (n))) +#define bswap_field(f, sz) \ +do { \ + if (bswap_safe(f, 0)) \ + attr->f = bswap_##sz(attr->f); \ +} while(0) +#define bswap_field_32(f) bswap_field(f, 32) +#define bswap_field_64(f) bswap_field(f, 64) + + bswap_field_64(config); + bswap_field_64(sample_period); + bswap_field_64(sample_type); + bswap_field_64(read_format); + bswap_field_32(wakeup_events); + bswap_field_32(bp_type); + bswap_field_64(bp_addr); + bswap_field_64(bp_len); + bswap_field_64(branch_sample_type); + bswap_field_64(sample_regs_user); + bswap_field_32(sample_stack_user); + bswap_field_32(aux_watermark); + + /* + * After read_format are bitfields. Check read_format because + * we are unable to use offsetof on bitfield. + */ + if (bswap_safe(read_format, 1)) + swap_bitfield((u8 *) (&attr->read_format + 1), + sizeof(u64)); +#undef bswap_field_64 +#undef bswap_field_32 +#undef bswap_field +#undef bswap_safe } static void perf_event__hdr_attr_swap(union perf_event *event, -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/