mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] tools/mm: prevent page_owner_sort from truncating input
@ 2026-07-29  5:38 Warren Xiong
  2026-07-30  0:31 ` Andrew Morton
  2026-07-30  1:58 ` [PATCH v2] " Warren Xiong
  0 siblings, 2 replies; 5+ messages in thread
From: Warren Xiong @ 2026-07-29  5:38 UTC (permalink / raw)
  To: Andrew Morton; +Cc: linux-mm, linux-kernel, Warren Xiong

page_owner_sort opens the output file with "w" before reading the input.
If both paths refer to the same file, this truncates the input and the
tool silently processes zero records before returning success.

Open the output without truncating it and compare the device and inode
numbers of the opened files. Reject matching regular files, then truncate
regular output files only after the check. This also detects hard link and
symbolic link aliases while preserving non-regular outputs such as
/dev/stdout.

Signed-off-by: Warren Xiong <warren.xiong@ugreen.com>
---
 tools/mm/page_owner_sort.c | 41 ++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/tools/mm/page_owner_sort.c b/tools/mm/page_owner_sort.c
index 35d3d2549..602f541d8 100644
--- a/tools/mm/page_owner_sort.c
+++ b/tools/mm/page_owner_sort.c
@@ -713,7 +713,8 @@ int main(int argc, char **argv)
 	FILE *fin, *fout;
 	char *buf, *ext_buf;
 	int i, count, compare_flag;
-	struct stat st;
+	int fout_fd;
+	struct stat st, output_st;
 	int opt;
 	struct option longopts[] = {
 		{ "pid", required_argument, NULL, 1 },
@@ -836,13 +837,46 @@ int main(int argc, char **argv)
 	}
 
 	fin = fopen(argv[optind], "r");
-	fout = fopen(argv[optind + 1], "w");
-	if (!fin || !fout) {
+	if (!fin) {
 		usage();
 		perror("open: ");
 		exit(1);
 	}
 
+	if (fstat(fileno(fin), &st)) {
+		perror("fstat input");
+		exit(1);
+	}
+
+	/*
+	 * Do not truncate the output until after checking whether it refers
+	 * to the input file.  Comparing the opened files also catches aliases
+	 * created with hard links or symbolic links.
+	 */
+	fout_fd = open(argv[optind + 1], O_WRONLY | O_CREAT, 0666);
+	if (fout_fd < 0) {
+		perror("open output");
+		exit(1);
+	}
+	if (fstat(fout_fd, &output_st)) {
+		perror("fstat output");
+		exit(1);
+	}
+	if (S_ISREG(st.st_mode) && S_ISREG(output_st.st_mode) &&
+	    st.st_dev == output_st.st_dev && st.st_ino == output_st.st_ino) {
+		fprintf(stderr, "Input and output files must be different\n");
+		exit(1);
+	}
+	if (S_ISREG(output_st.st_mode) && ftruncate(fout_fd, 0)) {
+		perror("truncate output");
+		exit(1);
+	}
+	fout = fdopen(fout_fd, "w");
+	if (!fout) {
+		perror("fdopen output");
+		exit(1);
+	}
+
 	if (!check_regcomp(&order_pattern, "order\\s*([0-9]*),"))
 		goto out_order;
 	if (!check_regcomp(&pid_pattern, "pid\\s*([0-9]*),"))
@@ -854,7 +888,6 @@ int main(int argc, char **argv)
 	if (!check_regcomp(&ts_nsec_pattern, "ts\\s*([0-9]*)\\s*ns"))
 		goto out_ts;
 
-	fstat(fileno(fin), &st);
 	max_size = st.st_size / 100; /* hack ... */
 
 	list = malloc(max_size * sizeof(*list));
-- 
2.39.5


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

end of thread, other threads:[~2026-07-30 20:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-29  5:38 [PATCH] tools/mm: prevent page_owner_sort from truncating input Warren Xiong
2026-07-30  0:31 ` Andrew Morton
2026-07-30  1:30   ` 熊卧龙
2026-07-30  1:58 ` [PATCH v2] " Warren Xiong
2026-07-30 20:45   ` Andrew Morton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®