linux-trace-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] libtracecmd: Support changing /proc/kallsyms
@ 2025-04-16 23:13 Ilya Leoshkevich
  2025-05-14  7:51 ` Ilya Leoshkevich
  2025-05-30 20:45 ` Steven Rostedt
  0 siblings, 2 replies; 6+ messages in thread
From: Ilya Leoshkevich @ 2025-04-16 23:13 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: linux-trace-devel, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Ilya Leoshkevich

Running BPF selftests under trace-cmd intermittently fails with:

    error in size of file '/proc/kallsyms'

This is because these selftests load and unload BPF programs.
bpf_prog_put() uses workqueues and RCU, so these programs disappear
from /proc/kallsyms after a delay.

trace-cmd reads /proc/kallsyms twice: the first time to compute its
size, and the second time to copy it into the trace file. If the
resulting sizes don't match, which is what happens in this case,
recording fails.

Fix by first copying /proc/kallsyms into a temporary file, and then
into the trace file. An alternative would be to read it into a
malloc()-ed buffer, but this would increase trace-cmd memory usage,
since /proc/kallsyms can be a few dozen megabytes large. In case
/tmp is tmpfs, both solutions are almost equivalent.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 lib/trace-cmd/trace-output.c | 66 ++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 14 deletions(-)

diff --git a/lib/trace-cmd/trace-output.c b/lib/trace-cmd/trace-output.c
index 00b87a19..d85021be 100644
--- a/lib/trace-cmd/trace-output.c
+++ b/lib/trace-cmd/trace-output.c
@@ -1129,14 +1129,52 @@ err:
 		tracecmd_warning("can't set kptr_restrict");
 }
 
+static int copy_to_temp_fd(const char *path, tsize_t *size)
+{
+	char temp_path[] = "/tmp/trace_XXXXXX";
+	char buf[BUFSIZ];
+	int fd, temp_fd;
+	stsize_t r;
+
+	fd = open(path, O_RDONLY);
+	if (fd < 0)
+		goto fail;
+
+	temp_fd = mkstemp(temp_path);
+	if (temp_fd < 0)
+		goto fail_close;
+	unlink(temp_path);
+
+	*size = 0;
+	for (;;) {
+		r = read(fd, buf, sizeof(buf));
+		if (r == 0)
+			break;
+		if (r < 0 || __do_write_check(temp_fd, buf, r))
+			goto fail_close_temp;
+		*size += r;
+	}
+
+	if (lseek(temp_fd, 0, SEEK_SET) == (off_t)-1)
+		goto fail_close_temp;
+
+	close(fd);
+	return temp_fd;
+
+fail_close_temp:
+	close(temp_fd);
+fail_close:
+	close(fd);
+fail:
+	return -1;
+}
+
 static int read_proc_kallsyms(struct tracecmd_output *handle, bool compress)
 {
 	enum tracecmd_section_flags flags = 0;
-	unsigned int size, check_size, endian4;
 	const char *path = "/proc/kallsyms";
-	tsize_t offset;
-	struct stat st;
-	int ret;
+	tsize_t check_size, offset, size;
+	int endian4, fd, ret;
 
 	if (!tcmd_check_out_state(handle, TRACECMD_FILE_KALLSYMS)) {
 		tracecmd_warning("Cannot read kallsyms, unexpected state 0x%X",
@@ -1155,36 +1193,36 @@ static int read_proc_kallsyms(struct tracecmd_output *handle, bool compress)
 		return -1;
 
 	tcmd_out_compression_start(handle, compress);
-	ret = stat(path, &st);
-	if (ret < 0) {
+	set_proc_kptr_restrict(0);
+	fd = copy_to_temp_fd(path, &size);
+	set_proc_kptr_restrict(1);
+	if (fd < 0) {
 		/* not found */
 		size = 0;
 		endian4 = convert_endian_4(handle, size);
 		ret = tcmd_do_write_check(handle, &endian4, 4);
 		goto out;
 	}
-	size = get_size(path);
 	endian4 = convert_endian_4(handle, size);
 	ret = tcmd_do_write_check(handle, &endian4, 4);
 	if (ret)
-		goto out;
+		goto out_close;
 
-	set_proc_kptr_restrict(0);
-	check_size = copy_file(handle, path);
+	check_size = copy_file_fd(handle, fd, 0);
 	if (size != check_size) {
 		errno = EINVAL;
 		tracecmd_warning("error in size of file '%s'", path);
-		set_proc_kptr_restrict(1);
 		ret = -1;
-		goto out;
+		goto out_close;
 	}
-	set_proc_kptr_restrict(1);
 
 	ret = tcmd_out_compression_end(handle, compress);
 	if (ret)
-		goto out;
+		goto out_close;
 
 	ret = tcmd_out_update_section_header(handle, offset);
+out_close:
+	close(fd);
 out:
 	if (!ret)
 		handle->file_state = TRACECMD_FILE_KALLSYMS;
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2025-06-02 15:18 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-16 23:13 [PATCH] libtracecmd: Support changing /proc/kallsyms Ilya Leoshkevich
2025-05-14  7:51 ` Ilya Leoshkevich
2025-05-14 13:45   ` Steven Rostedt
2025-05-30 20:45 ` Steven Rostedt
2025-06-02 15:05   ` Ilya Leoshkevich
2025-06-02 15:19     ` Steven Rostedt

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).