linux-perf-users.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@redhat.com>,
	 Arnaldo Carvalho de Melo <acme@kernel.org>,
	Namhyung Kim <namhyung@kernel.org>,
	 Mark Rutland <mark.rutland@arm.com>,
	 Alexander Shishkin <alexander.shishkin@linux.intel.com>,
	Jiri Olsa <jolsa@kernel.org>,  Ian Rogers <irogers@google.com>,
	Adrian Hunter <adrian.hunter@intel.com>,
	 Kan Liang <kan.liang@linux.intel.com>,
	James Clark <james.clark@linaro.org>,
	 Howard Chu <howardchu95@gmail.com>,
	Athira Jajeev <atrajeev@linux.vnet.ibm.com>,
	 Michael Petlan <mpetlan@redhat.com>,
	Veronika Molnarova <vmolnaro@redhat.com>,
	 Dapeng Mi <dapeng1.mi@linux.intel.com>,
	Thomas Richter <tmricht@linux.ibm.com>,
	 Ilya Leoshkevich <iii@linux.ibm.com>,
	Colin Ian King <colin.i.king@gmail.com>,
	 Weilin Wang <weilin.wang@intel.com>,
	Andi Kleen <ak@linux.intel.com>,
	 Josh Poimboeuf <jpoimboe@redhat.com>,
	linux-kernel@vger.kernel.org,  linux-perf-users@vger.kernel.org
Subject: [PATCH v6 06/22] perf script: Use openat for directory iteration
Date: Fri,  8 Nov 2024 22:17:53 -0800	[thread overview]
Message-ID: <20241109061809.811922-7-irogers@google.com> (raw)
In-Reply-To: <20241109061809.811922-1-irogers@google.com>

Rewrite the directory iteration to use openat so that large character
arrays aren't needed. The arrays are warned about potential buffer
overflows by GCC when the code exists in a single C file.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 tools/perf/builtin-script.c | 87 +++++++++++++++++++++++++------------
 tools/perf/util/path.c      | 10 +++++
 tools/perf/util/path.h      |  1 +
 3 files changed, 71 insertions(+), 27 deletions(-)

diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 5d5a1a06d8c6..e20d55b8a741 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -3530,27 +3530,35 @@ static void free_dlarg(void)
  * which is covered well now. And new parsing code should be added to
  * cover the future complex formats like event groups etc.
  */
