From nobody Sun May 24 21:37:41 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id ABBE539A4A7 for ; Thu, 21 May 2026 07:24:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779348286; cv=none; b=oryvmy10K3UKrX0zxxZRYWae42/C9tV5mNQr6eEcw1c+74ZLrL/4A/0ZBAxFEzQ85XrQnTZYrxS7p+lQNssqZuSkWJ3d/FX9XZq7wVe1BQ2Dy4b5oLwa9Cg41Ss1F2SPq4+xybyIJ7HCPjNI6FUnHUynVYrkuEyxw1joYS5cmV8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779348286; c=relaxed/simple; bh=2tq54+G1DHd3j5mugKeaTTS/fpsXiXue33lWment8Pw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=o6xQAngu8hNEbFSFNELbhTtu7TO7yRyVxTk/PVzy2nEHjwIqhVkhDOEf5qHVJvfqrQb5Zqd7tdlKyfQQWXfdCYsiYdLbAfcvyvsw6xMLk5LoQMKM2VdzP8kKuvmeT6UGhg29oh2azqAeN7Wp3oYVfJx86tIuclNRCg+arnzWp/U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ukahJsZa; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ukahJsZa" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-1361d52b3a0so2020893c88.0 for ; Thu, 21 May 2026 00:24:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1779348282; x=1779953082; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=f7gtESKLXiPD0tkvR99qaYWajcafSY5Lz8pSfIu9ikg=; b=ukahJsZaPp8zVXWoAcnxx/H/lLm5IERNFsZfV5qOC6CGAaEepUduwxHvH+w3r0/8c/ Bop/DFRfZJHUE5mlRLokMST2KXwoV+Oj9NpOUyXNEg+GqgV/UEQecPtyKiLrkPord1Ma BuyGkxs/jBIFaVkj8bEAVMBzudpSNpi9MorMTeW1LLK8DEyqRVclCaZP7kABLnoiUXMA re2TMKmGvBBrJHuYvUto6FmcRULnW5ik1FfZ+icNq1a38ABTuGE68rhSwQUMDqTv6lm/ tWVPJzdj3+KYM8gkLA021dgX2wU3BrpQietImwWpkN6Jao3wgLIymVEK/IfyRz/D+ysR afZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779348282; x=1779953082; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=f7gtESKLXiPD0tkvR99qaYWajcafSY5Lz8pSfIu9ikg=; b=LaSVWNgZTZPyQ2TeoiF6GtOtDlButNZL/JNUYLhIW3bSyKoNHKFQP5ufMdu/0vdqpx qwXUhlm4wBHtY994sBz2zWa9SMyfEewPIzqqtX9V3q47K2MP6mZeQpsMZFKRQr8cJ7pn Q50QZjBJTo5bWq8XCUZQt93B8RS0jN0k+uiWaMts05+RTq1cC75/K8nbrBzOjIGO8uZS D3/SKdO6463WZWwmh077EjDpmUcdKbmffeEguql0n3tXYwZEVky4f7yM2yxppHUnFUgZ 8BHaGuY8sPKISng68z7Zh3D9XFGRH/fZTMYqBJBiFIEBzl8OzKvf5NHwZjGvSZfDRA81 OBqg== X-Forwarded-Encrypted: i=1; AFNElJ98FGhgo+JQHj+CcrFw6T2xVvY8Ph1/YPHWn/HgYqo0XIdFhh8NW7EvVnyyPeo2HSrqb90ZRwBsYH6BW0o=@vger.kernel.org X-Gm-Message-State: AOJu0YyAW9VROLHruA7T4xIEDpsKmN3q2L8RQ4d7ZJeGp3qLSVZCjBlo OBZp+W7YZiCrRg8dAUtUCCWeFqg9K+U8BIup6ygduFCgWUXOUgDgsUyhBZ0MzwVlar3GFTh0fM3 6+FeOhUB+iw== X-Received: from dlbrh26.prod.google.com ([2002:a05:7022:f31a:b0:135:ebea:dc20]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:4b:b0:130:ab68:2b5e with SMTP id a92af1059eb24-136326e9d5amr855125c88.4.1779348281773; Thu, 21 May 2026 00:24:41 -0700 (PDT) Date: Thu, 21 May 2026 00:24:27 -0700 In-Reply-To: <20260521072429.1283423-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260521072429.1283423-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.746.g67dd491aae-goog Message-ID: <20260521072429.1283423-2-irogers@google.com> Subject: [PATCH v1 1/3] perf build: Unconditionally set up libunwind feature build flags From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A "make feature-dump" build does not specify LIBUNWIND=3D1 because it is run with the default configuration to detect system-wide capabilities. This sets NO_LIBUNWIND :=3D 1, causing Makefile.config to skip setting LIBUNWIND_LIBS and FEATURE_CHECK_LDFLAGS-libunwind. Consequently, when Makefile.feature is included and attempts to run all feature checks (via FEATURE_TESTS :=3D all), the local feature test test-libunwind.bin compiles without the required architecture-specific library flags (-lunwind-x86_64) and fails to link on x86_64. This results in a corrupted cached BUILD_TEST_FEATURE_DUMP showing feature-libunwind=3D0 even when the host supports it. Subsequent test builds (like make_libunwind_O in the build-test suite) which reuse the feature dump and specify LIBUNWIND=3D1 will fail to compile due to a mismatch where CONFIG_LIBUNWIND is set (via remote architecture checks which are self-contained) but HAVE_LIBUNWIND_SUPPORT is disabled, causing compiler errors due to missing maps__e_machine definitions in maps.h. Fix this by unconditionally setting up the libunwind library lists and feature check LDFLAGS in Makefile.config so they are always populated and available to the feature detection engine regardless of whether LIBUNWIND=3D1 is opted-in for the current run. Fixes: 444508cd7c7b ("perf build: Be more programmatic when setting up libu= nwind variables") Signed-off-by: Ian Rogers --- tools/perf/Makefile.config | 103 +++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 51 deletions(-) diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index b56fa8419f7d..c531b9315609 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -79,42 +79,43 @@ ifeq ($(ARCH),s390) CFLAGS +=3D -fPIC endif =20 +# Unconditionally set up the libunwind feature build flags as a +# feature-dump build doesn't specify LIBUNWIND=3D1. This means that +# dumping the libunwind features will be broken that can impact later +# builds that use the feature dump. +ifeq ($(SRCARCH),arm) + LIBUNWIND_LIBS =3D -lunwind -lunwind-arm +endif +ifeq ($(SRCARCH),arm64) + LIBUNWIND_LIBS =3D -lunwind -lunwind-aarch64 +endif +ifeq ($(SRCARCH),loongarch) + LIBUNWIND_LIBS =3D -lunwind -lunwind-loongarch64 +endif +ifeq ($(ARCH),mips) + LIBUNWIND_LIBS =3D -lunwind -lunwind-mips +endif +ifeq ($(SRCARCH),powerpc) + LIBUNWIND_LIBS :=3D -lunwind -lunwind-ppc64 +endif +ifeq ($(SRCARCH),riscv) + LIBUNWIND_LIBS :=3D -lunwind -lunwind-riscv +endif +ifeq ($(SRCARCH),s390) + LIBUNWIND_LIBS :=3D -lunwind -lunwind-s390x +endif +ifeq ($(SRCARCH),x86) + ifeq (${IS_64_BIT}, 1) + LIBUNWIND_LIBS =3D -lunwind-x86_64 -lunwind -llzma + else + LIBUNWIND_LIBS =3D -lunwind-x86 -lunwind -llzma + endif +endif ifneq ($(LIBUNWIND),1) NO_LIBUNWIND :=3D 1 endif - -ifndef NO_LIBUNWIND - ifeq ($(SRCARCH),arm) - LIBUNWIND_LIBS =3D -lunwind -lunwind-arm - endif - ifeq ($(SRCARCH),arm64) - LIBUNWIND_LIBS =3D -lunwind -lunwind-aarch64 - endif - ifeq ($(SRCARCH),loongarch) - LIBUNWIND_LIBS =3D -lunwind -lunwind-loongarch64 - endif - ifeq ($(ARCH),mips) - LIBUNWIND_LIBS =3D -lunwind -lunwind-mips - endif - ifeq ($(SRCARCH),powerpc) - LIBUNWIND_LIBS :=3D -lunwind -lunwind-ppc64 - endif - ifeq ($(SRCARCH),riscv) - LIBUNWIND_LIBS :=3D -lunwind -lunwind-riscv - endif - ifeq ($(SRCARCH),s390) - LIBUNWIND_LIBS :=3D -lunwind -lunwind-s390x - endif - ifeq ($(SRCARCH),x86) - ifeq (${IS_64_BIT}, 1) - LIBUNWIND_LIBS =3D -lunwind-x86_64 -lunwind -llzma - else - LIBUNWIND_LIBS =3D -lunwind-x86 -lunwind -llzma - endif - endif - ifeq ($(LIBUNWIND_LIBS),) - NO_LIBUNWIND :=3D 1 - endif +ifeq ($(LIBUNWIND_LIBS),) + NO_LIBUNWIND :=3D 1 endif =20 # @@ -124,24 +125,24 @@ endif # LIBUNWIND_ARCHS:=3Daarch64 arm loongarch64 mips ppc32 ppc64 riscv s390x x8= 6 x86_64 =20 -ifndef NO_LIBUNWIND - FEATURE_CHECK_CFLAGS-libunwind =3D $(LIBUNWIND_CFLAGS) - FEATURE_CHECK_LDFLAGS-libunwind =3D $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIB= S) - FEATURE_CHECK_CFLAGS-libunwind-debug-frame =3D $(LIBUNWIND_CFLAGS) - FEATURE_CHECK_LDFLAGS-libunwind-debug-frame =3D $(LIBUNWIND_LDFLAGS) $(L= IBUNWIND_LIBS) - - ifdef LIBUNWIND_DIR - LIBUNWIND_CFLAGS =3D -I$(LIBUNWIND_DIR)/include - LIBUNWIND_LDFLAGS =3D -L$(LIBUNWIND_DIR)/lib - - define libunwind_arch_set_flags - FEATURE_CHECK_CFLAGS-libunwind-$(1) =3D -I$(LIBUNWIND_DIR)/include - FEATURE_CHECK_LDFLAGS-libunwind-$(1) =3D -L$(LIBUNWIND_DIR)/lib -lun= wind -lunwind-$(1) - endef - $(foreach arch,$(LIBUNWIND_ARCHS), \ - $(eval $(call libunwind_arch_set_flags,$(arch))) \ - ) - endif +# "Local" (no arch specified) feature test flags. +FEATURE_CHECK_CFLAGS-libunwind =3D $(LIBUNWIND_CFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind =3D $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS) +FEATURE_CHECK_CFLAGS-libunwind-debug-frame =3D $(LIBUNWIND_CFLAGS) +FEATURE_CHECK_LDFLAGS-libunwind-debug-frame =3D $(LIBUNWIND_LDFLAGS) $(LIB= UNWIND_LIBS) + +# Add directory into the "remote" (build for a a specific arch) feature te= sts. +ifdef LIBUNWIND_DIR + LIBUNWIND_CFLAGS =3D -I$(LIBUNWIND_DIR)/include + LIBUNWIND_LDFLAGS =3D -L$(LIBUNWIND_DIR)/lib + + define libunwind_arch_set_flags + FEATURE_CHECK_CFLAGS-libunwind-$(1) =3D -I$(LIBUNWIND_DIR)/include + FEATURE_CHECK_LDFLAGS-libunwind-$(1) =3D -L$(LIBUNWIND_DIR)/lib -lunwi= nd -lunwind-$(1) + endef + $(foreach arch,$(LIBUNWIND_ARCHS), \ + $(eval $(call libunwind_arch_set_flags,$(arch))) \ + ) endif =20 ifdef CSINCLUDES --=20 2.54.0.746.g67dd491aae-goog From nobody Sun May 24 21:37:41 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BD557397AEF for ; Thu, 21 May 2026 07:24:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779348287; cv=none; b=iRN84c5d+Bc0p70TgAvpbyhOUMUfzcBaKAmjzmlBn2wns0vQ5/i/lfp7cOcgDHZDKj4FvPsdvDJZEfpv3ltTTSCVum/pLnEgzUnfeZk3q8h39jzYS1TO+HNxCkhlZcIMXJaEtD949S3UYTC57qrL1S+62vGIxH2ldqVEvaNdJJs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779348287; c=relaxed/simple; bh=Z4k5aPDSUnZVyff/4DWQFPnTg8uNxhX33iZgLEmRQc4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=KC5PBIOtJjylUoaO7WVxrHPglqxdUmZroF7IAmW6m4RNjCT8bkeAvXBuBJfy/odSx0ut5jDHdGUe1TVmDfHYl7RmTrXtjVOVrxlZL1AV/49OlDJ+e8QQhEbjI/niWG8NwWgw7PtLFxHB30/YoygdDXOnbtJMXFicWAZmpY5lkPQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=uKUGOL0K; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="uKUGOL0K" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2f525565b33so7111024eec.0 for ; Thu, 21 May 2026 00:24:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1779348283; x=1779953083; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=5WaPoD3mwOT0QqFAF1FBTEvv1PUPRMcMoIqd4RO4LvQ=; b=uKUGOL0KHy+mKx15IeNXaX2oLzclJL/4CRqJmKc5wEwTLFh8m5YTmE52dF1yGCk3Y2 FHmtvdSIZWP++5Xw9op7jIXzrvY5g3HxEhmcSspJDMgs1eBe3LPHDi1rPYyFQq0PsCRL sPSSVB31L+XWHdI/gz7h7BFgEDt3/DYb/UB+zNYRoyjESYduvhBYwlkOj2m0g5F8riul n4N3IFoGgBr5nd/+DnXKcoWs40AmhQi+uq6bUqbMWCRa8kM911gGAW6/XhBYVoL/CCIO GlbA3/JoGNe0tBJ6jmD81pGR4ILOJ0DdIdPVZXZwwy3RnYlwNhEYgvyMTrzG6hi4qn46 FMmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779348283; x=1779953083; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5WaPoD3mwOT0QqFAF1FBTEvv1PUPRMcMoIqd4RO4LvQ=; b=p46VjTcJ98bzoRIeRAtY7Aq07QWqzxtRVDoXiRlU+9NF1LZjjJXfRklxuCahIPODgM WnVhIgKgd6B6f4iYQJEvEhn5+WnvVKhfFaAKX3zhqeO2FTa9IGaZEjq53qhK5KTA/8Ac lLkqovQA35m/H5PpZCbv4XtD6YtVB4V5VWYAx3KURQiaVyJuzfZThOxFhk3WfIqIcr3g tOOfBY1qNKPRlW7aiZeW/hSs86UrTToOjmMmIqjsyOyMDzrNMpLImUT2GwdIbABXXC7J J1pFJJRleFzypRLdggu0xkb4PSx2wEYrT/i078FGRja+oW7073Lem5k6WkREyzQqc5Lu 8g5w== X-Forwarded-Encrypted: i=1; AFNElJ9vQf+8bDcx5l/N+OHDyLYYiTmL715v3J/UjFSwNx525jaRjdhKzI44lMnDEpNX994sumluc+KMFRdLsRI=@vger.kernel.org X-Gm-Message-State: AOJu0YzHr0TmcAODY6UvDPn8Wn1Envg4JnyihVUXVUAXJV7tSkGQMzaK wzpomCWhdd5An+UBemLGO8wgTNfRxlEohk6SmTCMHru6t/jiwScosRvOo8F2g6qEJ9UOg4giWC1 k/G2fXWd9EQ== X-Received: from dycns20.prod.google.com ([2002:a05:7300:f794:b0:303:971a:154d]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:a897:b0:2e1:e3e6:2909 with SMTP id 5a478bee46e88-3042f5c28d5mr1000547eec.9.1779348283394; Thu, 21 May 2026 00:24:43 -0700 (PDT) Date: Thu, 21 May 2026 00:24:28 -0700 In-Reply-To: <20260521072429.1283423-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260521072429.1283423-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.746.g67dd491aae-goog Message-ID: <20260521072429.1283423-3-irogers@google.com> Subject: [PATCH v1 2/3] perf kwork: Fix address sanitizer issues From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" There is a double free in the record array due to how parse_options will mutate the array. Fix by keeping an array that isn't mutated. Ensure kwork_usage is freed on all paths. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim --- tools/perf/builtin-kwork.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index 59a54d11f7fa..a4604e152002 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -2258,7 +2258,7 @@ static void setup_event_list(struct perf_kwork *kwork, static int perf_kwork__record(struct perf_kwork *kwork, int argc, const char **argv) { - const char **rec_argv; + const char **rec_argv, **to_free =3D NULL; unsigned int rec_argc, i, j; struct kwork_class *class; int ret; @@ -2295,16 +2295,27 @@ static int perf_kwork__record(struct perf_kwork *kw= ork, =20 BUG_ON(i !=3D rec_argc); =20 + /* Save the pointers as the array will be mutated by cmd_record. */ + to_free =3D calloc(rec_argc + 1, sizeof(char *)); + if (to_free =3D=3D NULL) { + ret =3D -ENOMEM; + goto EXIT; + } + pr_debug("record comm: "); - for (j =3D 0; j < rec_argc; j++) + for (j =3D 0; j < rec_argc; j++) { pr_debug("%s ", rec_argv[j]); + to_free[j] =3D rec_argv[j]; + } pr_debug("\n"); =20 ret =3D cmd_record(i, rec_argv); =20 EXIT: for (i =3D 0; i < rec_argc; i++) - free((void *)rec_argv[i]); + free((void *)(to_free ? to_free[i] : rec_argv[i])); + + free(to_free); free(rec_argv); return ret; } @@ -2447,6 +2458,7 @@ int cmd_kwork(int argc, const char **argv) const char *const kwork_subcommands[] =3D { "record", "report", "latency", "timehist", "top", NULL }; + int ret =3D 0; =20 perf_tool__init(&kwork.tool, /*ordered_events=3D*/true); kwork.tool.mmap =3D perf_event__process_mmap; @@ -2463,7 +2475,7 @@ int cmd_kwork(int argc, const char **argv) =20 if (strlen(argv[0]) > 2 && strstarts("record", argv[0])) { setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__record(&kwork, argc, argv); + ret =3D perf_kwork__record(&kwork, argc, argv); } else if (strlen(argv[0]) > 2 && strstarts("report", argv[0])) { kwork.sort_order =3D default_report_sort_order; if (argc > 1) { @@ -2474,7 +2486,7 @@ int cmd_kwork(int argc, const char **argv) kwork.report =3D KWORK_REPORT_RUNTIME; setup_sorting(&kwork, report_options, report_usage); setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__report(&kwork); + ret =3D perf_kwork__report(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("latency", argv[0])) { kwork.sort_order =3D default_latency_sort_order; if (argc > 1) { @@ -2485,7 +2497,7 @@ int cmd_kwork(int argc, const char **argv) kwork.report =3D KWORK_REPORT_LATENCY; setup_sorting(&kwork, latency_options, latency_usage); setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__report(&kwork); + ret =3D perf_kwork__report(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("timehist", argv[0])) { if (argc > 1) { argc =3D parse_options(argc, argv, timehist_options, timehist_usage, 0); @@ -2494,7 +2506,7 @@ int cmd_kwork(int argc, const char **argv) } kwork.report =3D KWORK_REPORT_TIMEHIST; setup_event_list(&kwork, kwork_options, kwork_usage); - return perf_kwork__timehist(&kwork); + ret =3D perf_kwork__timehist(&kwork); } else if (strlen(argv[0]) > 2 && strstarts("top", argv[0])) { kwork.sort_order =3D default_top_sort_order; if (argc > 1) { @@ -2507,12 +2519,12 @@ int cmd_kwork(int argc, const char **argv) kwork.event_list_str =3D "sched, irq, softirq"; setup_event_list(&kwork, kwork_options, kwork_usage); setup_sorting(&kwork, top_options, top_usage); - return perf_kwork__top(&kwork); + ret =3D perf_kwork__top(&kwork); } else usage_with_options(kwork_usage, kwork_options); =20 /* free usage string allocated by parse_options_subcommand */ free((void *)kwork_usage[0]); =20 - return 0; + return ret; } --=20 2.54.0.746.g67dd491aae-goog From nobody Sun May 24 21:37:41 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4066D39A053 for ; Thu, 21 May 2026 07:24:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779348290; cv=none; b=U1nf+xRRlabL9hHdsSfgvVpiYgaRo10V1b7vYXNW96eMy0coxtCjMsVYDsxkM45oaYAQZUZuuh5fNG4SCqH7d+z7U3nOc/m3ZsmbM7wiNmk58pS3VVvqa+94EjM9efdlVU3Summ6hidRlge9YedsllIHbF/IhLAnO5TeHdfj0+8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779348290; c=relaxed/simple; bh=M5bXVLuc0x8lBuTutbBwd25MT/WroNw+AYKDP4kaVxo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=kjsPxV5Yiy5jVo9pQGOKkmpp98tY2ed+TpFPQWsi3+67S4M4Va795b7LlOnPiKh8COSCYVTMOjF+WO9N3zM8v8UcAkOxNeqj4QAKawPjs8LaWl5HYexylsalSzO3dRQMpum8BT2YH5X9JCdqam4xa6/Zmejc0hijSHkUD9AQPgk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=V8Rg0hgh; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="V8Rg0hgh" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2fe1cf409a1so9870042eec.1 for ; Thu, 21 May 2026 00:24:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1779348285; x=1779953085; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=6m9EXKwSTsrrPfp/aS5MADZfGlUtrbkMt9KfRNRiRsA=; b=V8Rg0hghIZ6mhUghk8l9+r8krlZaRgOTNQlmKN3Df2GzsNnOfihUmLh375mV6jMtuC hjbaz0dLYvG7HiZdoFpL+JfSR3BOhWoeAXfp+GQvvDDA4qGv1qlLPBS49d0VQQ8YcmtL Hdm78UaehtwZaEbRLe+Jr/luGCEAzXHYllrlsZ+KSAucyEuhwv/WqpaFkp5QL1t3yw5B Aax76elvgwezVpmXf7ysEkeUR/86pyegCcbPKLNTs74aSYWHrglvhNEPQkbbnAqp3NXL khLazuMJcJNuL7pQh7YrdQWPLStbQfrH3ApoSlQf/y61dEBCieI1tNqEvLMC/PA0Va3f spcg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779348285; x=1779953085; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=6m9EXKwSTsrrPfp/aS5MADZfGlUtrbkMt9KfRNRiRsA=; b=jEYwO76jV8CQIWARU+lADml4PM+T7OROHmhEsIxqDUSiqBADvgsDOaEf7kxTya40AG M1xnbRxSfdHPX8dCUDdBSS/ZlxDmafn1ERxiS9Py29srduAgQ3c4QaeboM+Fq+awiD3r I/svOkCFQcwS54NLFcXngspqlIBnt/NVHUdK3UNQv8UlCPhrBRKDRX60n1n8LUiTUPj6 21CRLTcCdM8EX3G/ix+lkfGyNsAUDAj88azc0SaK5ET4ntrQ0Ib+cDFsO7A3QRW9Jkjl HkVJ9QaI5YBg4SVIdeLPcdz9XQnkxOnwv3syz80D5AIK8GKr2TA331D6GjZ3iTJ7/JS7 goFg== X-Forwarded-Encrypted: i=1; AFNElJ/O0hAU1Gkr/GO82rAZ1FPP1bOc58HC8+YGr4gfpYYItJFyHLqHIY6P0I8ZsprRs6K7hX73Q7VjRs4x+qY=@vger.kernel.org X-Gm-Message-State: AOJu0YwiM5/n6Sgl18KzXvAVzdqC/7Ej19xuqGSTxLEmPOKlwN7O9TlJ w5lrFS4WM2TP9aVxEFuTdWR6p4ZriD1PXHWtsKqi5K/WZu+ys9Ivkpe3Wev5RmAcA2+5xSwKUzS /C2Z3NNrNTw== X-Received: from dybnl19.prod.google.com ([2002:a05:7300:cf93:b0:2f9:af7:504a]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:e82b:b0:2dd:c066:c02 with SMTP id 5a478bee46e88-3042f94e725mr1030027eec.22.1779348285043; Thu, 21 May 2026 00:24:45 -0700 (PDT) Date: Thu, 21 May 2026 00:24:29 -0700 In-Reply-To: <20260521072429.1283423-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260521072429.1283423-1-irogers@google.com> X-Mailer: git-send-email 2.54.0.746.g67dd491aae-goog Message-ID: <20260521072429.1283423-4-irogers@google.com> Subject: [PATCH v1 3/3] perf kwork: Fix memory management of kwork_work From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Jiri Olsa , Ian Rogers , Adrian Hunter , James Clark , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This commit addresses several memory management issues in builtin-kwork.c: 1. Implements a global cleanup function perf_kwork__exit to free all kwork_work and kwork_atom_page objects at the end of the command. 2. Ensures all 'name' fields in struct kwork_work are malloc-ed (or NULL) and properly freed by using strdup and zfree. 3. Fixes memory leaks in top_merge_tasks where kwork_work objects were dropped without being freed. 4. Adds robustness with NULL checks for name fields. 5. Fixes workqueue_work_init to correctly resolve and strdup kernel function names, preventing bad-free errors. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim --- tools/perf/builtin-kwork.c | 121 ++++++++++++++++++++++++++++-------- tools/perf/util/bpf_kwork.c | 14 +++-- tools/perf/util/kwork.h | 9 +++ 3 files changed, 115 insertions(+), 29 deletions(-) diff --git a/tools/perf/builtin-kwork.c b/tools/perf/builtin-kwork.c index a4604e152002..f793ea578515 100644 --- a/tools/perf/builtin-kwork.c +++ b/tools/perf/builtin-kwork.c @@ -323,8 +323,8 @@ static struct kwork_work *work_search(struct rb_root_ca= ched *root, else if (cmp < 0) node =3D node->rb_right; else { - if (work->name =3D=3D NULL) - work->name =3D key->name; + if (work->name =3D=3D NULL && key->name !=3D NULL) + work->name =3D strdup(key->name); return work; } } @@ -371,11 +371,54 @@ static struct kwork_work *work_new(struct kwork_work = *key) =20 work->id =3D key->id; work->cpu =3D key->cpu; - work->name =3D key->name; + work->name =3D key->name ? strdup(key->name) : NULL; work->class =3D key->class; return work; } =20 + +static void work_delete(struct kwork_work *work) +{ + if (work) { + work_exit(work); + free(work); + } +} + +static void kwork_work__free_root(struct rb_root_cached *root) +{ + struct rb_node *next; + struct kwork_work *work; + + while ((next =3D rb_first_cached(root))) { + work =3D rb_entry(next, struct kwork_work, node); + rb_erase_cached(next, root); + work_delete(work); + } +} + +static void perf_kwork__exit(struct perf_kwork *kwork) +{ + struct kwork_class *class; + struct kwork_atom_page *page, *tmp_page; + + list_for_each_entry(class, &kwork->class_list, list) { + kwork_work__free_root(&class->work_root); + } + + kwork_work__free_root(&kwork->sorted_work_root); + + list_for_each_entry_safe(page, tmp_page, &kwork->atom_page_list, list) { + list_del_init(&page->list); + free(page); + } + + INIT_LIST_HEAD(&kwork->class_list); + INIT_LIST_HEAD(&kwork->atom_page_list); + INIT_LIST_HEAD(&kwork->sort_list); + INIT_LIST_HEAD(&kwork->cmp_id); +} + static struct kwork_work *work_findnew(struct rb_root_cached *root, struct kwork_work *key, struct list_head *sort_list) @@ -453,25 +496,29 @@ static int work_push_atom(struct perf_kwork *kwork, struct kwork_work **ret_work, bool overwrite) { - struct kwork_atom *atom, *dst_atom, *last_atom; + struct kwork_atom *atom =3D NULL, *dst_atom, *last_atom; struct kwork_work *work, key; + int ret =3D 0; =20 BUG_ON(class->work_init =3D=3D NULL); class->work_init(kwork, class, &key, src_type, sample, machine); =20 atom =3D atom_new(kwork, sample); - if (atom =3D=3D NULL) - return -1; + if (atom =3D=3D NULL) { + ret =3D -1; + goto out; + } =20 work =3D work_findnew(&class->work_root, &key, &kwork->cmp_id); if (work =3D=3D NULL) { atom_free(atom); - return -1; + ret =3D -1; + goto out; } =20 if (!profile_event_match(kwork, work, sample)) { atom_free(atom); - return 0; + goto out; } =20 if (dst_type < KWORK_TRACE_MAX) { @@ -498,8 +545,9 @@ static int work_push_atom(struct perf_kwork *kwork, } =20 list_add_tail(&atom->list, &work->atom_list[src_type]); - - return 0; +out: + work_exit(&key); + return ret; } =20 static struct kwork_atom *work_pop_atom(struct perf_kwork *kwork, @@ -510,7 +558,7 @@ static struct kwork_atom *work_pop_atom(struct perf_kwo= rk *kwork, struct machine *machine, struct kwork_work **ret_work) { - struct kwork_atom *atom, *src_atom; + struct kwork_atom *atom =3D NULL, *src_atom; struct kwork_work *work, key; =20 BUG_ON(class->work_init =3D=3D NULL); @@ -521,15 +569,15 @@ static struct kwork_atom *work_pop_atom(struct perf_k= work *kwork, *ret_work =3D work; =20 if (work =3D=3D NULL) - return NULL; + goto out; =20 if (!profile_event_match(kwork, work, sample)) - return NULL; + goto out; =20 atom =3D list_last_entry_or_null(&work->atom_list[dst_type], struct kwork_atom, list); if (atom !=3D NULL) - return atom; + goto out; =20 src_atom =3D atom_new(kwork, sample); if (src_atom !=3D NULL) @@ -538,8 +586,9 @@ static struct kwork_atom *work_pop_atom(struct perf_kwo= rk *kwork, if (ret_work !=3D NULL) *ret_work =3D NULL; } - - return NULL; +out: + work_exit(&key); + return atom; } =20 static struct kwork_work *find_work_by_id(struct rb_root_cached *root, @@ -1002,13 +1051,16 @@ static void irq_work_init(struct perf_kwork *kwork, work->name =3D NULL; } else { work->id =3D perf_sample__intval(sample, "irq"); - work->name =3D perf_sample__strval(sample, "name"); + work->name =3D strdup(perf_sample__strval(sample, "name") ?: ""= ); } } =20 static void irq_work_name(struct kwork_work *work, char *buf, int len) { - snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id); + if (work->name !=3D NULL) + snprintf(buf, len, "%s:%" PRIu64 "", work->name, work->id); + else + snprintf(buf, len, "%" PRIu64 "", work->id); } =20 static struct kwork_class kwork_irq =3D { @@ -1135,7 +1187,10 @@ static void softirq_work_init(struct perf_kwork *kwo= rk, =20 static void softirq_work_name(struct kwork_work *work, char *buf, int len) { - snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id); + if (work->name !=3D NULL) + snprintf(buf, len, "(s)%s:%" PRIu64 "", work->name, work->id); + else + snprintf(buf, len, "(s)%" PRIu64 "", work->id); } =20 static struct kwork_class kwork_softirq =3D { @@ -1220,8 +1275,14 @@ static void workqueue_work_init(struct perf_kwork *k= work __maybe_unused, work->class =3D class; work->cpu =3D sample->cpu; work->id =3D perf_sample__intval(sample, "work"); - work->name =3D function_addr =3D=3D 0 ? NULL : - machine__resolve_kernel_addr(machine, &function_addr, &modp); + work->name =3D NULL; + + if (function_addr !=3D 0) { + const char *name =3D machine__resolve_kernel_addr(machine, &function_add= r, &modp); + + if (name) + work->name =3D strdup(name); + } } =20 static void workqueue_work_name(struct kwork_work *work, char *buf, int le= n) @@ -1284,16 +1345,16 @@ static void sched_work_init(struct perf_kwork *kwor= k __maybe_unused, =20 if (src_type =3D=3D KWORK_TRACE_EXIT) { work->id =3D perf_sample__intval(sample, "prev_pid"); - work->name =3D strdup(perf_sample__strval(sample, "prev_comm")); + work->name =3D strdup(perf_sample__strval(sample, "prev_comm") ?: ""); } else if (src_type =3D=3D KWORK_TRACE_ENTRY) { work->id =3D perf_sample__intval(sample, "next_pid"); - work->name =3D strdup(perf_sample__strval(sample, "next_comm")); + work->name =3D strdup(perf_sample__strval(sample, "next_comm") ?: ""); } } =20 static void sched_work_name(struct kwork_work *work, char *buf, int len) { - snprintf(buf, len, "%s", work->name); + snprintf(buf, len, "%s", work->name ?: ""); } =20 static struct kwork_class kwork_sched =3D { @@ -2100,8 +2161,10 @@ static void top_merge_tasks(struct perf_kwork *kwork) rb_erase_cached(node, &class->work_root); data =3D rb_entry(node, struct kwork_work, node); =20 - if (!profile_name_match(kwork, data)) + if (!profile_name_match(kwork, data)) { + work_delete(data); continue; + } =20 cpu =3D data->cpu; merged_work =3D find_work_by_id(&merged_root, data->id, @@ -2109,11 +2172,17 @@ static void top_merge_tasks(struct perf_kwork *kwor= k) if (!merged_work) { work_insert(&merged_root, data, &kwork->cmp_id); } else { + if (merged_work->name =3D=3D NULL && data->name !=3D NULL) + merged_work->name =3D strdup(data->name); + merged_work->total_runtime +=3D data->total_runtime; merged_work->cpu_usage +=3D data->cpu_usage; } =20 top_calc_load_runtime(kwork, data); + + if (merged_work) + work_delete(data); } =20 work_sort(kwork, class, &merged_root); @@ -2523,6 +2592,8 @@ int cmd_kwork(int argc, const char **argv) } else usage_with_options(kwork_usage, kwork_options); =20 + perf_kwork__exit(&kwork); + /* free usage string allocated by parse_options_subcommand */ free((void *)kwork_usage[0]); =20 diff --git a/tools/perf/util/bpf_kwork.c b/tools/perf/util/bpf_kwork.c index d3a2e548f2b6..2248f462a847 100644 --- a/tools/perf/util/bpf_kwork.c +++ b/tools/perf/util/bpf_kwork.c @@ -273,6 +273,7 @@ static int add_work(struct perf_kwork *kwork, .cpu =3D key->cpu, }; enum kwork_class_type type =3D key->type; + int ret =3D 0; =20 if (!valid_kwork_class_type(type)) { pr_debug("Invalid class type %d to add work\n", type); @@ -287,8 +288,10 @@ static int add_work(struct perf_kwork *kwork, return -1; =20 work =3D kwork->add_work(kwork, tmp.class, &tmp); - if (work =3D=3D NULL) - return -1; + if (work =3D=3D NULL) { + ret =3D -1; + goto out; + } =20 if (kwork->report =3D=3D KWORK_REPORT_RUNTIME) { work->nr_atoms =3D data->nr; @@ -304,13 +307,16 @@ static int add_work(struct perf_kwork *kwork, work->max_latency_end =3D data->max_time_end; } else { pr_debug("Invalid bpf report type %d\n", kwork->report); - return -1; + ret =3D -1; + goto out; } =20 kwork->timestart =3D (u64)ts_start.tv_sec * NSEC_PER_SEC + ts_start.tv_ns= ec; kwork->timeend =3D (u64)ts_end.tv_sec * NSEC_PER_SEC + ts_end.tv_nsec; =20 - return 0; +out: + work_exit(&tmp); + return ret; } =20 int perf_kwork__report_read_bpf(struct perf_kwork *kwork) diff --git a/tools/perf/util/kwork.h b/tools/perf/util/kwork.h index abf637d44794..81d39a7f78c8 100644 --- a/tools/perf/util/kwork.h +++ b/tools/perf/util/kwork.h @@ -5,6 +5,7 @@ #include "util/tool.h" #include "util/time-utils.h" =20 +#include #include #include #include @@ -164,6 +165,14 @@ struct kwork_class { char *buf, int len); }; =20 +static inline void work_exit(struct kwork_work *work) +{ + if (work) { + free(work->name); + work->name =3D NULL; + } +} + struct trace_kwork_handler { int (*raise_event)(struct perf_kwork *kwork, struct kwork_class *class, --=20 2.54.0.746.g67dd491aae-goog