From nobody Sun Dec 28 02:30:11 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA63444C79; Wed, 27 Dec 2023 12:38:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="s3xdYdjN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 13075C433C9; Wed, 27 Dec 2023 12:38:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1703680709; bh=X7R6F9hT6XYOO3BGfeWVV1thc/132FVHa6UnzJbO8Fg=; h=From:To:Cc:Subject:Date:From; b=s3xdYdjN0JOula1WTh6A2iY780fPuc5IgTrHuxBP2YtCgzASY8pVu5cCIY7V7869q TE0fEUoZX+CYtqtqwXCsY8OYqXoe843PQhGtjEdymRcJLFja1/UF0z70P+ObGRMhcy q5mHqo9TWriOWFO8r/kE4PTdfsTl5/UVNn9H+iJe8JO4oJipqon4Kv1/oyimY/7o8v 0TzD2/pQGXH+KeQR/7JBNOzi9SHvR2xPoYCM7SvufLJ2jw0s74kX+eqxEsTqPiypj3 zZySoByBOlV7buyytNoiODdK6mDu0ZQbrUqD0ZaH5FVMY98tGXBo8VMIUahi8uB1fA uCC4SF5HSoqYg== From: "Masami Hiramatsu (Google)" To: Steven Rostedt , Jiri Olsa Cc: linux-trace-kernel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] tracing: Fix possible memory leak in ftrace_regsiter_direct() Date: Wed, 27 Dec 2023 21:38:25 +0900 Message-Id: <170368070504.42064.8960569647118388081.stgit@devnote2> X-Mailer: git-send-email 2.34.1 User-Agent: StGit/0.19 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Masami Hiramatsu (Google) If ftrace_register_direct() called with a large number of target functions (e.g. 65), the free_hash can be updated twice or more in the ftrace_add_rec_direct() without freeing the previous hash memory. Thus this can cause a memory leak. Fix this issue by expanding the direct_hash at once before adding the new entries. Signed-off-by: Masami Hiramatsu (Google) Fixes: f64dd4627ec6 ("ftrace: Add multi direct register/unregister interfac= e") Cc: stable@vger.kernel.org --- kernel/trace/ftrace.c | 49 +++++++++++++++++++++++++++++++--------------= ---- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8de8bec5f366..9269c2c3e595 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2555,28 +2555,33 @@ unsigned long ftrace_find_rec_direct(unsigned long = ip) return entry->direct; } =20 -static struct ftrace_func_entry* -ftrace_add_rec_direct(unsigned long ip, unsigned long addr, - struct ftrace_hash **free_hash) +static struct ftrace_hash *ftrace_expand_direct(int inc_count) { - struct ftrace_func_entry *entry; + struct ftrace_hash *new_hash, *free_hash; + int size =3D ftrace_hash_empty(direct_functions) ? 0 : + direct_functions->count + inc_count; =20 - if (ftrace_hash_empty(direct_functions) || - direct_functions->count > 2 * (1 << direct_functions->size_bits)) { - struct ftrace_hash *new_hash; - int size =3D ftrace_hash_empty(direct_functions) ? 0 : - direct_functions->count + 1; + if (!ftrace_hash_empty(direct_functions) && + size <=3D 2 * (1 << direct_functions->size_bits)) + return NULL; =20 - if (size < 32) - size =3D 32; + if (size < 32) + size =3D 32; =20 - new_hash =3D dup_hash(direct_functions, size); - if (!new_hash) - return NULL; + new_hash =3D dup_hash(direct_functions, size); + if (!new_hash) + return ERR_PTR(-ENOMEM); =20 - *free_hash =3D direct_functions; - direct_functions =3D new_hash; - } + free_hash =3D direct_functions; + direct_functions =3D new_hash; + + return free_hash; +} + +static struct ftrace_func_entry* +ftrace_add_rec_direct(unsigned long ip, unsigned long addr) +{ + struct ftrace_func_entry *entry; =20 entry =3D kmalloc(sizeof(*entry), GFP_KERNEL); if (!entry) @@ -5436,11 +5441,19 @@ int register_ftrace_direct(struct ftrace_ops *ops, = unsigned long addr) } } =20 + /* ... and prepare the insertion */ + free_hash =3D ftrace_expand_direct(hash->count); + if (IS_ERR(free_hash)) { + err =3D PTR_ERR(free_hash); + free_hash =3D NULL; + goto out_unlock; + } + /* ... and insert them to direct_functions hash. */ err =3D -ENOMEM; for (i =3D 0; i < size; i++) { hlist_for_each_entry(entry, &hash->buckets[i], hlist) { - new =3D ftrace_add_rec_direct(entry->ip, addr, &free_hash); + new =3D ftrace_add_rec_direct(entry->ip, addr); if (!new) goto out_remove; entry->direct =3D addr;