-static int check_ev_match(char *dir_name, char *scriptname,
-			struct perf_session *session)
+static int check_ev_match(int dir_fd, const char *scriptname, struct perf_session *session)
 {
-	char filename[MAXPATHLEN], evname[128];
-	char line[BUFSIZ], *p;
-	struct evsel *pos;
-	int match, len;
+	char line[BUFSIZ];
 	FILE *fp;
 
-	scnprintf(filename, MAXPATHLEN, "%s/bin/%s-record", dir_name, scriptname);
+	{
+		char filename[FILENAME_MAX + 5];
+		int fd;
 
-	fp = fopen(filename, "r");
-	if (!fp)
-		return -1;
+		scnprintf(filename, sizeof(filename), "bin/%s-record", scriptname);
+		fd = openat(dir_fd, filename, O_RDONLY);
+		if (fd == -1)
+			return -1;
+		fp = fdopen(fd, "r");
+		if (!fp)
+			return -1;
+	}
 
 	while (fgets(line, sizeof(line), fp)) {
-		p = skip_spaces(line);
+		char *p = skip_spaces(line);
+
 		if (*p == '#')
 			continue;
 
 		while (strlen(p)) {
+			int match, len;
+			struct evsel *pos;
+			char evname[128];
+
 			p = strstr(p, "-e");
 			if (!p)
 				break;
@@ -3593,7 +3601,7 @@ int find_scripts(char **scripts_array, char **scripts_path_array, int num,
 		 int pathlen)
 {
 	struct dirent *script_dirent, *lang_dirent;
-	char scripts_path[MAXPATHLEN], lang_path[MAXPATHLEN];
+	int scripts_dir_fd, lang_dir_fd;
 	DIR *scripts_dir, *lang_dir;
 	struct perf_session *session;
 	struct perf_data data = {
@@ -3602,51 +3610,76 @@ int find_scripts(char **scripts_array, char **scripts_path_array, int num,
 	};
 	char *temp;
 	int i = 0;
+	const char *exec_path = get_argv_exec_path();
 
 	session = perf_session__new(&data, NULL);
 	if (IS_ERR(session))
 		return PTR_ERR(session);
 
-	snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
+	{
+		char scripts_path[PATH_MAX];
 
-	scripts_dir = opendir(scripts_path);
+		snprintf(scripts_path, sizeof(scripts_path), "%s/scripts", exec_path);
+		scripts_dir_fd = open(scripts_path, O_DIRECTORY);
+		pr_err("Failed to open directory '%s'", scripts_path);
+		if (scripts_dir_fd == -1) {
+			perf_session__delete(session);
+			return -1;
+		}
+	}
+	scripts_dir = fdopendir(scripts_dir_fd);
 	if (!scripts_dir) {
+		close(scripts_dir_fd);
 		perf_session__delete(session);
 		return -1;
 	}
 
-	for_each_lang(scripts_path, scripts_dir, lang_dirent) {
-		scnprintf(lang_path, MAXPATHLEN, "%s/%s", scripts_path,
-			  lang_dirent->d_name);
+	while ((lang_dirent = readdir(scripts_dir)) != NULL) {
+		if (lang_dirent->d_type != DT_DIR &&
+		    (lang_dirent->d_type == DT_UNKNOWN &&
+		     !is_directory_at(scripts_dir_fd, lang_dirent->d_name)))
+			continue;
+		if (!strcmp(lang_dirent->d_name, ".") || !strcmp(lang_dirent->d_name, ".."))
+			continue;
+
 #ifndef HAVE_LIBPERL_SUPPORT
-		if (strstr(lang_path, "perl"))
+		if (strstr(lang_dirent->d_name, "perl"))
 			continue;
 #endif
 #ifndef HAVE_LIBPYTHON_SUPPORT
-		if (strstr(lang_path, "python"))
+		if (strstr(lang_dirent->d_name, "python"))
 			continue;
 #endif
 
-		lang_dir = opendir(lang_path);
-		if (!lang_dir)
+		lang_dir_fd = openat(scripts_dir_fd, lang_dirent->d_name, O_DIRECTORY);
+		if (lang_dir_fd == -1)
 			continue;
-
-		for_each_script(lang_path, lang_dir, script_dirent) {
+		lang_dir = fdopendir(lang_dir_fd);
+		if (!lang_dir) {
+			close(lang_dir_fd);
+			continue;
+		}
+		while ((script_dirent = readdir(lang_dir)) != NULL) {
+			if (script_dirent->d_type == DT_DIR)
+				continue;
+			if (script_dirent->d_type == DT_UNKNOWN &&
+			    is_directory_at(lang_dir_fd, script_dirent->d_name))
+				continue;
 			/* Skip those real time scripts: xxxtop.p[yl] */
 			if (strstr(script_dirent->d_name, "top."))
 				continue;
 			if (i >= num)
 				break;
-			snprintf(scripts_path_array[i], pathlen, "%s/%s",
-				lang_path,
+			scnprintf(scripts_path_array[i], pathlen, "%s/scripts/%s/%s",
+				exec_path,
+				lang_dirent->d_name,
 				script_dirent->d_name);
 			temp = strchr(script_dirent->d_name, '.');
 			snprintf(scripts_array[i],
 				(temp - script_dirent->d_name) + 1,
 				"%s", script_dirent->d_name);
 
-			if (check_ev_match(lang_path,
-					scripts_array[i], session))
+			if (check_ev_match(lang_dir_fd, scripts_array[i], session))
 				continue;
 
 			i++;
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 00adf872bf00..9712466c51e2 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -68,6 +68,16 @@ bool is_directory(const char *base_path, const struct dirent *dent)
 	return S_ISDIR(st.st_mode);
 }
 
+bool is_directory_at(int dir_fd, const char *path)
+{
+	struct stat st;
+
+	if (fstatat(dir_fd, path, &st, /*flags=*/0))
+		return false;
+
+	return S_ISDIR(st.st_mode);
+}
+
 bool is_executable_file(const char *base_path, const struct dirent *dent)
 {
 	char path[PATH_MAX];
diff --git a/tools/perf/util/path.h b/tools/perf/util/path.h
index d94902c22222..fbafbe7015dd 100644
--- a/tools/perf/util/path.h
+++ b/tools/perf/util/path.h
@@ -12,6 +12,7 @@ int path__join3(char *bf, size_t size, const char *path1, const char *path2, con
 
 bool is_regular_file(const char *file);
 bool is_directory(const char *base_path, const struct dirent *dent);
+bool is_directory_at(int dir_fd, const char *path);
 bool is_executable_file(const char *base_path, const struct dirent *dent);
 
 #endif /* _PERF_PATH_H */
-- 
2.47.0.277.g8800431eea-goog


  parent reply	other threads:[~2024-11-09  6:18 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-09  6:17 [PATCH v6 00/22] Python module cleanup Ian Rogers
2024-11-09  6:17 ` [PATCH v6 01/22] perf python: Remove python 2 scripting support Ian Rogers
2024-11-09  6:17 ` [PATCH v6 02/22] perf python: Constify variables and parameters Ian Rogers
2024-11-09  6:17 ` [PATCH v6 03/22] perf python: Remove unused #include Ian Rogers
2024-11-09  6:17 ` [PATCH v6 04/22] perf script: Move scripting_max_stack out of builtin Ian Rogers
2024-11-09  6:17 ` [PATCH v6 05/22] perf kvm: Move functions used in util " Ian Rogers
2024-11-09  6:17 ` Ian Rogers [this message]
2024-11-19  0:25   ` [PATCH v6 06/22] perf script: Use openat for directory iteration Namhyung Kim
2024-11-09  6:17 ` [PATCH v6 07/22] perf script: Move find_scripts to browser/scripts.c Ian Rogers
2024-11-19  0:26   ` Namhyung Kim
2024-11-09  6:17 ` [PATCH v6 08/22] perf stat: Move stat_config into config.c Ian Rogers
2024-11-09  6:17 ` [PATCH v6 09/22] perf script: Move script_spec code to trace-event-scripting.c Ian Rogers
2024-11-09  6:17 ` [PATCH v6 10/22] perf script: Move script_fetch_insn " Ian Rogers
2024-11-09  6:17 ` [PATCH v6 11/22] perf script: Move perf_sample__sprintf_flags " Ian Rogers
2024-11-09  6:17 ` [PATCH v6 12/22] perf x86: Define arch_fetch_insn in NO_AUXTRACE builds Ian Rogers
2024-11-09  6:18 ` [PATCH v6 13/22] perf intel-pt: Remove stale build comment Ian Rogers
2024-11-09  6:18 ` [PATCH v6 14/22] perf env: Move arch errno function to only use in env Ian Rogers
2024-11-09  6:18 ` [PATCH v6 15/22] perf lock: Move common lock contention code to new file Ian Rogers
2024-11-19  0:23   ` Namhyung Kim
2024-11-19  1:03     ` Ian Rogers
2024-11-19 17:00       ` Namhyung Kim
2024-11-19 17:21         ` Ian Rogers
2024-11-09  6:18 ` [PATCH v6 16/22] perf bench: Remove reference to cmd_inject Ian Rogers
2024-11-09  6:18 ` [PATCH v6 17/22] perf kwork: Make perf_kwork_add_work a callback Ian Rogers
2024-11-09  6:18 ` [PATCH v6 18/22] perf build: Remove test library from python shared object Ian Rogers
2024-11-09  6:18 ` [PATCH v6 19/22] perf python: Add parse_events function Ian Rogers
2024-11-09  6:18 ` [PATCH v6 20/22] perf python: Add __str__ and __repr__ functions to evlist Ian Rogers
2024-11-09  6:18 ` [PATCH v6 21/22] perf python: Add __str__ and __repr__ functions to evsel Ian Rogers
2024-11-09  6:18 ` [PATCH v6 22/22] perf python: Correctly throw IndexError Ian Rogers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241109061809.811922-7-irogers@google.com \
    --to=irogers@google.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=ak@linux.intel.com \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=atrajeev@linux.vnet.ibm.com \
    --cc=colin.i.king@gmail.com \
    --cc=dapeng1.mi@linux.intel.com \
    --cc=howardchu95@gmail.com \
    --cc=iii@linux.ibm.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=jpoimboe@redhat.com \
    --cc=kan.liang@linux.intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=mpetlan@redhat.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    --cc=tmricht@linux.ibm.com \
    --cc=vmolnaro@redhat.com \
    --cc=weilin.wang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).