From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 08244C43603 for ; Tue, 10 Dec 2019 21:16:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CE1C3205C9 for ; Tue, 10 Dec 2019 21:16:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576012581; bh=H/ys2Wtv/GALGsCkH/q6pJXQUSuQ1ipluh6D6LxfUFY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=RYfFCeA1qatgtDGrAFGraI3+vAdo3pfGjbbajgnsQaEGGOirR38mC0cn+iXHvm1xk tGnQbWHgJ0QGAqeElILbyP5jxVCYyvgwtNnHgvDujO9KhU64zaOpM91uyO4b0Ee6Xz zRH0mTTAm7NPcnhfciofLYiBFC52m7PrWW8q5M1o= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729274AbfLJVNT (ORCPT ); Tue, 10 Dec 2019 16:13:19 -0500 Received: from mail.kernel.org ([198.145.29.99]:39234 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729252AbfLJVNQ (ORCPT ); Tue, 10 Dec 2019 16:13:16 -0500 Received: from sasha-vm.mshome.net (c-73-47-72-35.hsd1.nh.comcast.net [73.47.72.35]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id E3D572077B; Tue, 10 Dec 2019 21:13:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1576012394; bh=H/ys2Wtv/GALGsCkH/q6pJXQUSuQ1ipluh6D6LxfUFY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=QZ6/Ur8cSRhsp6bWIM3H2IPekdem7g5NAOp3kPkcNtM/dLiY5kXctsDYe83/043E/ pwpJTa4KrT4iWNMDmmubq2ltG85ptOr1bFIqRsg+E7wF4ol1f/WI4iNHM5VPJ+Mvd3 kxap8XLRpvXdtnq88eljv8L4oKBrPwvRSNhOD/Ow= From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Alexey Budankov , Jiri Olsa , Alexander Shishkin , Andi Kleen , Namhyung Kim , Peter Zijlstra , Arnaldo Carvalho de Melo , Sasha Levin Subject: [PATCH AUTOSEL 5.4 315/350] perf session: Fix decompression of PERF_RECORD_COMPRESSED records Date: Tue, 10 Dec 2019 16:07:00 -0500 Message-Id: <20191210210735.9077-276-sashal@kernel.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20191210210735.9077-1-sashal@kernel.org> References: <20191210210735.9077-1-sashal@kernel.org> MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alexey Budankov [ Upstream commit bb1835a3b86c73aa534ef6430ad40223728dfbc0 ] Avoid termination of trace loading in case the last record in the decompressed buffer partly resides in the following mmaped PERF_RECORD_COMPRESSED record. In this case NULL value returned by fetch_mmaped_event() means to proceed to the next mmaped record then decompress it and load compressed events. The issue can be reproduced like this: $ perf record -z -- some_long_running_workload $ perf report --stdio -vv decomp (B): 44519 to 163000 decomp (B): 48119 to 174800 decomp (B): 65527 to 131072 fetch_mmaped_event: head=0x1ffe0 event->header_size=0x28, mmap_size=0x20000: fuzzed perf.data? Error: failed to process sample ... Testing: 71: Zstd perf.data compression/decompression : Ok $ tools/perf/perf report -vv --stdio decomp (B): 59593 to 262160 decomp (B): 4438 to 16512 decomp (B): 285 to 880 Looking at the vmlinux_path (8 entries long) Using vmlinux for symbols decomp (B): 57474 to 261248 prefetch_event: head=0x3fc78 event->header_size=0x28, mmap_size=0x3fc80: fuzzed or compressed perf.data? decomp (B): 25 to 32 decomp (B): 52 to 120 ... Fixes: 57fc032ad643 ("perf session: Avoid infinite loop when seeing invalid header.size") Link: https://marc.info/?l=linux-kernel&m=156580812427554&w=2 Co-developed-by: Jiri Olsa Acked-by: Jiri Olsa Signed-off-by: Alexey Budankov Cc: Alexander Shishkin Cc: Andi Kleen Cc: Namhyung Kim Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/cf782c34-f3f8-2f9f-d6ab-145cee0d5322@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo Signed-off-by: Sasha Levin --- tools/perf/util/session.c | 44 ++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 061bb4d6a3f5a..5c172845fa5ac 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -1954,8 +1954,8 @@ static int __perf_session__process_pipe_events(struct perf_session *session) } static union perf_event * -fetch_mmaped_event(struct perf_session *session, - u64 head, size_t mmap_size, char *buf) +prefetch_event(char *buf, u64 head, size_t mmap_size, + bool needs_swap, union perf_event *error) { union perf_event *event; @@ -1967,20 +1967,32 @@ fetch_mmaped_event(struct perf_session *session, return NULL; event = (union perf_event *)(buf + head); + if (needs_swap) + perf_event_header__bswap(&event->header); - if (session->header.needs_swap) + if (head + event->header.size <= mmap_size) + return event; + + /* We're not fetching the event so swap back again */ + if (needs_swap) perf_event_header__bswap(&event->header); - if (head + event->header.size > mmap_size) { - /* We're not fetching the event so swap back again */ - if (session->header.needs_swap) - perf_event_header__bswap(&event->header); - pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx: fuzzed perf.data?\n", - __func__, head, event->header.size, mmap_size); - return ERR_PTR(-EINVAL); - } + pr_debug("%s: head=%#" PRIx64 " event->header_size=%#x, mmap_size=%#zx:" + " fuzzed or compressed perf.data?\n",__func__, head, event->header.size, mmap_size); - return event; + return error; +} + +static union perf_event * +fetch_mmaped_event(u64 head, size_t mmap_size, char *buf, bool needs_swap) +{ + return prefetch_event(buf, head, mmap_size, needs_swap, ERR_PTR(-EINVAL)); +} + +static union perf_event * +fetch_decomp_event(u64 head, size_t mmap_size, char *buf, bool needs_swap) +{ + return prefetch_event(buf, head, mmap_size, needs_swap, NULL); } static int __perf_session__process_decomp_events(struct perf_session *session) @@ -1993,10 +2005,8 @@ static int __perf_session__process_decomp_events(struct perf_session *session) return 0; while (decomp->head < decomp->size && !session_done()) { - union perf_event *event = fetch_mmaped_event(session, decomp->head, decomp->size, decomp->data); - - if (IS_ERR(event)) - return PTR_ERR(event); + union perf_event *event = fetch_decomp_event(decomp->head, decomp->size, decomp->data, + session->header.needs_swap); if (!event) break; @@ -2096,7 +2106,7 @@ reader__process_events(struct reader *rd, struct perf_session *session, } more: - event = fetch_mmaped_event(session, head, mmap_size, buf); + event = fetch_mmaped_event(head, mmap_size, buf, session->header.needs_swap); if (IS_ERR(event)) return PTR_ERR(event); -- 2.20.1